From 66d0c35ae5b52492d9c53567d34fed3eab882305 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Fri, 3 Feb 2023 14:02:48 +0530 Subject: [PATCH 01/22] Download external dependencies to external directory --- Cargo.lock | 175 +- Cargo.toml | 16 + external/nimbus-consensus/Cargo.toml | 39 + external/nimbus-consensus/src/import_queue.rs | 275 + external/nimbus-consensus/src/lib.rs | 443 + external/nimbus-consensus/src/manual_seal.rs | 131 + external/nimbus-primitives/Cargo.toml | 40 + external/nimbus-primitives/src/digests.rs | 80 + external/nimbus-primitives/src/inherents.rs | 52 + external/nimbus-primitives/src/lib.rs | 185 + external/pallets/author-inherent/Cargo.toml | 53 + .../pallets/author-inherent/src/benchmarks.rs | 30 + external/pallets/author-inherent/src/exec.rs | 99 + external/pallets/author-inherent/src/lib.rs | 247 + external/pallets/author-inherent/src/mock.rs | 113 + external/pallets/author-inherent/src/tests.rs | 72 + .../pallets/author-inherent/src/weights.rs | 91 + external/pallets/author-mapping/Cargo.toml | 50 + external/pallets/author-mapping/migrations.md | 10 + .../pallets/author-mapping/src/benchmarks.rs | 160 + external/pallets/author-mapping/src/lib.rs | 403 + .../pallets/author-mapping/src/migrations.rs | 183 + external/pallets/author-mapping/src/mock.rs | 191 + external/pallets/author-mapping/src/tests.rs | 480 + .../pallets/author-mapping/src/weights.rs | 159 + .../pallets/author-slot-filter/Cargo.toml | 45 + .../author-slot-filter/src/benchmarks.rs | 50 + .../pallets/author-slot-filter/src/lib.rs | 227 + .../author-slot-filter/src/migration.rs | 102 + .../pallets/author-slot-filter/src/mock.rs | 92 + .../pallets/author-slot-filter/src/num.rs | 127 + .../pallets/author-slot-filter/src/tests.rs | 98 + .../pallets/author-slot-filter/src/weights.rs | 71 + external/pallets/parachain-staking/Cargo.toml | 45 + external/pallets/parachain-staking/README.md | 26 + .../pallets/parachain-staking/migrations.md | 42 + .../parachain-staking/src/auto_compound.rs | 377 + .../parachain-staking/src/benchmarks.rs | 1502 +++ .../src/delegation_requests.rs | 704 ++ .../parachain-staking/src/inflation.rs | 228 + external/pallets/parachain-staking/src/lib.rs | 1926 ++++ .../parachain-staking/src/migrations.rs | 182 + .../pallets/parachain-staking/src/mock.rs | 1061 ++ external/pallets/parachain-staking/src/set.rs | 89 + .../pallets/parachain-staking/src/tests.rs | 9025 +++++++++++++++++ .../pallets/parachain-staking/src/traits.rs | 66 + .../pallets/parachain-staking/src/types.rs | 1757 ++++ .../pallets/parachain-staking/src/weights.rs | 903 ++ external/session-keys/Cargo.toml | 42 + external/session-keys/src/digest.rs | 63 + external/session-keys/src/inherent.rs | 76 + external/session-keys/src/lib.rs | 45 + external/session-keys/src/vrf.rs | 100 + external/vrf/Cargo.toml | 27 + external/vrf/src/lib.rs | 75 + node/Cargo.toml | 12 +- runtime/battery-station/Cargo.toml | 12 +- runtime/common/Cargo.toml | 8 +- runtime/common/src/lib.rs | 9 +- runtime/common/src/weights/mod.rs | 4 - runtime/zeitgeist/Cargo.toml | 12 +- 61 files changed, 22968 insertions(+), 39 deletions(-) create mode 100644 external/nimbus-consensus/Cargo.toml create mode 100644 external/nimbus-consensus/src/import_queue.rs create mode 100644 external/nimbus-consensus/src/lib.rs create mode 100644 external/nimbus-consensus/src/manual_seal.rs create mode 100644 external/nimbus-primitives/Cargo.toml create mode 100644 external/nimbus-primitives/src/digests.rs create mode 100644 external/nimbus-primitives/src/inherents.rs create mode 100644 external/nimbus-primitives/src/lib.rs create mode 100644 external/pallets/author-inherent/Cargo.toml create mode 100644 external/pallets/author-inherent/src/benchmarks.rs create mode 100644 external/pallets/author-inherent/src/exec.rs create mode 100644 external/pallets/author-inherent/src/lib.rs create mode 100644 external/pallets/author-inherent/src/mock.rs create mode 100644 external/pallets/author-inherent/src/tests.rs create mode 100644 external/pallets/author-inherent/src/weights.rs create mode 100644 external/pallets/author-mapping/Cargo.toml create mode 100644 external/pallets/author-mapping/migrations.md create mode 100644 external/pallets/author-mapping/src/benchmarks.rs create mode 100644 external/pallets/author-mapping/src/lib.rs create mode 100644 external/pallets/author-mapping/src/migrations.rs create mode 100644 external/pallets/author-mapping/src/mock.rs create mode 100644 external/pallets/author-mapping/src/tests.rs create mode 100644 external/pallets/author-mapping/src/weights.rs create mode 100644 external/pallets/author-slot-filter/Cargo.toml create mode 100644 external/pallets/author-slot-filter/src/benchmarks.rs create mode 100644 external/pallets/author-slot-filter/src/lib.rs create mode 100644 external/pallets/author-slot-filter/src/migration.rs create mode 100644 external/pallets/author-slot-filter/src/mock.rs create mode 100644 external/pallets/author-slot-filter/src/num.rs create mode 100644 external/pallets/author-slot-filter/src/tests.rs create mode 100644 external/pallets/author-slot-filter/src/weights.rs create mode 100644 external/pallets/parachain-staking/Cargo.toml create mode 100644 external/pallets/parachain-staking/README.md create mode 100644 external/pallets/parachain-staking/migrations.md create mode 100644 external/pallets/parachain-staking/src/auto_compound.rs create mode 100644 external/pallets/parachain-staking/src/benchmarks.rs create mode 100644 external/pallets/parachain-staking/src/delegation_requests.rs create mode 100644 external/pallets/parachain-staking/src/inflation.rs create mode 100644 external/pallets/parachain-staking/src/lib.rs create mode 100644 external/pallets/parachain-staking/src/migrations.rs create mode 100644 external/pallets/parachain-staking/src/mock.rs create mode 100644 external/pallets/parachain-staking/src/set.rs create mode 100644 external/pallets/parachain-staking/src/tests.rs create mode 100644 external/pallets/parachain-staking/src/traits.rs create mode 100644 external/pallets/parachain-staking/src/types.rs create mode 100644 external/pallets/parachain-staking/src/weights.rs create mode 100644 external/session-keys/Cargo.toml create mode 100644 external/session-keys/src/digest.rs create mode 100644 external/session-keys/src/inherent.rs create mode 100644 external/session-keys/src/lib.rs create mode 100644 external/session-keys/src/vrf.rs create mode 100644 external/vrf/Cargo.toml create mode 100644 external/vrf/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 8383998b6..b9ec0ff78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -431,6 +431,15 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +[[package]] +name = "basic-toml" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e819b667739967cd44d308b8c7b71305d8bb0729ac44a248aa08f33d01950b4" +dependencies = [ + "serde", +] + [[package]] name = "battery-station-runtime" version = "0.3.8" @@ -791,6 +800,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", +] + [[package]] name = "bstr" version = "1.1.0" @@ -1157,6 +1177,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys", +] + [[package]] name = "const-oid" version = "0.7.1" @@ -2035,6 +2067,12 @@ dependencies = [ "syn", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.8.1" @@ -2105,6 +2143,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "dissimilar" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e" + [[package]] name = "dns-parser" version = "0.8.0" @@ -2227,6 +2271,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "enum-as-inner" version = "0.4.0" @@ -2721,6 +2771,40 @@ dependencies = [ "syn", ] +[[package]] +name = "frame-support-test" +version = "3.0.0" +source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +dependencies = [ + "frame-support", + "frame-support-test-pallet", + "frame-system", + "parity-scale-codec", + "pretty_assertions", + "rustversion", + "scale-info", + "serde", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-version", + "trybuild", +] + +[[package]] +name = "frame-support-test-pallet" +version = "4.0.0-dev" +source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "frame-system" version = "4.0.0-dev" @@ -3045,7 +3129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", - "bstr", + "bstr 1.1.0", "fnv", "log", "regex", @@ -4796,7 +4880,6 @@ dependencies = [ [[package]] name = "moonbeam-vrf" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/moonbeam?tag=v0.27.2-a#cf8094af82c8324378f18ac4b4a647cc06705c33" dependencies = [ "nimbus-primitives", "parity-scale-codec", @@ -5009,7 +5092,6 @@ dependencies = [ [[package]] name = "nimbus-consensus" version = "0.9.0" -source = "git+https://github.com/zeitgeistpm/nimbus?branch=moonbeam-polkadot-v0.9.29#9cb2d9280c4f99bf4ea5acbe57b731dfad1c0e23" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -5040,7 +5122,6 @@ dependencies = [ [[package]] name = "nimbus-primitives" version = "0.9.0" -source = "git+https://github.com/zeitgeistpm/nimbus?branch=moonbeam-polkadot-v0.9.29#9cb2d9280c4f99bf4ea5acbe57b731dfad1c0e23" dependencies = [ "async-trait", "frame-benchmarking", @@ -5423,6 +5504,15 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +[[package]] +name = "output_vt100" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" +dependencies = [ + "winapi", +] + [[package]] name = "owning_ref" version = "0.4.1" @@ -5461,10 +5551,10 @@ dependencies = [ [[package]] name = "pallet-author-inherent" version = "0.9.0" -source = "git+https://github.com/zeitgeistpm/nimbus?branch=moonbeam-polkadot-v0.9.29#9cb2d9280c4f99bf4ea5acbe57b731dfad1c0e23" dependencies = [ "frame-benchmarking", "frame-support", + "frame-support-test", "frame-system", "log", "nimbus-primitives", @@ -5473,7 +5563,9 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-authorship", + "sp-core", "sp-inherents", + "sp-io", "sp-runtime", "sp-std", ] @@ -5481,17 +5573,19 @@ dependencies = [ [[package]] name = "pallet-author-mapping" version = "2.0.5" -source = "git+https://github.com/zeitgeistpm/moonbeam?tag=v0.27.2-a#cf8094af82c8324378f18ac4b4a647cc06705c33" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "nimbus-primitives", + "pallet-balances", "parity-scale-codec", "scale-info", "serde", "session-keys-primitives", + "sp-core", + "sp-io", "sp-runtime", "sp-std", ] @@ -5499,10 +5593,10 @@ dependencies = [ [[package]] name = "pallet-author-slot-filter" version = "0.9.0" -source = "git+https://github.com/zeitgeistpm/nimbus?branch=moonbeam-polkadot-v0.9.29#9cb2d9280c4f99bf4ea5acbe57b731dfad1c0e23" dependencies = [ "frame-benchmarking", "frame-support", + "frame-support-test", "frame-system", "log", "nimbus-primitives", @@ -5510,6 +5604,7 @@ dependencies = [ "scale-info", "serde", "sp-core", + "sp-io", "sp-runtime", "sp-std", ] @@ -6012,16 +6107,19 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://github.com/zeitgeistpm/moonbeam?tag=v0.27.2-a#cf8094af82c8324378f18ac4b4a647cc06705c33" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "nimbus-primitives", + "pallet-balances", "parity-scale-codec", "scale-info", "serde", + "similar-asserts", + "sp-core", + "sp-io", "sp-runtime", "sp-std", "substrate-fixed", @@ -7962,6 +8060,18 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pretty_assertions" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +dependencies = [ + "ctor", + "diff", + "output_vt100", + "yansi", +] + [[package]] name = "primitive-types" version = "0.11.1" @@ -10020,7 +10130,6 @@ dependencies = [ [[package]] name = "session-keys-primitives" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/moonbeam?tag=v0.27.2-a#cf8094af82c8324378f18ac4b4a647cc06705c33" dependencies = [ "async-trait", "frame-support", @@ -10153,6 +10262,26 @@ dependencies = [ "paste", ] +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +dependencies = [ + "bstr 0.2.17", + "unicode-segmentation", +] + +[[package]] +name = "similar-asserts" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18" +dependencies = [ + "console", + "similar", +] + [[package]] name = "slab" version = "0.4.7" @@ -11735,6 +11864,22 @@ dependencies = [ "zstd", ] +[[package]] +name = "trybuild" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44da5a6f2164c8e14d3bbc0657d69c5966af9f5f6930d4f600b1f5c4a673413" +dependencies = [ + "basic-toml", + "dissimilar", + "glob", + "once_cell", + "serde", + "serde_derive", + "serde_json", + "termcolor", +] + [[package]] name = "tt-call" version = "1.0.9" @@ -11816,6 +11961,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" @@ -12668,6 +12819,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "zeitgeist-node" version = "0.3.8" diff --git a/Cargo.toml b/Cargo.toml index d38578d8b..98144fe60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,13 @@ [workspace] default-members = [ + "external/nimbus-consensus", + "external/nimbus-primitives", + "external/pallets/author-inherent", + "external/pallets/author-mapping", + "external/pallets/author-slot-filter", + "external/pallets/parachain-staking", + "external/session-keys", + "external/vrf", "node", "primitives", "runtime/common", @@ -21,6 +29,14 @@ default-members = [ "zrml/styx", ] members = [ + "external/nimbus-consensus", + "external/nimbus-primitives", + "external/pallets/author-inherent", + "external/pallets/author-mapping", + "external/pallets/author-slot-filter", + "external/pallets/parachain-staking", + "external/session-keys", + "external/vrf", "node", "primitives", "runtime/common", diff --git a/external/nimbus-consensus/Cargo.toml b/external/nimbus-consensus/Cargo.toml new file mode 100644 index 000000000..a1845ba86 --- /dev/null +++ b/external/nimbus-consensus/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "nimbus-consensus" +description = "Client-side worker for the Nimbus family of consensus algorithms" +edition = "2021" +version = "0.9.0" +[dependencies] +# Substrate deps +sc-client-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sc-consensus = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sc-consensus-manual-seal = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-block-builder = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-blockchain = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-consensus = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-keystore = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +substrate-prometheus-endpoint = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } + +# Polkadot dependencies +polkadot-client = { git = "https://github.com/zeitgeistpm/polkadot", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +# Cumulus dependencies +cumulus-client-consensus-common = { git = "https://github.com/zeitgeistpm/cumulus", branch = "moonbeam-polkadot-v0.9.29" } +cumulus-primitives-core = { git = "https://github.com/zeitgeistpm/cumulus", branch = "moonbeam-polkadot-v0.9.29" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/zeitgeistpm/cumulus", branch = "moonbeam-polkadot-v0.9.29" } + +# Nimbus Dependencies +nimbus-primitives = { path = "../nimbus-primitives" } + +# Other deps +async-trait = "0.1" +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } +futures = { version = "0.3.24", features = [ "compat" ] } +log = "0.4.17" +parking_lot = "0.12" +tracing = "0.1.22" diff --git a/external/nimbus-consensus/src/import_queue.rs b/external/nimbus-consensus/src/import_queue.rs new file mode 100644 index 000000000..54c407104 --- /dev/null +++ b/external/nimbus-consensus/src/import_queue.rs @@ -0,0 +1,275 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use std::{marker::PhantomData, sync::Arc}; + +use log::debug; +use nimbus_primitives::{digests::CompatibleDigestItem, NimbusId, NimbusPair, NIMBUS_ENGINE_ID}; +use sc_consensus::{ + import_queue::{BasicQueue, Verifier as VerifierT}, + BlockImport, BlockImportParams, +}; +use sp_api::ProvideRuntimeApi; +use sp_application_crypto::{ByteArray, Pair as _}; +use sp_block_builder::BlockBuilder as BlockBuilderApi; +use sp_blockchain::Result as ClientResult; +use sp_consensus::{error::Error as ConsensusError, CacheKeyId}; +use sp_inherents::{CreateInherentDataProviders, InherentDataProvider}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, Header as HeaderT}, + DigestItem, +}; + +/// The Nimbus verifier strips the seal digest, and checks that it is a valid signature by +/// the same key that was injected into the runtime and noted in the Seal digest. +/// From Nimbu's perspective any block that faithfully reports its authorship to the runtime +/// is valid. The intention is that the runtime itself may then put further restrictions on +/// the identity of the author. +struct Verifier { + client: Arc, + create_inherent_data_providers: CIDP, + _marker: PhantomData, +} + +#[async_trait::async_trait] +impl VerifierT for Verifier +where + Block: BlockT, + Client: ProvideRuntimeApi + Send + Sync, + >::Api: BlockBuilderApi, + CIDP: CreateInherentDataProviders, +{ + async fn verify( + &mut self, + mut block_params: BlockImportParams, + ) -> Result< + ( + BlockImportParams, + Option)>>, + ), + String, + > { + debug!( + target: crate::LOG_TARGET, + "🪲 Header hash before popping digest {:?}", + block_params.header.hash() + ); + // Grab the seal digest. Assume it is last (since it is a seal after-all). + let seal = block_params + .header + .digest_mut() + .pop() + .expect("Block should have at least one digest on it"); + + let signature = seal + .as_nimbus_seal() + .ok_or_else(|| String::from("HeaderUnsealed"))?; + + debug!( + target: crate::LOG_TARGET, + "🪲 Header hash after popping digest {:?}", + block_params.header.hash() + ); + + debug!( + target: crate::LOG_TARGET, + "🪲 Signature according to verifier is {:?}", signature + ); + + // Grab the author information from either the preruntime digest or the consensus digest + //TODO use the trait + let claimed_author = block_params + .header + .digest() + .logs + .iter() + .find_map(|digest| match *digest { + DigestItem::Consensus(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + _ => None, + }) + .expect("Expected one consensus or pre-runtime digest that contains author id bytes"); + + debug!( + target: crate::LOG_TARGET, + "🪲 Claimed Author according to verifier is {:?}", claimed_author + ); + + // Verify the signature + let valid_signature = NimbusPair::verify( + &signature, + block_params.header.hash(), + &NimbusId::from_slice(&claimed_author) + .map_err(|_| "Invalid Nimbus ID (wrong length)")?, + ); + + debug!( + target: crate::LOG_TARGET, + "🪲 Valid signature? {:?}", valid_signature + ); + + if !valid_signature { + return Err("Block signature invalid".into()); + } + + // This part copied from RelayChainConsensus. I guess this is the inherent checking. + if let Some(inner_body) = block_params.body.take() { + let inherent_data_providers = self + .create_inherent_data_providers + .create_inherent_data_providers(*block_params.header.parent_hash(), ()) + .await + .map_err(|e| e.to_string())?; + + let inherent_data = inherent_data_providers + .create_inherent_data() + .map_err(|e| format!("{:?}", e))?; + + let block = Block::new(block_params.header.clone(), inner_body); + + let inherent_res = self + .client + .runtime_api() + .check_inherents( + &BlockId::Hash(*block_params.header.parent_hash()), + block.clone(), + inherent_data, + ) + .map_err(|e| format!("{:?}", e))?; + + if !inherent_res.ok() { + for (i, e) in inherent_res.into_errors() { + match inherent_data_providers.try_handle_error(&i, &e).await { + Some(r) => r.map_err(|e| format!("{:?}", e))?, + None => Err(format!( + "Unhandled inherent error from `{}`.", + String::from_utf8_lossy(&i) + ))?, + } + } + } + + let (_, inner_body) = block.deconstruct(); + block_params.body = Some(inner_body); + } + + block_params.post_digests.push(seal); + + // The standard is to use the longest chain rule. This is overridden by the `NimbusBlockImport` in the parachain context. + block_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::LongestChain); + + debug!( + target: crate::LOG_TARGET, + "🪲 Just finished verifier. posthash from params is {:?}", + &block_params.post_hash() + ); + + Ok((block_params, None)) + } +} + +/// Start an import queue for a Cumulus collator that does not uses any special authoring logic. +pub fn import_queue( + client: Arc, + block_import: I, + create_inherent_data_providers: CIDP, + spawner: &impl sp_core::traits::SpawnEssentialNamed, + registry: Option<&substrate_prometheus_endpoint::Registry>, + parachain: bool, +) -> ClientResult> +where + I: BlockImport + Send + Sync + 'static, + I::Transaction: Send, + Client: ProvideRuntimeApi + Send + Sync + 'static, + >::Api: BlockBuilderApi, + CIDP: CreateInherentDataProviders + 'static, +{ + let verifier = Verifier { + client, + create_inherent_data_providers, + _marker: PhantomData, + }; + + Ok(BasicQueue::new( + verifier, + Box::new(NimbusBlockImport::new(block_import, parachain)), + None, + spawner, + registry, + )) +} + +/// Nimbus specific block import. +/// +/// Nimbus supports both parachain and non-parachain contexts. In the parachain +/// context, new blocks should not be imported as best. Cumulus's ParachainBlockImport +/// handles this correctly, but does not work in non-parachain contexts. +/// This block import has a field indicating whether we should apply parachain rules or not. +/// +/// There may be additional nimbus-specific logic here in the future, but for now it is +/// only the conditional parachain logic +pub struct NimbusBlockImport { + inner: I, + parachain_context: bool, +} + +impl NimbusBlockImport { + /// Create a new instance. + pub fn new(inner: I, parachain_context: bool) -> Self { + Self { + inner, + parachain_context, + } + } +} + +#[async_trait::async_trait] +impl BlockImport for NimbusBlockImport +where + Block: BlockT, + I: BlockImport + Send, +{ + type Error = I::Error; + type Transaction = I::Transaction; + + async fn check_block( + &mut self, + block: sc_consensus::BlockCheckParams, + ) -> Result { + self.inner.check_block(block).await + } + + async fn import_block( + &mut self, + mut block_import_params: sc_consensus::BlockImportParams, + cache: std::collections::HashMap>, + ) -> Result { + // If we are in the parachain context, best block is determined by the relay chain + // except during initial sync + if self.parachain_context { + block_import_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::Custom( + block_import_params.origin == sp_consensus::BlockOrigin::NetworkInitialSync, + )); + } + + // Now continue on to the rest of the import pipeline. + self.inner.import_block(block_import_params, cache).await + } +} diff --git a/external/nimbus-consensus/src/lib.rs b/external/nimbus-consensus/src/lib.rs new file mode 100644 index 000000000..8392f3056 --- /dev/null +++ b/external/nimbus-consensus/src/lib.rs @@ -0,0 +1,443 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! The nimbus consensus client-side worker +//! +//! It queries the in-runtime filter to determine whether any keys +//! stored in its keystore are eligible to author at this slot. If it has an eligible +//! key it authors. + +use cumulus_client_consensus_common::{ + ParachainBlockImport, ParachainCandidate, ParachainConsensus, +}; +use cumulus_primitives_core::{relay_chain::v2::Hash as PHash, ParaId, PersistedValidationData}; +pub use import_queue::import_queue; +use log::{debug, info, warn}; +use nimbus_primitives::{ + CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_KEY_ID, +}; +use parking_lot::Mutex; +use sc_consensus::{BlockImport, BlockImportParams}; +use sp_api::{BlockId, ProvideRuntimeApi}; +use sp_application_crypto::{ByteArray, CryptoTypePublicPair}; +use sp_consensus::{ + BlockOrigin, EnableProofRecording, Environment, ProofRecording, Proposal, Proposer, +}; +use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; +use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; +use sp_runtime::{ + traits::{Block as BlockT, Header as HeaderT}, + DigestItem, +}; +use std::convert::TryInto; +use std::{marker::PhantomData, sync::Arc, time::Duration}; +use tracing::error; +mod import_queue; +mod manual_seal; +pub use manual_seal::NimbusManualSealConsensusDataProvider; + +const LOG_TARGET: &str = "filtering-consensus"; + +/// The implementation of the relay-chain provided consensus for parachains. +pub struct NimbusConsensus { + para_id: ParaId, + proposer_factory: Arc>, + create_inherent_data_providers: Arc, + block_import: Arc>>, + parachain_client: Arc, + keystore: SyncCryptoStorePtr, + skip_prediction: bool, + additional_digests_provider: Arc, + _phantom: PhantomData, +} + +impl Clone for NimbusConsensus { + fn clone(&self) -> Self { + Self { + para_id: self.para_id, + proposer_factory: self.proposer_factory.clone(), + create_inherent_data_providers: self.create_inherent_data_providers.clone(), + block_import: self.block_import.clone(), + parachain_client: self.parachain_client.clone(), + keystore: self.keystore.clone(), + skip_prediction: self.skip_prediction, + additional_digests_provider: self.additional_digests_provider.clone(), + _phantom: PhantomData, + } + } +} + +impl NimbusConsensus +where + B: BlockT, + PF: 'static, + BI: 'static, + ParaClient: ProvideRuntimeApi + 'static, + CIDP: CreateInherentDataProviders + 'static, + DP: DigestsProvider::Hash> + 'static, +{ + /// Create a new instance of nimbus consensus. + pub fn build( + BuildNimbusConsensusParams { + para_id, + proposer_factory, + create_inherent_data_providers, + block_import, + parachain_client, + keystore, + skip_prediction, + additional_digests_provider, + }: BuildNimbusConsensusParams, + ) -> Box> + where + Self: ParachainConsensus, + { + Box::new(Self { + para_id, + proposer_factory: Arc::new(Mutex::new(proposer_factory)), + create_inherent_data_providers: Arc::new(create_inherent_data_providers), + block_import: Arc::new(futures::lock::Mutex::new(ParachainBlockImport::new( + block_import, + ))), + parachain_client, + keystore, + skip_prediction, + additional_digests_provider: Arc::new(additional_digests_provider), + _phantom: PhantomData, + }) + } + + //TODO Could this be a provided implementation now that we have this async inherent stuff? + /// Create the data. + async fn inherent_data( + &self, + parent: B::Hash, + validation_data: &PersistedValidationData, + relay_parent: PHash, + author_id: NimbusId, + ) -> Option { + let inherent_data_providers = self + .create_inherent_data_providers + .create_inherent_data_providers( + parent, + (relay_parent, validation_data.clone(), author_id), + ) + .await + .map_err(|e| { + tracing::error!( + target: LOG_TARGET, + error = ?e, + "Failed to create inherent data providers.", + ) + }) + .ok()?; + + inherent_data_providers + .create_inherent_data() + .map_err(|e| { + tracing::error!( + target: LOG_TARGET, + error = ?e, + "Failed to create inherent data.", + ) + }) + .ok() + } +} + +/// Grabs any available nimbus key from the keystore. +/// This may be useful in situations where you expect exactly one key +/// and intend to perform an operation with it regardless of whether it is +/// expected to be eligible. Concretely, this is used in the consensus worker +/// to implement the `skip_prediction` feature. +pub(crate) fn first_available_key(keystore: &dyn SyncCryptoStore) -> Option { + // Get all the available keys + let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) + .expect("keystore should return the keys it has"); + + // Print a more helpful message than "not eligible" when there are no keys at all. + if available_keys.is_empty() { + warn!( + target: LOG_TARGET, + "🔏 No Nimbus keys available. We will not be able to author." + ); + return None; + } + + Some(available_keys[0].clone()) +} + +/// Grab the first eligible nimbus key from the keystore +/// If multiple keys are eligible this function still only returns one +/// and makes no guarantees which one as that depends on the keystore's iterator behavior. +/// This is the standard way of determining which key to author with. +pub(crate) fn first_eligible_key( + client: Arc, + keystore: &dyn SyncCryptoStore, + parent: &B::Header, + slot_number: u32, +) -> Option +where + C: ProvideRuntimeApi, + C::Api: NimbusApi, +{ + // Get all the available keys + let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) + .expect("keystore should return the keys it has"); + + // Print a more helpful message than "not eligible" when there are no keys at all. + if available_keys.is_empty() { + warn!( + target: LOG_TARGET, + "🔏 No Nimbus keys available. We will not be able to author." + ); + return None; + } + + let at = BlockId::Hash(parent.hash()); + + // Iterate keys until we find an eligible one, or run out of candidates. + // If we are skipping prediction, then we author with the first key we find. + // prediction skipping only really makes sense when there is a single key in the keystore. + let maybe_key = available_keys.into_iter().find(|type_public_pair| { + // Have to convert to a typed NimbusId to pass to the runtime API. Maybe this is a clue + // That I should be passing Vec across the wasm boundary? + NimbusApi::can_author( + &*client.runtime_api(), + &at, + NimbusId::from_slice(&type_public_pair.1).expect("Provided keys should be valid"), + slot_number, + parent, + ) + .expect("NimbusAPI should not return error") + }); + + // If there are no eligible keys, print the log, and exit early. + if maybe_key.is_none() { + info!( + target: LOG_TARGET, + "🔮 Skipping candidate production because we are not eligible for slot {}", slot_number + ); + } + + maybe_key +} + +pub(crate) fn seal_header( + header: &B::Header, + keystore: &dyn SyncCryptoStore, + type_public_pair: &CryptoTypePublicPair, +) -> DigestItem +where + B: BlockT, +{ + let pre_hash = header.hash(); + + let raw_sig = SyncCryptoStore::sign_with( + &*keystore, + NIMBUS_KEY_ID, + type_public_pair, + pre_hash.as_ref(), + ) + .expect("Keystore should be able to sign") + .expect("We already checked that the key was present"); + + debug!(target: LOG_TARGET, "The signature is \n{:?}", raw_sig); + + let signature = raw_sig + .clone() + .try_into() + .expect("signature bytes produced by keystore should be right length"); + + ::nimbus_seal(signature) +} + +#[async_trait::async_trait] +impl ParachainConsensus + for NimbusConsensus +where + B: BlockT, + BI: BlockImport + Send + Sync + 'static, + PF: Environment + Send + Sync + 'static, + PF::Proposer: Proposer< + B, + Transaction = BI::Transaction, + ProofRecording = EnableProofRecording, + Proof = ::Proof, + >, + ParaClient: ProvideRuntimeApi + Send + Sync + 'static, + ParaClient::Api: NimbusApi, + CIDP: CreateInherentDataProviders + 'static, + DP: DigestsProvider::Hash> + 'static + Send + Sync, +{ + async fn produce_candidate( + &mut self, + parent: &B::Header, + relay_parent: PHash, + validation_data: &PersistedValidationData, + ) -> Option> { + // Determine if runtime change + let runtime_upgraded = if *parent.number() > sp_runtime::traits::Zero::zero() { + let at = BlockId::Hash(parent.hash()); + let parent_at = BlockId::::Hash(*parent.parent_hash()); + use sp_api::Core as _; + let previous_runtime_version: sp_api::RuntimeVersion = self + .parachain_client + .runtime_api() + .version(&parent_at) + .expect("Runtime api access to not error."); + let runtime_version: sp_api::RuntimeVersion = self + .parachain_client + .runtime_api() + .version(&at) + .expect("Runtime api access to not error."); + + previous_runtime_version != runtime_version + } else { + false + }; + + let maybe_key = if self.skip_prediction || runtime_upgraded { + first_available_key(&*self.keystore) + } else { + first_eligible_key::( + self.parachain_client.clone(), + &*self.keystore, + parent, + validation_data.relay_parent_number, + ) + }; + + // If there are no eligible keys, print the log, and exit early. + let type_public_pair = match maybe_key { + Some(p) => p, + None => { + return None; + } + }; + + let proposer_future = self.proposer_factory.lock().init(&parent); + + let proposer = proposer_future + .await + .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Could not create proposer.")) + .ok()?; + + let nimbus_id = NimbusId::from_slice(&type_public_pair.1) + .map_err( + |e| error!(target: LOG_TARGET, error = ?e, "Invalid Nimbus ID (wrong length)."), + ) + .ok()?; + + let inherent_data = self + .inherent_data( + parent.hash(), + &validation_data, + relay_parent, + nimbus_id.clone(), + ) + .await?; + + let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; + logs.extend( + self.additional_digests_provider + .provide_digests(nimbus_id, parent.hash()), + ); + let inherent_digests = sp_runtime::generic::Digest { logs }; + + let Proposal { + block, + storage_changes, + proof, + } = proposer + .propose( + inherent_data, + inherent_digests, + //TODO: Fix this. + Duration::from_millis(500), + // Set the block limit to 50% of the maximum PoV size. + // + // TODO: If we got benchmarking that includes that encapsulates the proof size, + // we should be able to use the maximum pov size. + Some((validation_data.max_pov_size / 2) as usize), + ) + .await + .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Proposing failed.")) + .ok()?; + + let (header, extrinsics) = block.clone().deconstruct(); + + let sig_digest = seal_header::(&header, &*self.keystore, &type_public_pair); + + let mut block_import_params = BlockImportParams::new(BlockOrigin::Own, header.clone()); + block_import_params.post_digests.push(sig_digest.clone()); + block_import_params.body = Some(extrinsics.clone()); + block_import_params.state_action = sc_consensus::StateAction::ApplyChanges( + sc_consensus::StorageChanges::Changes(storage_changes), + ); + + // Print the same log line as slots (aura and babe) + info!( + "🔖 Sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + *header.number(), + block_import_params.post_hash(), + header.hash(), + ); + + if let Err(err) = self + .block_import + .lock() + .await + .import_block(block_import_params, Default::default()) + .await + { + error!( + target: LOG_TARGET, + at = ?parent.hash(), + error = ?err, + "Error importing built block.", + ); + + return None; + } + + // Compute info about the block after the digest is added + let mut post_header = header.clone(); + post_header.digest_mut().logs.push(sig_digest.clone()); + let post_block = B::new(post_header, extrinsics); + + // Returning the block WITH the seal for distribution around the network. + Some(ParachainCandidate { + block: post_block, + proof, + }) + } +} + +/// Paramaters of [`build_relay_chain_consensus`]. +/// +/// I briefly tried the async keystore approach, but decided to go sync so I can copy +/// code from Aura. Maybe after it is working, Jeremy can help me go async. +pub struct BuildNimbusConsensusParams { + pub para_id: ParaId, + pub proposer_factory: PF, + pub create_inherent_data_providers: CIDP, + pub block_import: BI, + pub parachain_client: Arc, + pub keystore: SyncCryptoStorePtr, + pub skip_prediction: bool, + pub additional_digests_provider: DP, +} diff --git a/external/nimbus-consensus/src/manual_seal.rs b/external/nimbus-consensus/src/manual_seal.rs new file mode 100644 index 000000000..27ca5856c --- /dev/null +++ b/external/nimbus-consensus/src/manual_seal.rs @@ -0,0 +1,131 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use cumulus_primitives_parachain_inherent::{ + ParachainInherentData, INHERENT_IDENTIFIER as PARACHAIN_INHERENT_IDENTIFIER, +}; +use nimbus_primitives::{ + CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_ENGINE_ID, +}; +use sc_consensus::BlockImportParams; +use sc_consensus_manual_seal::{ConsensusDataProvider, Error}; +use sp_api::{BlockT, HeaderT, ProvideRuntimeApi, TransactionFor}; +use sp_application_crypto::ByteArray; +use sp_inherents::InherentData; +use sp_keystore::SyncCryptoStorePtr; +use sp_runtime::{Digest, DigestItem}; +use std::{marker::PhantomData, sync::Arc}; + +/// Provides nimbus-compatible pre-runtime digests for use with manual seal consensus +pub struct NimbusManualSealConsensusDataProvider { + /// Shared reference to keystore + pub keystore: SyncCryptoStorePtr, + + /// Shared reference to the client + pub client: Arc, + // Could have a skip_prediction field here if it becomes desireable + /// Additional digests provider + pub additional_digests_provider: DP, + + pub _phantom: PhantomData

, +} + +impl ConsensusDataProvider for NimbusManualSealConsensusDataProvider +where + B: BlockT, + C: ProvideRuntimeApi + Send + Sync, + C::Api: NimbusApi, + DP: DigestsProvider::Hash> + Send + Sync, + P: Send + Sync, +{ + type Transaction = TransactionFor; + type Proof = P; + + fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result { + // Retrieve the relay chain block number to use as the slot number from the parachain inherent + let slot_number = inherents + .get_data::(&PARACHAIN_INHERENT_IDENTIFIER) + .expect("Parachain inherent should decode correctly") + .expect("Parachain inherent should be present because we are mocking it") + .validation_data + .relay_parent_number; + + // Fetch first eligible key from keystore + let maybe_key = crate::first_eligible_key::( + self.client.clone(), + &*self.keystore, + parent, + // For now we author all blocks in slot zero, which is consistent with how we are + // mocking the relay chain height which the runtime uses for slot beacon. + // This should improve. See https://github.com/PureStake/nimbus/issues/3 + slot_number, + ); + + // If we aren't eligible, return an appropriate error + match maybe_key { + Some(key) => { + let nimbus_id = NimbusId::from_slice(&key.1).map_err(|_| { + Error::StringError(String::from("invalid nimbus id (wrong length)")) + })?; + let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; + logs.extend( + self.additional_digests_provider + .provide_digests(nimbus_id, parent.hash()), + ); + Ok(Digest { logs }) + } + None => Err(Error::StringError(String::from( + "no nimbus keys available to manual seal", + ))), + } + } + + // This is where we actually sign with the nimbus key and attach the seal + fn append_block_import( + &self, + _parent: &B::Header, + params: &mut BlockImportParams, + _inherents: &InherentData, + _proof: Self::Proof, + ) -> Result<(), Error> { + // We have to reconstruct the type-public pair which is only communicated through the pre-runtime digest + let claimed_author = params + .header + .digest() + .logs + .iter() + .find_map(|digest| { + match *digest { + // We do not support the older author inherent in manual seal + DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + _ => None, + } + }) + .expect("Expected one pre-runtime digest that contains author id bytes"); + + let nimbus_public = NimbusId::from_slice(&claimed_author) + .map_err(|_| Error::StringError(String::from("invalid nimbus id (wrong length)")))?; + + let sig_digest = + crate::seal_header::(¶ms.header, &*self.keystore, &nimbus_public.into()); + + params.post_digests.push(sig_digest); + + Ok(()) + } +} diff --git a/external/nimbus-primitives/Cargo.toml b/external/nimbus-primitives/Cargo.toml new file mode 100644 index 000000000..f780237fc --- /dev/null +++ b/external/nimbus-primitives/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "nimbus-primitives" +authors = [ "PureStake" ] +description = "Primitive types and traits used in the Nimbus consensus framework" +edition = "2021" +version = "0.9.0" + +[dependencies] +async-trait = { version = "0.1", optional = true } +parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } + +frame-support = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-system = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } +sp-api = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-std = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", optional = true, default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +[features] +default = [ "std" ] +std = [ + "async-trait", + "frame-support/std", + "frame-system/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-api/std", + "sp-application-crypto/std", + "sp-inherents/std", + "sp-runtime/std", + "sp-std/std", +] + +runtime-benchmarks = [ "frame-benchmarking", "sp-runtime/runtime-benchmarks" ] + +try-runtime = [ "frame-support/try-runtime" ] diff --git a/external/nimbus-primitives/src/digests.rs b/external/nimbus-primitives/src/digests.rs new file mode 100644 index 000000000..a6fb82789 --- /dev/null +++ b/external/nimbus-primitives/src/digests.rs @@ -0,0 +1,80 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! A convenient interface over the digests used in nimbus. +//! +//! Currently Nimbus has two digests; +//! 1. A consensus digest that contains the block author identity +//! This information is copied from the author inehrent. +//! This may be replaced with a pre-runtime digest in the future. +//! 2. A seal digest that contains a signature over the rest of the +//! block including the first digest. + +use crate::{NimbusId, NimbusSignature, NIMBUS_ENGINE_ID}; +use parity_scale_codec::Encode; +use sp_runtime::generic::DigestItem; + +/// A digest item which is usable with aura consensus. +pub trait CompatibleDigestItem: Sized { + /// Construct a pre-runtime digest from the given AuthorId + fn nimbus_pre_digest(author: NimbusId) -> Self; + + /// If this item is a nimbus pre-runtime digest, return the author + fn as_nimbus_pre_digest(&self) -> Option; + + /// Construct a seal digest item from the given signature + fn nimbus_seal(signature: NimbusSignature) -> Self; + + /// If this item is a nimbus seal, return the signature. + fn as_nimbus_seal(&self) -> Option; + + /// This will be deprecated in the future + /// Construct a consensus digest from the given AuthorId + fn nimbus_consensus_digest(author: NimbusId) -> Self; + + /// This will be deprecated in the future + /// If this item is a nimbus consensus digest, return the author + fn as_nimbus_consensus_digest(&self) -> Option; +} + +impl CompatibleDigestItem for DigestItem { + fn nimbus_pre_digest(author: NimbusId) -> Self { + DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode()) + } + + fn as_nimbus_pre_digest(&self) -> Option { + self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) + } + + fn nimbus_seal(signature: NimbusSignature) -> Self { + DigestItem::Seal(NIMBUS_ENGINE_ID, signature.encode()) + } + + fn as_nimbus_seal(&self) -> Option { + self.seal_try_to(&NIMBUS_ENGINE_ID) + } + + // Remove this once deprecated + fn nimbus_consensus_digest(author: NimbusId) -> Self { + DigestItem::Consensus(NIMBUS_ENGINE_ID, author.encode()) + } + + // Remove this once deprecated. I don't think it is used anyway. + // Notice that it calls the pre_runtime helper function. + fn as_nimbus_consensus_digest(&self) -> Option { + self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) + } +} diff --git a/external/nimbus-primitives/src/inherents.rs b/external/nimbus-primitives/src/inherents.rs new file mode 100644 index 000000000..267b17d96 --- /dev/null +++ b/external/nimbus-primitives/src/inherents.rs @@ -0,0 +1,52 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use sp_inherents::{InherentData, InherentIdentifier}; + +/// The InherentIdentifier for nimbus's author inherent +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"author__"; + +/// A bare minimum inherent data provider that provides no real data. +/// The inherent is simply used as a way to kick off some computation +/// until https://github.com/zeitgeistpm/substrate/pull/10128 lands. +pub struct InherentDataProvider; + +#[cfg(feature = "std")] +#[async_trait::async_trait] +impl sp_inherents::InherentDataProvider for InherentDataProvider { + fn provide_inherent_data( + &self, + inherent_data: &mut InherentData, + ) -> Result<(), sp_inherents::Error> { + inherent_data.put_data(INHERENT_IDENTIFIER, &()) + } + + async fn try_handle_error( + &self, + identifier: &InherentIdentifier, + _error: &[u8], + ) -> Option> { + // Dont' process modules from other inherents + if *identifier != INHERENT_IDENTIFIER { + return None; + } + + // All errors with the author inehrent are fatal + Some(Err(sp_inherents::Error::Application(Box::from( + String::from("Error processing dummy nimbus inherent"), + )))) + } +} diff --git a/external/nimbus-primitives/src/lib.rs b/external/nimbus-primitives/src/lib.rs new file mode 100644 index 000000000..e543d04ef --- /dev/null +++ b/external/nimbus-primitives/src/lib.rs @@ -0,0 +1,185 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! Nimbus Consensus Primitives +//! +//! Primitive types and traits for working with the Nimbus consensus framework. +//! This code can be built to no_std for use in the runtime + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_application_crypto::KeyTypeId; +use sp_runtime::generic::DigestItem; +use sp_runtime::traits::BlockNumberProvider; +use sp_runtime::ConsensusEngineId; +#[cfg(feature = "runtime-benchmarks")] +use sp_std::vec; +use sp_std::vec::Vec; + +pub mod digests; +mod inherents; + +pub use digests::CompatibleDigestItem; + +pub use inherents::{InherentDataProvider, INHERENT_IDENTIFIER}; + +pub trait DigestsProvider { + type Digests: IntoIterator; + fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests; +} + +impl DigestsProvider for () { + type Digests = [DigestItem; 0]; + fn provide_digests(&self, _id: Id, _parent: BlockHash) -> Self::Digests { + [] + } +} + +impl DigestsProvider for F +where + F: Fn(Id, BlockHash) -> D, + D: IntoIterator, +{ + type Digests = D; + + fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests { + (*self)(id, parent) + } +} + +/// The given account ID is the author of the current block. +pub trait EventHandler { + //TODO should we be tking ownership here? + fn note_author(author: Author); +} + +impl EventHandler for () { + fn note_author(_author: T) {} +} + +/// A mechanism for determining the current slot. +/// For now we use u32 as the slot type everywhere. Let's see how long we can get away with that. +pub trait SlotBeacon { + fn slot() -> u32; + #[cfg(feature = "runtime-benchmarks")] + fn set_slot(_slot: u32) {} +} + +/// Anything that can provide a block height can be used as a slot beacon. This could be +/// used in at least two realistic ways. +/// 1. Use your own chain's height as the slot number +/// 2. If you're a parachain, use the relay chain's height as the slot number. +impl> SlotBeacon for T { + fn slot() -> u32 { + Self::current_block_number() + } + #[cfg(feature = "runtime-benchmarks")] + fn set_slot(slot: u32) { + Self::set_block_number(slot); + } +} + +/// PLANNED: A SlotBeacon that starts a new slot based on the timestamp. Behaviorally, this is +/// similar to what aura, babe and company do. Implementation-wise it is different because it +/// depends on the timestamp pallet for its notion of time. +pub struct IntervalBeacon; + +impl SlotBeacon for IntervalBeacon { + fn slot() -> u32 { + todo!() + } +} + +/// Trait to determine whether this author is eligible to author in this slot. +/// This is the primary trait your nimbus filter needs to implement. +/// +/// This is the proposition-logic variant. +/// That is to say the caller specifies an author an author and the implementation +/// replies whether that author is eligible. This is useful in many cases and is +/// particularly useful when the active set is unbounded. +/// There may be another variant where the caller only supplies a slot and the +/// implementation replies with a complete set of eligible authors. +pub trait CanAuthor { + #[cfg(feature = "try-runtime")] + // With `try-runtime` the local author should always be able to author a block. + fn can_author(author: &AuthorId, slot: &u32) -> bool { + true + } + #[cfg(not(feature = "try-runtime"))] + fn can_author(author: &AuthorId, slot: &u32) -> bool; + #[cfg(feature = "runtime-benchmarks")] + fn get_authors(_slot: &u32) -> Vec { + vec![] + } + #[cfg(feature = "runtime-benchmarks")] + fn set_eligible_author(_slot: &u32) {} +} +/// Default implementation where anyone can author. +/// +/// This is identical to Cumulus's RelayChainConsensus +impl CanAuthor for () { + fn can_author(_: &T, _: &u32) -> bool { + true + } +} + +/// A Trait to lookup runtime AccountIds from AuthorIds (probably NimbusIds) +/// The trait is generic over the AccountId, becuase different runtimes use +/// different notions of AccoutId. It is also generic over the AuthorId to +/// support the usecase where the author inherent is used for beneficiary info +/// and contains an AccountId directly. +pub trait AccountLookup { + fn lookup_account(author: &NimbusId) -> Option; +} + +// A dummy impl used in simple tests +impl AccountLookup for () { + fn lookup_account(_: &NimbusId) -> Option { + None + } +} + +/// The ConsensusEngineId for nimbus consensus +/// this same identifier will be used regardless of the filters installed +pub const NIMBUS_ENGINE_ID: ConsensusEngineId = *b"nmbs"; + +/// The KeyTypeId used in the Nimbus consensus framework regardles of wat filters are in place. +/// If this gets well adopted, we could move this definition to sp_core to avoid conflicts. +pub const NIMBUS_KEY_ID: KeyTypeId = KeyTypeId(*b"nmbs"); + +// The strongly-typed crypto wrappers to be used by Nimbus in the keystore +mod nimbus_crypto { + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, crate::NIMBUS_KEY_ID); +} + +/// A nimbus author identifier (A public key). +pub type NimbusId = nimbus_crypto::Public; + +/// A nimbus signature. +pub type NimbusSignature = nimbus_crypto::Signature; + +sp_application_crypto::with_pair! { + /// A nimbus keypair + pub type NimbusPair = nimbus_crypto::Pair; +} + +sp_api::decl_runtime_apis! { + /// The runtime api used to predict whether a Nimbus author will be eligible in the given slot + pub trait NimbusApi { + fn can_author(author: NimbusId, relay_parent: u32, parent_header: &Block::Header) -> bool; + } +} diff --git a/external/pallets/author-inherent/Cargo.toml b/external/pallets/author-inherent/Cargo.toml new file mode 100644 index 000000000..4e056fb2d --- /dev/null +++ b/external/pallets/author-inherent/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "pallet-author-inherent" +authors = [ "PureStake" ] +description = "This pallet is the core of the in-runtime portion of Nimbus." +edition = "2021" +license = "GPL-3.0-only" +version = "0.9.0" + +[dependencies] +frame-support = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-system = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +log = { version = "0.4.17", default-features = false } +nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } +parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } +sp-api = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-authorship = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-std = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +# Benchmarks +frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", optional = true, default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +[dev-dependencies] +frame-support-test = { git = "https://github.com/zeitgeistpm/substrate", version = "3.0.0" , branch = "moonbeam-polkadot-v0.9.29" } +sp-core = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-io = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +[features] +default = [ "std" ] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-api/std", + "sp-application-crypto/std", + "sp-authorship/std", + "sp-inherents/std", + "sp-runtime/std", + "sp-std/std", +] + +runtime-benchmarks = [ + "frame-benchmarking", + "nimbus-primitives/runtime-benchmarks", +] +try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] diff --git a/external/pallets/author-inherent/src/benchmarks.rs b/external/pallets/author-inherent/src/benchmarks.rs new file mode 100644 index 000000000..4235fca8f --- /dev/null +++ b/external/pallets/author-inherent/src/benchmarks.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +use crate::{Call, Config, Pallet}; +use frame_benchmarking::benchmarks; +use frame_system::RawOrigin; +use nimbus_primitives::CanAuthor; +use nimbus_primitives::SlotBeacon; +benchmarks! { + kick_off_authorship_validation { + // The slot inserted needs to be higher than that already in storage + T::SlotBeacon::set_slot(100); + Pallet::::set_eligible_author(&T::SlotBeacon::slot()); + }: _(RawOrigin::None) +} diff --git a/external/pallets/author-inherent/src/exec.rs b/external/pallets/author-inherent/src/exec.rs new file mode 100644 index 000000000..bd4f3bb99 --- /dev/null +++ b/external/pallets/author-inherent/src/exec.rs @@ -0,0 +1,99 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! Block executive to be used by relay chain validators when validating parachain blocks built +//! with the nimubs consensus family. + +use frame_support::traits::ExecuteBlock; +use sp_api::{BlockT, HeaderT}; +// For some reason I can't get these logs to actually print +use log::debug; +use nimbus_primitives::{digests::CompatibleDigestItem, NimbusId, NIMBUS_ENGINE_ID}; +use sp_application_crypto::ByteArray; +use sp_runtime::{generic::DigestItem, RuntimeAppPublic}; + +/// Block executive to be used by relay chain validators when validating parachain blocks built +/// with the nimubs consensus family. +/// +/// This will strip the seal digest, and confirm that it contains a valid signature +/// By the block author reported in the author inherent. +/// +/// Essentially this contains the logic of the verifier plus the inner executive. +/// TODO Degisn improvement: +/// Can we share code with the verifier? +/// Can this struct take a verifier as an associated type? +/// Or maybe this will just get simpler in general when https://github.com/paritytech/polkadot/issues/2888 lands +pub struct BlockExecutor(sp_std::marker::PhantomData<(T, I)>); + +impl ExecuteBlock for BlockExecutor +where + Block: BlockT, + I: ExecuteBlock, +{ + fn execute_block(block: Block) { + let (mut header, extrinsics) = block.deconstruct(); + + debug!(target: "executive", "In hacked Executive. Initial digests are {:?}", header.digest()); + + // Set the seal aside for checking. + let seal = header + .digest_mut() + .pop() + .expect("Seal digest is present and is last item"); + + debug!(target: "executive", "In hacked Executive. digests after stripping {:?}", header.digest()); + debug!(target: "executive", "The seal we got {:?}", seal); + + let signature = seal + .as_nimbus_seal() + .unwrap_or_else(|| panic!("HeaderUnsealed")); + + debug!(target: "executive", "🪲 Header hash after popping digest {:?}", header.hash()); + + debug!(target: "executive", "🪲 Signature according to executive is {:?}", signature); + + // Grab the author information from the preruntime digest + //TODO use the trait + let claimed_author = header + .digest() + .logs + .iter() + .find_map(|digest| match *digest { + DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + _ => None, + }) + .expect("Expected pre-runtime digest that contains author id bytes"); + + debug!(target: "executive", "🪲 Claimed Author according to executive is {:?}", claimed_author); + + // Verify the signature + let valid_signature = NimbusId::from_slice(&claimed_author) + .expect("Expected claimed author to be a valid NimbusId.") + .verify(&header.hash(), &signature); + + debug!(target: "executive", "🪲 Valid signature? {:?}", valid_signature); + + if !valid_signature { + panic!("Block signature invalid"); + } + + // Now that we've verified the signature, hand execution off to the inner executor + // which is probably the normal frame executive. + I::execute_block(Block::new(header, extrinsics)); + } +} diff --git a/external/pallets/author-inherent/src/lib.rs b/external/pallets/author-inherent/src/lib.rs new file mode 100644 index 000000000..6f873a8eb --- /dev/null +++ b/external/pallets/author-inherent/src/lib.rs @@ -0,0 +1,247 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! Pallet that allows block authors to include their identity in a block via an inherent. +//! Currently the author does not _prove_ their identity, just states it. So it should not be used, +//! for things like equivocation slashing that require authenticated authorship information. + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::traits::{FindAuthor, Get}; +use nimbus_primitives::{ + AccountLookup, CanAuthor, NimbusId, SlotBeacon, INHERENT_IDENTIFIER, NIMBUS_ENGINE_ID, +}; +use parity_scale_codec::{Decode, Encode}; +use sp_inherents::{InherentIdentifier, IsFatalError}; +use sp_runtime::{ConsensusEngineId, RuntimeString}; + +mod exec; +pub use exec::BlockExecutor; + +pub use pallet::*; + +#[cfg(any(test, feature = "runtime-benchmarks"))] +mod benchmarks; + +pub mod weights; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use crate::weights::WeightInfo; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + /// The Author Inherent pallet. The core of the nimbus consensus framework's runtime presence. + #[pallet::pallet] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// A type to convert between AuthorId and AccountId. This is useful when you want to associate + /// Block authoring behavior with an AccoutId for rewards or slashing. If you do not need to + /// hold an AccountID responsible for authoring use `()` which acts as an identity mapping. + type AccountLookup: AccountLookup; + + /// The final word on whether the reported author can author at this height. + /// This will be used when executing the inherent. This check is often stricter than the + /// Preliminary check, because it can use more data. + /// If the pallet that implements this trait depends on an inherent, that inherent **must** + /// be included before this one. + type CanAuthor: CanAuthor; + + /// Some way of determining the current slot for purposes of verifying the author's eligibility + type SlotBeacon: SlotBeacon; + + type WeightInfo: WeightInfo; + } + + impl sp_runtime::BoundToRuntimeAppPublic for Pallet { + type Public = NimbusId; + } + + #[pallet::error] + pub enum Error { + /// Author already set in block. + AuthorAlreadySet, + /// No AccountId was found to be associated with this author + NoAccountId, + /// The author in the inherent is not an eligible author. + CannotBeAuthor, + } + + /// Author of current block. + #[pallet::storage] + pub type Author = StorageValue<_, T::AccountId, OptionQuery>; + + /// The highest slot that has been seen in the history of this chain. + /// This is a strictly-increasing value. + #[pallet::storage] + pub type HighestSlotSeen = StorageValue<_, u32, ValueQuery>; + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_: T::BlockNumber) -> Weight { + // Now extract the author from the digest + let digest = >::digest(); + let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + if let Some(author) = Self::find_author(pre_runtime_digests) { + // Store the author so we can confirm eligibility after the inherents have executed + >::put(&author); + } + + T::DbWeight::get().writes(1) + } + } + + #[pallet::call] + impl Pallet { + /// This inherent is a workaround to run code after the "real" inherents have executed, + /// but before transactions are executed. + // This should go into on_post_inherents when it is ready https://github.com/zeitgeistpm/substrate/pull/10128 + // TODO better weight. For now we just set a somewhat conservative fudge factor + #[pallet::weight((T::WeightInfo::kick_off_authorship_validation(), DispatchClass::Mandatory))] + pub fn kick_off_authorship_validation(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure_none(origin)?; + + // First check that the slot number is valid (greater than the previous highest) + let slot = T::SlotBeacon::slot(); + assert!( + slot > HighestSlotSeen::::get(), + "Block invalid; Supplied slot number is not high enough" + ); + + // Now check that the author is valid in this slot + assert!( + T::CanAuthor::can_author(&Self::get(), &slot), + "Block invalid, supplied author is not eligible." + ); + + // Once that is validated, update the stored slot number + HighestSlotSeen::::put(slot); + + Ok(Pays::No.into()) + } + } + + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + type Error = InherentError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn is_inherent_required(_: &InherentData) -> Result, Self::Error> { + // Return Ok(Some(_)) unconditionally because this inherent is required in every block + // If it is not found, throw an AuthorInherentRequired error. + Ok(Some(InherentError::Other( + sp_runtime::RuntimeString::Borrowed( + "Inherent required to manually initiate author validation", + ), + ))) + } + + // Regardless of whether the client is still supplying the author id, + // we will create the new empty-payload inherent extrinsic. + fn create_inherent(_data: &InherentData) -> Option { + Some(Call::kick_off_authorship_validation {}) + } + + fn is_inherent(call: &Self::Call) -> bool { + matches!(call, Call::kick_off_authorship_validation { .. }) + } + } + + impl FindAuthor for Pallet { + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + for (id, mut data) in digests.into_iter() { + if id == NIMBUS_ENGINE_ID { + let author_id = NimbusId::decode(&mut data) + .expect("NimbusId encoded in preruntime digest must be valid"); + + let author_account = T::AccountLookup::lookup_account(&author_id) + .expect("No Account Mapped to this NimbusId"); + + return Some(author_account); + } + } + + None + } + } + + impl Get for Pallet { + fn get() -> T::AccountId { + Author::::get().expect("Block author not inserted into Author Inherent Pallet") + } + } + + /// To learn whether a given NimbusId can author, as opposed to an account id, you + /// can ask this pallet directly. It will do the mapping for you. + impl CanAuthor for Pallet { + fn can_author(author: &NimbusId, slot: &u32) -> bool { + let account = match T::AccountLookup::lookup_account(author) { + Some(account) => account, + // Authors whose account lookups fail will not be eligible + None => { + return false; + } + }; + + T::CanAuthor::can_author(&account, slot) + } + #[cfg(feature = "runtime-benchmarks")] + fn set_eligible_author(slot: &u32) { + let eligible_authors = T::CanAuthor::get_authors(slot); + if let Some(author) = eligible_authors.first() { + Author::::put(author) + } + } + } +} + +#[derive(Encode)] +#[cfg_attr(feature = "std", derive(Debug, Decode))] +pub enum InherentError { + Other(RuntimeString), +} + +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + match *self { + InherentError::Other(_) => true, + } + } +} + +impl InherentError { + /// Try to create an instance ouf of the given identifier and data. + #[cfg(feature = "std")] + pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { + if id == &INHERENT_IDENTIFIER { + ::decode(&mut &data[..]).ok() + } else { + None + } + } +} diff --git a/external/pallets/author-inherent/src/mock.rs b/external/pallets/author-inherent/src/mock.rs new file mode 100644 index 000000000..df37a07af --- /dev/null +++ b/external/pallets/author-inherent/src/mock.rs @@ -0,0 +1,113 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use crate::{self as pallet_testing, AccountLookup, NimbusId}; +use frame_support::parameter_types; +use frame_support::traits::ConstU32; +use frame_support::weights::RuntimeDbWeight; +use frame_system; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + AuthorInherent: pallet_testing::{Pallet, Call, Storage}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub Authors: Vec = vec![1, 2, 3, 4, 5]; + pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 1, + write: 10, + }; +} + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = TestDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +pub struct DummyBeacon {} +impl nimbus_primitives::SlotBeacon for DummyBeacon { + fn slot() -> u32 { + 0 + } +} + +pub const ALICE: u64 = 1; +pub const ALICE_NIMBUS: [u8; 32] = [1; 32]; +pub struct MockAccountLookup; +impl AccountLookup for MockAccountLookup { + fn lookup_account(nimbus_id: &NimbusId) -> Option { + let nimbus_id_bytes: &[u8] = nimbus_id.as_ref(); + + if nimbus_id_bytes == &ALICE_NIMBUS { + Some(ALICE) + } else { + None + } + } +} + +impl pallet_testing::Config for Test { + type AccountLookup = MockAccountLookup; + type CanAuthor = (); + type SlotBeacon = DummyBeacon; + type WeightInfo = (); +} + +/// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + frame_system::GenesisConfig::default() + .build_storage::() + .unwrap() + .into() +} diff --git a/external/pallets/author-inherent/src/tests.rs b/external/pallets/author-inherent/src/tests.rs new file mode 100644 index 000000000..affa2e042 --- /dev/null +++ b/external/pallets/author-inherent/src/tests.rs @@ -0,0 +1,72 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use crate::mock::*; +use crate::pallet::Author; +use frame_support::traits::{OnFinalize, OnInitialize}; +use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID}; +use parity_scale_codec::Encode; +use sp_core::{ByteArray, H256}; +use sp_runtime::{Digest, DigestItem}; + +#[test] +fn kick_off_authorship_validation_is_mandatory() { + use frame_support::dispatch::{DispatchClass, GetDispatchInfo}; + + let info = crate::Call::::kick_off_authorship_validation {}.get_dispatch_info(); + assert_eq!(info.class, DispatchClass::Mandatory); +} + +#[test] +fn test_author_is_available_after_on_initialize() { + new_test_ext().execute_with(|| { + let block_number = 1; + System::initialize( + &block_number, + &H256::default(), + &Digest { + logs: vec![DigestItem::PreRuntime( + NIMBUS_ENGINE_ID, + NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), + )], + }, + ); + + AuthorInherent::on_initialize(block_number); + assert_eq!(Some(ALICE), >::get()); + }); +} + +#[test] +fn test_author_is_still_available_after_on_finalize() { + new_test_ext().execute_with(|| { + let block_number = 1; + System::initialize( + &block_number, + &H256::default(), + &Digest { + logs: vec![DigestItem::PreRuntime( + NIMBUS_ENGINE_ID, + NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), + )], + }, + ); + + AuthorInherent::on_initialize(block_number); + AuthorInherent::on_finalize(block_number); + assert_eq!(Some(ALICE), >::get()); + }); +} diff --git a/external/pallets/author-inherent/src/weights.rs b/external/pallets/author-inherent/src/weights.rs new file mode 100644 index 000000000..420fbdb8f --- /dev/null +++ b/external/pallets/author-inherent/src/weights.rs @@ -0,0 +1,91 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Autogenerated weights for pallet_author_inherent +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-04-22, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// --chain +// dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// pallet_author_inherent +// --extrinsic +// kick_off_authorship_validation +// --steps +// 50 +// --repeat +// 20 +// --template=./benchmarking/frame-weight-template.hbs +// --record-proof +// --json-file +// raw.json +// --output +// weights.rs + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_author_inherent. +pub trait WeightInfo { + #[rustfmt::skip] + fn kick_off_authorship_validation() -> Weight; +} + +/// Weights for pallet_author_inherent using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) + // Storage: AuthorInherent Author (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:1 w:0) + // Storage: AuthorFilter EligibleCount (r:1 w:0) + // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + #[rustfmt::skip] + fn kick_off_authorship_validation() -> Weight { + Weight::from_ref_time(20_862_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) + // Storage: AuthorInherent Author (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:1 w:0) + // Storage: AuthorFilter EligibleCount (r:1 w:0) + // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + #[rustfmt::skip] + fn kick_off_authorship_validation() -> Weight { + Weight::from_ref_time(20_862_000 as u64) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } +} diff --git a/external/pallets/author-mapping/Cargo.toml b/external/pallets/author-mapping/Cargo.toml new file mode 100644 index 000000000..cf5a3925b --- /dev/null +++ b/external/pallets/author-mapping/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "pallet-author-mapping" +authors = [ "PureStake" ] +description = "Maps AuthorIds to AccountIds Useful for associating consensus authors with in-runtime accounts" +edition = "2021" +version = "2.0.5" + +[dependencies] +log = { version = "0.4", default-features = false } +serde = { version = "1.0.124", optional = true } + +# Substrate +frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", optional = true, default-features = false } +frame-support = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +frame-system = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-std = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } + +# Nimbus +nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } + +session-keys-primitives = { path = "../../session-keys", default-features = false } + +[dev-dependencies] +pallet-balances = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-io = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } + +[features] +default = [ "std" ] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde", + "session-keys-primitives/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "session-keys-primitives/runtime-benchmarks", +] +try-runtime = [ "frame-support/try-runtime" ] diff --git a/external/pallets/author-mapping/migrations.md b/external/pallets/author-mapping/migrations.md new file mode 100644 index 000000000..7f0c0b19c --- /dev/null +++ b/external/pallets/author-mapping/migrations.md @@ -0,0 +1,10 @@ +# Migration History + +## Add session keys to author mapping pallet + +- [Migration PR `#1407`](https://github.com/PureStake/moonbeam/pull/1407) + +## Manage author mapping blake2 migration + +- [Migration PR `#796`](https://github.com/PureStake/moonbeam/pull/796) +- [Migration Removal PR `#1434`](https://github.com/PureStake/moonbeam/pull/1434) diff --git a/external/pallets/author-mapping/src/benchmarks.rs b/external/pallets/author-mapping/src/benchmarks.rs new file mode 100644 index 000000000..21faae3a0 --- /dev/null +++ b/external/pallets/author-mapping/src/benchmarks.rs @@ -0,0 +1,160 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +//! Benchmarking +use crate::{keys_wrapper, BalanceOf, Call, Config, Pallet}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; +use frame_support::{ + assert_ok, + traits::{Currency, Get}, +}; +use frame_system::RawOrigin; +use nimbus_primitives::NimbusId; +use parity_scale_codec::Decode; + +/// Create a funded user. +fn create_funded_user() -> T::AccountId { + let user = account("account id", 0u32, 0u32); + T::DepositCurrency::make_free_balance_be( + &user, + <::DepositAmount as Get>>::get(), + ); + T::DepositCurrency::issue(<::DepositAmount as Get>>::get()); + user +} + +/// Create a valid nimbus id from a simple u8 seed +pub fn nimbus_id(seed: u8) -> NimbusId { + let id = [seed; 32]; + NimbusId::decode(&mut &id[..]).expect("valid input") +} + +benchmarks! { + add_association { + let caller = create_funded_user::(); + let id = nimbus_id(1u8); + }: _(RawOrigin::Signed(caller.clone()), id.clone()) + verify { + assert_eq!(Pallet::::account_id_of(&id), Some(caller)); + } + + update_association { + let caller = create_funded_user::(); + let first_id = nimbus_id(1u8); + let second_id = nimbus_id(2u8); + assert_ok!(Pallet::::add_association( + RawOrigin::Signed(caller.clone()).into(), + first_id.clone()) + ); + }: _(RawOrigin::Signed(caller.clone()), first_id.clone(), second_id.clone()) + verify { + assert_eq!(Pallet::::account_id_of(&first_id), None); + assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); + } + + clear_association { + let caller = create_funded_user::(); + let first_id = nimbus_id(1u8); + assert_ok!(Pallet::::add_association( + RawOrigin::Signed(caller.clone()).into(), + first_id.clone()) + ); + }: _(RawOrigin::Signed(caller.clone()), first_id.clone()) + verify { + assert_eq!(Pallet::::account_id_of(&first_id), None); + } + + remove_keys { + let caller = create_funded_user::(); + let id = nimbus_id(1u8); + let keys: T::Keys = nimbus_id(3u8).into(); + assert_ok!(Pallet::::set_keys( + RawOrigin::Signed(caller.clone()).into(), + keys_wrapper::(id.clone(), keys.clone()), + ) + ); + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert_eq!(Pallet::::account_id_of(&id), None); + assert_eq!(Pallet::::nimbus_id_of(&caller), None); + } + + set_keys { + let caller = create_funded_user::(); + let first_id = nimbus_id(1u8); + let first_keys: T::Keys = nimbus_id(3u8).into(); + let second_id = nimbus_id(2u8); + let second_keys: T::Keys = nimbus_id(3u8).into(); + // we benchmark set_keys after already calling set_keys because + // key rotation is more common than initially setting them + assert_ok!(Pallet::::set_keys( + RawOrigin::Signed(caller.clone()).into(), + keys_wrapper::(first_id.clone(), + first_keys.clone()), + ) + ); + }: _(RawOrigin::Signed(caller.clone()), keys_wrapper::(second_id.clone(), second_keys.clone()) + ) verify { + assert_eq!(Pallet::::account_id_of(&first_id), None); + assert_eq!(Pallet::::keys_of(&first_id), None); + assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); + assert_eq!(Pallet::::keys_of(&second_id), Some(second_keys)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::Runtime; + use frame_support::assert_ok; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + TestExternalities::new(t) + } + + #[test] + fn bench_add_association() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_add_association()); + }); + } + + #[test] + fn bench_update_association() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_update_association()); + }); + } + + #[test] + fn bench_clear_association() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_clear_association()); + }); + } +} + +impl_benchmark_test_suite!( + Pallet, + crate::benchmarks::tests::new_test_ext(), + crate::mock::Runtime +); diff --git a/external/pallets/author-mapping/src/lib.rs b/external/pallets/author-mapping/src/lib.rs new file mode 100644 index 000000000..fca208903 --- /dev/null +++ b/external/pallets/author-mapping/src/lib.rs @@ -0,0 +1,403 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Maps Author Ids as used in nimbus consensus layer to account ids as used in the runtime. +//! This should likely be moved to nimbus eventually. +//! +//! This pallet maps NimbusId => AccountId which is most useful when using propositional style +//! queries. This mapping will likely need to go the other way if using exhaustive authority sets. +//! That could either be a separate pallet, or this pallet could implement a two-way mapping. But +//! for now it it one-way + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::pallet; + +pub use pallet::*; + +pub mod weights; +use weights::WeightInfo; +#[cfg(any(test, feature = "runtime-benchmarks"))] +mod benchmarks; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +pub mod migrations; + +#[pallet] +pub mod pallet { + use crate::WeightInfo; + use frame_support::pallet_prelude::*; + use frame_support::traits::{Currency, ReservableCurrency}; + use frame_system::pallet_prelude::*; + use nimbus_primitives::{AccountLookup, NimbusId}; + use session_keys_primitives::KeysLookup; + use sp_std::{mem::size_of, vec::Vec}; + + pub type BalanceOf = <::DepositCurrency as Currency< + ::AccountId, + >>::Balance; + + #[derive(Clone, Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] + #[scale_info(skip_type_params(T))] + pub struct RegistrationInfo { + pub(crate) account: T::AccountId, + pub(crate) deposit: BalanceOf, + pub(crate) keys: T::Keys, + } + + /// Wrapper to form the input to `set_keys` from NimbusId + keys + pub fn keys_wrapper(nimbus_id: NimbusId, keys: T::Keys) -> Vec { + let mut r = nimbus_id.encode(); + r.extend(&keys.encode()); + r + } + + /// Size of NimbusId + T::Keys to check size of `set_keys` input before trying to decode + pub fn keys_size() -> usize { + size_of::() as usize + size_of::() as usize + } + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + /// Configuration trait of this pallet + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type + type Event: From> + IsType<::Event>; + /// Currency in which the security deposit will be taken. + type DepositCurrency: Currency + ReservableCurrency; + /// The amount that should be taken as a security deposit when registering a NimbusId. + type DepositAmount: Get<>::Balance>; + /// Additional keys + /// Convertible From to get default keys for each mapping (for the migration) + type Keys: Parameter + Member + MaybeSerializeDeserialize + From; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + /// An error that can occur while executing the mapping pallet's logic. + #[pallet::error] + pub enum Error { + /// The association can't be cleared because it is not found. + AssociationNotFound, + /// The association can't be cleared because it belongs to another account. + NotYourAssociation, + /// This account cannot set an author because it cannon afford the security deposit + CannotAffordSecurityDeposit, + /// The NimbusId in question is already associated and cannot be overwritten + AlreadyAssociated, + /// No existing NimbusId can be found for the account + OldAuthorIdNotFound, + /// Keys have wrong size + WrongKeySize, + /// Failed to decode NimbusId for `set_keys` + DecodeNimbusFailed, + /// Failed to decode T::Keys for `set_keys` + DecodeKeysFailed, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// A NimbusId has been registered and mapped to an AccountId. + KeysRegistered { + nimbus_id: NimbusId, + account_id: T::AccountId, + keys: T::Keys, + }, + /// An NimbusId has been de-registered, and its AccountId mapping removed. + KeysRemoved { + nimbus_id: NimbusId, + account_id: T::AccountId, + keys: T::Keys, + }, + /// An NimbusId has been registered, replacing a previous registration and its mapping. + KeysRotated { + new_nimbus_id: NimbusId, + account_id: T::AccountId, + new_keys: T::Keys, + }, + } + + #[pallet::call] + impl Pallet { + /// Register your NimbusId onchain so blocks you author are associated with your account. + /// + /// Users who have been (or will soon be) elected active collators in staking, + /// should submit this extrinsic to have their blocks accepted and earn rewards. + #[pallet::weight(::WeightInfo::add_association())] + pub fn add_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { + let account_id = ensure_signed(origin)?; + + Self::register_keys(nimbus_id.clone(), account_id, nimbus_id.into()) + } + + /// Change your Mapping. + /// + /// This is useful for normal key rotation or for when switching from one physical collator + /// machine to another. No new security deposit is required. + /// This sets keys to new_nimbus_id.into() by default. + #[pallet::weight(::WeightInfo::update_association())] + pub fn update_association( + origin: OriginFor, + old_nimbus_id: NimbusId, + new_nimbus_id: NimbusId, + ) -> DispatchResult { + let account_id = ensure_signed(origin)?; + + Self::rotate_keys( + old_nimbus_id, + new_nimbus_id.clone(), + account_id, + new_nimbus_id.into(), + ) + } + + /// Clear your Mapping. + /// + /// This is useful when you are no longer an author and would like to re-claim your security + /// deposit. + #[pallet::weight(::WeightInfo::clear_association())] + pub fn clear_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { + let account_id = ensure_signed(origin)?; + + Self::rm_keys(nimbus_id, account_id) + } + + /// Remove your Mapping. + /// + /// This is useful when you are no longer an author and would like to re-claim your security + /// deposit. + #[pallet::weight(::WeightInfo::remove_keys())] + pub fn remove_keys(origin: OriginFor) -> DispatchResult { + let account_id = ensure_signed(origin)?; + let nimbus_id = + Self::nimbus_id_of(&account_id).ok_or(Error::::OldAuthorIdNotFound)?; + + Self::rm_keys(nimbus_id, account_id) + } + + /// Set association and session keys at once. + /// + /// This is useful for key rotation to update Nimbus and VRF keys in one call. + /// No new security deposit is required. Will replace `update_association` which is kept + /// now for backwards compatibility reasons. + #[pallet::weight(::WeightInfo::set_keys())] + pub fn set_keys(origin: OriginFor, keys: Vec) -> DispatchResult { + let account_id = ensure_signed(origin)?; + ensure!(keys.len() == keys_size::(), Error::::WrongKeySize); + let encoded = &mut keys.as_slice(); + let new_nimbus_id = + NimbusId::decode(encoded).map_err(|_| Error::::DecodeNimbusFailed)?; + let keys = T::Keys::decode(encoded).map_err(|_| Error::::DecodeKeysFailed)?; + + if let Some(old_nimbus_id) = Self::nimbus_id_of(&account_id) { + Self::rotate_keys(old_nimbus_id, new_nimbus_id, account_id, keys) + } else { + Self::register_keys(new_nimbus_id, account_id, keys) + } + } + } + + impl Pallet { + fn rm_keys(nimbus_id: NimbusId, account_id: T::AccountId) -> DispatchResult { + let stored_info = MappingWithDeposit::::try_get(&nimbus_id) + .map_err(|_| Error::::AssociationNotFound)?; + + ensure!( + account_id == stored_info.account, + Error::::NotYourAssociation + ); + + MappingWithDeposit::::remove(&nimbus_id); + NimbusLookup::::remove(&account_id); + + T::DepositCurrency::unreserve(&account_id, stored_info.deposit); + + >::deposit_event(Event::KeysRemoved { + nimbus_id, + account_id, + keys: stored_info.keys, + }); + Ok(()) + } + fn register_keys( + nimbus_id: NimbusId, + account_id: T::AccountId, + keys: T::Keys, + ) -> DispatchResult { + ensure!( + MappingWithDeposit::::get(&nimbus_id).is_none(), + Error::::AlreadyAssociated + ); + Self::enact_registration(&nimbus_id, &account_id, keys.clone())?; + + >::deposit_event(Event::KeysRegistered { + nimbus_id, + account_id, + keys, + }); + Ok(()) + } + fn rotate_keys( + old_nimbus_id: NimbusId, + new_nimbus_id: NimbusId, + account_id: T::AccountId, + new_keys: T::Keys, + ) -> DispatchResult { + let stored_info = MappingWithDeposit::::try_get(&old_nimbus_id) + .map_err(|_| Error::::AssociationNotFound)?; + + ensure!( + account_id == stored_info.account, + Error::::NotYourAssociation + ); + if old_nimbus_id != new_nimbus_id { + // cannot overwrite a NimbusId if it is not yours + ensure!( + MappingWithDeposit::::get(&new_nimbus_id).is_none(), + Error::::AlreadyAssociated + ); + } + + MappingWithDeposit::::remove(&old_nimbus_id); + let new_stored_info = RegistrationInfo { + keys: new_keys.clone(), + ..stored_info + }; + MappingWithDeposit::::insert(&new_nimbus_id, &new_stored_info); + NimbusLookup::::insert(&account_id, &new_nimbus_id); + + >::deposit_event(Event::KeysRotated { + new_nimbus_id, + account_id, + new_keys, + }); + Ok(()) + } + pub fn enact_registration( + nimbus_id: &NimbusId, + account_id: &T::AccountId, + keys: T::Keys, + ) -> DispatchResult { + let deposit = T::DepositAmount::get(); + + T::DepositCurrency::reserve(account_id, deposit) + .map_err(|_| Error::::CannotAffordSecurityDeposit)?; + + let info = RegistrationInfo { + account: account_id.clone(), + deposit, + keys, + }; + + MappingWithDeposit::::insert(nimbus_id, info); + NimbusLookup::::insert(account_id, nimbus_id); + + Ok(()) + } + } + + #[pallet::storage] + #[pallet::getter(fn account_and_deposit_of)] + /// We maintain a mapping from the NimbusIds used in the consensus layer + /// to the AccountIds runtime. + pub type MappingWithDeposit = + StorageMap<_, Blake2_128Concat, NimbusId, RegistrationInfo, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn nimbus_lookup)] + /// We maintain a reverse mapping from AccountIds to NimbusIDS + pub type NimbusLookup = + StorageMap<_, Blake2_128Concat, T::AccountId, NimbusId, OptionQuery>; + + #[pallet::genesis_config] + /// Genesis config for author mapping pallet + pub struct GenesisConfig { + /// The associations that should exist at chain genesis + pub mappings: Vec<(NimbusId, T::AccountId)>, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { mappings: vec![] } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + for (nimbus_id, account_id) in &self.mappings { + if let Err(e) = Pallet::::enact_registration( + &nimbus_id, + &account_id, + nimbus_id.clone().into(), + ) { + log::warn!("Error with genesis author mapping registration: {:?}", e); + } + } + } + } + + impl AccountLookup for Pallet { + fn lookup_account(author: &NimbusId) -> Option { + Self::account_id_of(author) + } + } + + impl KeysLookup for Pallet { + #[cfg(feature = "runtime-benchmarks")] + type Account = T::AccountId; + fn lookup_keys(author: &NimbusId) -> Option { + Self::keys_of(author) + } + /// Sets keys WITHOUT reserving deposit, for benchmarking purposes only + #[cfg(feature = "runtime-benchmarks")] + fn set_keys(id: NimbusId, account: T::AccountId, keys: T::Keys) { + use sp_runtime::traits::Zero; + MappingWithDeposit::::insert( + id, + RegistrationInfo { + account, + deposit: Zero::zero(), + keys, + }, + ); + } + } + + impl Pallet { + /// A helper function to lookup the account id associated with the given author id. This is + /// the primary lookup that this pallet is responsible for. + pub fn account_id_of(nimbus_id: &NimbusId) -> Option { + Self::account_and_deposit_of(nimbus_id).map(|info| info.account) + } + /// A helper function to lookup the keys associated with the given author id. + pub fn keys_of(nimbus_id: &NimbusId) -> Option { + Self::account_and_deposit_of(nimbus_id).map(|info| info.keys) + } + /// A helper function to lookup NimbusId associated with a given AccountId + pub fn nimbus_id_of(account_id: &T::AccountId) -> Option { + NimbusLookup::::get(account_id) + } + } +} diff --git a/external/pallets/author-mapping/src/migrations.rs b/external/pallets/author-mapping/src/migrations.rs new file mode 100644 index 000000000..1b373dbce --- /dev/null +++ b/external/pallets/author-mapping/src/migrations.rs @@ -0,0 +1,183 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +use crate::{BalanceOf, Config, Event, MappingWithDeposit, NimbusLookup, Pallet, RegistrationInfo}; +use frame_support::{ + pallet_prelude::PhantomData, + traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, + weights::Weight, +}; +use nimbus_primitives::NimbusId; +use parity_scale_codec::{Decode, Encode}; + +#[cfg(feature = "try-runtime")] +use sp_std::vec::Vec; +/// Migrates MappingWithDeposit map value from RegistrationInfo to RegistrationInformation, +/// thereby adding a keys: T::Keys field to the value to support VRF keys that can be looked up +/// via NimbusId. +pub struct AddAccountIdToNimbusLookup(PhantomData); +impl OnRuntimeUpgrade for AddAccountIdToNimbusLookup { + fn on_runtime_upgrade() -> Weight { + log::info!(target: "AddAccountIdToNimbusLookup", "running migration"); + + let mut read_write_count = 0u64; + >::translate(|nimbus_id, registration_info: RegistrationInfo| { + read_write_count += 2u64; + if NimbusLookup::::get(®istration_info.account).is_none() { + >::insert(®istration_info.account, nimbus_id); + Some(registration_info) + } else { + // revoke the additional association and return the funds + T::DepositCurrency::unreserve( + ®istration_info.account, + registration_info.deposit, + ); + + >::deposit_event(Event::KeysRemoved { + nimbus_id, + account_id: registration_info.account, + keys: registration_info.keys, + }); + None + } + }); + // return weight + + T::DbWeight::get() + .reads(read_write_count) + .saturating_add(T::DbWeight::get().writes(read_write_count)) + } + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let mut nimbus_set: Vec = Vec::new(); + let mut state_map: BTreeMap = BTreeMap::new(); + for (nimbus_id, info) in >::iter() { + if !nimbus_set.contains(&nimbus_id) { + state_map.insert(nimbus_id.clone(), info.account); + nimbus_set.push(nimbus_id); + } + } + Ok(state_map.encode()) + } + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let state_map: BTreeMap = + Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + for (nimbus_id, _) in >::iter() { + let old_account = state_map.get(&nimbus_id).expect("qed"); + let maybe_account_of_nimbus = >::get(old_account); + assert_eq!( + Some(nimbus_id), + maybe_account_of_nimbus, + "New NimbusLookup dne expected NimbusID" + ); + } + Ok(()) + } +} + +/// Migrates MappingWithDeposit map value from RegistrationInfo to RegistrationInformation, +/// thereby adding a keys: T::Keys field to the value to support VRF keys that can be looked up +/// via NimbusId. +pub struct AddKeysToRegistrationInfo(PhantomData); +#[derive(Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] +struct OldRegistrationInfo { + account: AccountId, + deposit: Balance, +} +fn migrate_registration_info( + nimbus_id: NimbusId, + old: OldRegistrationInfo>, +) -> RegistrationInfo { + RegistrationInfo { + account: old.account, + deposit: old.deposit, + keys: nimbus_id.into(), + } +} +impl OnRuntimeUpgrade for AddKeysToRegistrationInfo { + fn on_runtime_upgrade() -> Weight { + log::info!(target: "AddKeysToRegistrationInfo", "running migration"); + + let mut read_write_count = 0u64; + >::translate( + |nimbus_id, old_registration_info: OldRegistrationInfo>| { + read_write_count = read_write_count.saturating_add(1u64); + Some(migrate_registration_info(nimbus_id, old_registration_info)) + }, + ); + // return weight + T::DbWeight::get() + .reads(read_write_count) + .saturating_add(T::DbWeight::get().writes(read_write_count)) + } + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let mut state_map: BTreeMap)> = BTreeMap::new(); + + // get total deposited and account for all nimbus_keys + for (nimbus_id, info) in >::iter() { + state_map.insert(nimbus_id, (info.account, info.deposit)); + } + Ok(state_map.encode()) + } + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let state_map: BTreeMap)> = + Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + // ensure new deposit and account are the same as the old ones + // ensure new keys are equal to nimbus_id + for (nimbus_id, info) in >::iter() { + let (old_account, old_deposit) = state_map.get(&nimbus_id).expect("qed"); + + let new_account = info.account; + assert_eq!( + old_account.clone(), + new_account, + "Old Account {:?} dne New Account {:?} for NimbusID {:?}", + old_account.clone(), + new_account, + nimbus_id + ); + let new_deposit = info.deposit; + assert_eq!( + old_deposit.clone(), + new_deposit, + "Old Deposit {:?} dne New Deposit {:?} for NimbusID {:?}", + old_deposit.clone(), + new_deposit, + nimbus_id + ); + let nimbus_id_as_keys: T::Keys = nimbus_id.into(); + assert_eq!( + nimbus_id_as_keys, info.keys, + "Old NimbusID {:?} dne New Keys {:?}", + nimbus_id_as_keys, info.keys, + ); + } + Ok(()) + } +} diff --git a/external/pallets/author-mapping/src/mock.rs b/external/pallets/author-mapping/src/mock.rs new file mode 100644 index 000000000..619567c2c --- /dev/null +++ b/external/pallets/author-mapping/src/mock.rs @@ -0,0 +1,191 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! A minimal runtime including the author-mapping pallet +use crate as pallet_author_mapping; +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, GenesisBuild}, + weights::Weight, +}; +use nimbus_primitives::NimbusId; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_core::{ByteArray, H256}; +use sp_io; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + Perbill, RuntimeDebug, +}; + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum TestAuthor { + Alice, + Bob, + Charlie, +} +impl Default for TestAuthor { + fn default() -> TestAuthor { + TestAuthor::Alice + } +} +impl Into for TestAuthor { + fn into(self) -> NimbusId { + match self { + Self::Alice => NimbusId::from_slice(&[0u8; 32]), + Self::Bob => NimbusId::from_slice(&[1u8; 32]), + Self::Charlie => NimbusId::from_slice(&[2u8; 32]), + } + .expect("valid ids") + } +} + +pub type AccountId = u64; +pub type Balance = u128; +pub type BlockNumber = u32; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + AuthorMapping: pallet_author_mapping::{Pallet, Call, Storage, Config, Event}, + } +); + +parameter_types! { + pub const BlockHashCount: u32 = 250; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Config for Runtime { + type BaseCallFilter = Everything; + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} +impl pallet_balances::Config for Runtime { + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + pub const DepositAmount: Balance = 100; +} +impl pallet_author_mapping::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type DepositCurrency = Balances; + type DepositAmount = DepositAmount; + type Keys = NimbusId; + type WeightInfo = (); +} + +/// Externality builder for pallet author mapping's mock runtime +/// Allows configuring balances and initial mappings +pub(crate) struct ExtBuilder { + /// Accounts endowed with balances + balances: Vec<(AccountId, Balance)>, + /// AuthorId -> AccoutId mappings + mappings: Vec<(NimbusId, AccountId)>, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + mappings: vec![], + } + } +} + +impl ExtBuilder { + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub(crate) fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { + self.mappings = mappings; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: self.balances, + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + pallet_author_mapping::GenesisConfig:: { + mappings: self.mappings, + } + .assimilate_storage(&mut t) + .expect("Pallet author mapping's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +pub(crate) fn last_event() -> RuntimeEvent { + System::events().pop().expect("Event expected").event +} diff --git a/external/pallets/author-mapping/src/tests.rs b/external/pallets/author-mapping/src/tests.rs new file mode 100644 index 000000000..40fd4d01a --- /dev/null +++ b/external/pallets/author-mapping/src/tests.rs @@ -0,0 +1,480 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Unit testing +use crate::mock::{ + last_event, AuthorMapping, Balances, DepositAmount, ExtBuilder, Runtime, + RuntimeEvent as MetaEvent, RuntimeOrigin, System, TestAuthor, +}; +use crate::{keys_size, keys_wrapper, Error, Event, MappingWithDeposit, RegistrationInfo}; +use frame_support::{ + assert_noop, assert_ok, + traits::{OnRuntimeUpgrade, ReservableCurrency}, +}; +use nimbus_primitives::NimbusId; + +#[test] +fn check_key_size() { + // NimbusId (32) + NimbusId (32) + assert_eq!(keys_size::(), 64usize); +} + +#[test] +fn genesis_builder_works() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + assert_eq!(Balances::free_balance(&1), 900); + assert_eq!(Balances::reserved_balance(&1), 100); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Alice.into()), + Some(1) + ); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); + }) +} + +#[test] +fn eligible_account_can_register() { + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::add_association( + RuntimeOrigin::signed(2), + TestAuthor::Bob.into() + )); + + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Bob.into()), + Some(2) + ); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Bob.into(), + account_id: 2, + keys: TestAuthor::Bob.into(), + }) + ); + }) +} + +#[test] +fn cannot_add_association_without_deposit() { + ExtBuilder::default() + .with_balances(vec![(2, 10)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), + Error::::CannotAffordSecurityDeposit + ); + + assert_eq!(Balances::free_balance(&2), 10); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Alice.into()), + None + ); + }) +} + +#[test] +fn double_registration_costs_twice_as_much() { + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .build() + .execute_with(|| { + // Register once as Bob + assert_ok!(AuthorMapping::add_association( + RuntimeOrigin::signed(2), + TestAuthor::Bob.into() + )); + + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Bob.into()), + Some(2) + ); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Bob.into(), + account_id: 2, + keys: TestAuthor::Bob.into(), + }) + ); + + // Register again as Alice + assert_ok!(AuthorMapping::add_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into() + )); + + assert_eq!(Balances::free_balance(&2), 800); + assert_eq!(Balances::reserved_balance(&2), 200); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Alice.into()), + Some(2) + ); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Alice.into(), + account_id: 2, + keys: TestAuthor::Alice.into(), + }) + ); + + // Should still be registered as Bob as well + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Bob.into()), + Some(2) + ); + }) +} + +#[test] +fn registered_account_can_clear() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::remove_keys(RuntimeOrigin::signed(1))); + + assert_eq!(Balances::free_balance(&1), 1000); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Alice.into()), + None + ); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRemoved { + nimbus_id: TestAuthor::Alice.into(), + account_id: 1, + keys: TestAuthor::Alice.into(), + }) + ); + }) +} + +#[test] +fn unregistered_author_cannot_be_cleared() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + AuthorMapping::remove_keys(RuntimeOrigin::signed(1)), + Error::::OldAuthorIdNotFound + ); + }) +} + +#[test] +fn registered_author_cannot_be_cleared_by_non_owner() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::clear_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into() + ), + Error::::NotYourAssociation + ); + }) +} + +#[test] +fn registered_author_cannot_be_overwritten() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), + Error::::AlreadyAssociated + ); + }) +} + +#[test] +fn registered_can_rotate() { + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::update_association( + RuntimeOrigin::signed(2), + TestAuthor::Bob.into(), + TestAuthor::Charlie.into() + )); + + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), + Some(2) + ); + + // Should still only have paid a single security deposit + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + }) +} + +#[test] +fn unregistered_author_cannot_be_rotated() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + AuthorMapping::update_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into(), + TestAuthor::Bob.into() + ), + Error::::AssociationNotFound + ); + }) +} + +#[test] +fn registered_author_cannot_be_rotated_by_non_owner() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::update_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into(), + TestAuthor::Bob.into() + ), + Error::::NotYourAssociation + ); + }) +} + +#[test] +fn rotating_to_the_same_nimbus_id_leaves_registration_in_tact() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::update_association( + RuntimeOrigin::signed(1), + TestAuthor::Alice.into(), + TestAuthor::Alice.into() + )); + }) +} + +#[test] +fn eligible_account_can_full_register() { + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Alice.into()), + )); + + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Bob.into()), + Some(2) + ); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Bob.into(), + account_id: 2, + keys: TestAuthor::Alice.into(), + }) + ); + }) +} + +#[test] +fn cannot_set_keys_without_deposit() { + ExtBuilder::default() + .with_balances(vec![(2, 10)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), + ), + Error::::CannotAffordSecurityDeposit + ); + + assert_eq!(Balances::free_balance(&2), 10); + assert_eq!(AuthorMapping::keys_of(&TestAuthor::Alice.into()), None); + }) +} + +#[test] +fn full_registered_author_cannot_be_overwritten() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), + ), + Error::::AlreadyAssociated + ); + }) +} + +#[test] +fn registered_can_full_rotate() { + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Charlie.into(), TestAuthor::Charlie.into()) + )); + + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); + assert_eq!( + AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), + Some(2) + ); + assert_eq!( + AuthorMapping::keys_of(&TestAuthor::Charlie.into()), + Some(TestAuthor::Charlie.into()) + ); + + // Should still only have paid a single security deposit + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + }) +} + +#[test] +fn unregistered_author_can_be_full_rotated() { + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Bob.into()), + )); + }) +} + +#[test] +fn registered_author_cannot_be_full_rotated_by_non_owner() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()) + ), + Error::::AlreadyAssociated + ); + }) +} + +#[test] +fn full_rotating_to_the_same_nimbus_id_leaves_registration_in_tact() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(1), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Alice.into()) + )); + }) +} + +#[test] +fn add_reverse_mapping_migration_works() { + ExtBuilder::default() + .with_balances(vec![(1, 300)]) + .build() + .execute_with(|| { + // register 3 NimbusId owned by 1 account + let alice_as_nimbus: NimbusId = TestAuthor::Alice.into(); + let bob_as_nimbus: NimbusId = TestAuthor::Bob.into(); + let charlie_as_nimbus: NimbusId = TestAuthor::Charlie.into(); + MappingWithDeposit::::insert( + alice_as_nimbus.clone(), + RegistrationInfo { + account: 1, + deposit: DepositAmount::get(), + keys: alice_as_nimbus.clone(), + }, + ); + MappingWithDeposit::::insert( + bob_as_nimbus.clone(), + RegistrationInfo { + account: 1, + deposit: DepositAmount::get(), + keys: bob_as_nimbus.clone(), + }, + ); + MappingWithDeposit::::insert( + charlie_as_nimbus.clone(), + RegistrationInfo { + account: 1, + deposit: DepositAmount::get(), + keys: charlie_as_nimbus.clone(), + }, + ); + assert_ok!(Balances::reserve(&1, DepositAmount::get() * 3)); + // run migration + crate::migrations::AddAccountIdToNimbusLookup::::on_runtime_upgrade(); + // ensure last 2 mappings revoked => 200 unreserved but still 100 reserved + assert_eq!(Balances::free_balance(&1), DepositAmount::get() * 2); + assert_eq!(Balances::reserved_balance(&1), DepositAmount::get() * 1); + assert!(MappingWithDeposit::::get(bob_as_nimbus).is_some()); + assert!(MappingWithDeposit::::get(alice_as_nimbus).is_none()); + assert!(MappingWithDeposit::::get(charlie_as_nimbus).is_none()); + }) +} diff --git a/external/pallets/author-mapping/src/weights.rs b/external/pallets/author-mapping/src/weights.rs new file mode 100644 index 000000000..30fd8b6a6 --- /dev/null +++ b/external/pallets/author-mapping/src/weights.rs @@ -0,0 +1,159 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Autogenerated weights for pallet_author_mapping +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// * +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --template=./benchmarking/frame-weight-template.hbs +// --json-file +// raw.json +// --output +// ./tmp/ + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_author_mapping. +pub trait WeightInfo { + #[rustfmt::skip] + fn add_association() -> Weight; + #[rustfmt::skip] + fn update_association() -> Weight; + #[rustfmt::skip] + fn clear_association() -> Weight; + #[rustfmt::skip] + fn remove_keys() -> Weight; + #[rustfmt::skip] + fn set_keys() -> Weight; +} + +/// Weights for pallet_author_mapping using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) + #[rustfmt::skip] + fn add_association() -> Weight { + Weight::from_ref_time(50_753_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) + #[rustfmt::skip] + fn update_association() -> Weight { + Weight::from_ref_time(41_499_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) + #[rustfmt::skip] + fn clear_association() -> Weight { + Weight::from_ref_time(55_398_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn remove_keys() -> Weight { + Weight::from_ref_time(60_757_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + #[rustfmt::skip] + fn set_keys() -> Weight { + Weight::from_ref_time(45_388_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) + #[rustfmt::skip] + fn add_association() -> Weight { + Weight::from_ref_time(50_753_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) + #[rustfmt::skip] + fn update_association() -> Weight { + Weight::from_ref_time(41_499_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) + #[rustfmt::skip] + fn clear_association() -> Weight { + Weight::from_ref_time(55_398_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn remove_keys() -> Weight { + Weight::from_ref_time(60_757_000 as u64) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + #[rustfmt::skip] + fn set_keys() -> Weight { + Weight::from_ref_time(45_388_000 as u64) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } +} diff --git a/external/pallets/author-slot-filter/Cargo.toml b/external/pallets/author-slot-filter/Cargo.toml new file mode 100644 index 000000000..3d0cda7e9 --- /dev/null +++ b/external/pallets/author-slot-filter/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pallet-author-slot-filter" +authors = [ "PureStake" ] +description = "Selects a pseudorandom Subset of eligible (probably staked) authors at each slot" +edition = "2021" +version = "0.9.0" + +[dependencies] +frame-support = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-system = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +log = { version = "0.4.17", default-features = false } +nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } +parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } +serde = { version = "1.0.101", default-features = false, features = [ "derive" ] } +sp-core = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-std = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +# Benchmarks +frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", optional = true, default-features = false , branch = "moonbeam-polkadot-v0.9.29" } + +[dev-dependencies] +frame-support-test = { git = "https://github.com/zeitgeistpm/substrate", version = "3.0.0" , branch = "moonbeam-polkadot-v0.9.29" } +sp-io = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } + +[features] +default = [ "std" ] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] + +runtime-benchmarks = [ "frame-benchmarking", "nimbus-primitives/runtime-benchmarks" ] + +try-runtime = [ "frame-support/try-runtime", "nimbus-primitives/try-runtime" ] diff --git a/external/pallets/author-slot-filter/src/benchmarks.rs b/external/pallets/author-slot-filter/src/benchmarks.rs new file mode 100644 index 000000000..4a50a3a43 --- /dev/null +++ b/external/pallets/author-slot-filter/src/benchmarks.rs @@ -0,0 +1,50 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +use crate::num::NonZeroU32; +use crate::{Call, Config, Pallet}; +use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; +use frame_system::RawOrigin; + +benchmarks! { + set_eligible { + let count = NonZeroU32::new_unchecked(34); + }: _(RawOrigin::Root, count.clone()) + verify { + assert_eq!(Pallet::::eligible_count(), count); + } +} + +#[cfg(test)] +mod tests { + use crate::tests::Test; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + TestExternalities::new(t) + } +} + +impl_benchmark_test_suite!( + Pallet, + crate::benchmarks::tests::new_test_ext(), + crate::tests::Test +); diff --git a/external/pallets/author-slot-filter/src/lib.rs b/external/pallets/author-slot-filter/src/lib.rs new file mode 100644 index 000000000..a63adcffb --- /dev/null +++ b/external/pallets/author-slot-filter/src/lib.rs @@ -0,0 +1,227 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! Small pallet responsible determining which accounts are eligible to author at the current +//! slot. +//! +//! Using a randomness beacon supplied by the `Randomness` trait, this pallet takes the set of +//! currently active accounts from an upstream source, and filters them down to a pseudorandom subset. +//! The current technique gives no preference to any particular author. In the future, we could +//! disfavor authors who are authoring a disproportionate amount of the time in an attempt to +//! "even the playing field". + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[cfg(any(test, feature = "runtime-benchmarks"))] +mod benchmarks; + +pub mod migration; +pub mod num; +pub mod weights; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +#[frame_support::pallet] +pub mod pallet { + + use crate::num::NonZeroU32; + use crate::weights::WeightInfo; + use frame_support::{pallet_prelude::*, traits::Randomness}; + use frame_system::pallet_prelude::*; + use log::debug; + use nimbus_primitives::CanAuthor; + use sp_core::H256; + use sp_runtime::Percent; + use sp_std::vec::Vec; + + /// The Author Filter pallet + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type + type Event: From + IsType<::Event>; + /// Deterministic on-chain pseudo-randomness used to do the filtering + type RandomnessSource: Randomness; + //TODO introduce a new trait for exhaustive sets and use it here. + // Oh actually, we can use the same trait. First we call the inner one + // to determine whether this particular author is eligible there. then we + // use the author as part of the subject when querying eligibility. I like this better. + /// A source for the complete set of potential authors. + /// The starting point of the filtering. + type PotentialAuthors: Get>; + type WeightInfo: WeightInfo; + } + + /// Compute a pseudo-random subset of the input accounts by using Pallet's + /// source of randomness, `Config::RandomnessSource`. + /// Returns (Eligible, Ineligible), each is a set of accounts + pub fn compute_pseudo_random_subset( + mut active: Vec, + seed: &u32, + ) -> (Vec, Vec) { + let mut num_eligible = EligibleCount::::get().get() as usize; + if num_eligible > active.len() { + num_eligible = active.len(); + } + + let mut eligible = Vec::with_capacity(num_eligible); + + for i in 0..num_eligible { + // A context identifier for grabbing the randomness. Consists of three parts + // 1. Constant string *b"filter" - to identify this pallet + // 2. First 2 bytes of index.to_le_bytes when selecting the ith eligible author + // 3. First 4 bytes of seed.to_be_bytes + let mut first_two_bytes_of_index = &i.to_le_bytes()[..2]; + let mut first_four_bytes_of_seed = &seed.to_be_bytes()[..4]; + let mut constant_string: [u8; 6] = [b'f', b'i', b'l', b't', b'e', b'r']; + let mut subject: [u8; 12] = [0u8; 12]; + subject[..6].copy_from_slice(&mut constant_string); + subject[6..8].copy_from_slice(&mut first_two_bytes_of_index); + subject[8..].copy_from_slice(&mut first_four_bytes_of_seed); + let (randomness, _) = T::RandomnessSource::random(&subject); + debug!(target: "author-filter", "🎲Randomness sample {}: {:?}", i, &randomness); + + // Cast to u32 first so we get consistent results on 32- and 64-bit platforms. + let bytes: [u8; 4] = randomness.to_fixed_bytes()[0..4] + .try_into() + .expect("H256 has at least 4 bytes; qed"); + let randomness = u32::from_le_bytes(bytes) as usize; + + // Move the selected author from the original vector into the eligible vector + // TODO we could short-circuit this check by returning early when the claimed + // author is selected. For now I'll leave it like this because: + // 1. it is easier to understand what our core filtering logic is + // 2. we currently show the entire filtered set in the debug event + eligible.push(active.remove(randomness % active.len())); + } + (eligible, active) + } + + // This code will be called by the author-inherent pallet to check whether the reported author + // of this block is eligible in this slot. We calculate that result on demand and do not + // record it in storage (although we do emit a debugging event for now). + impl CanAuthor for Pallet { + #[cfg(not(feature = "try-runtime"))] + fn can_author(author: &T::AccountId, slot: &u32) -> bool { + // Compute pseudo-random subset of potential authors + let (eligible, ineligible) = + compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); + + // Print some logs for debugging purposes. + debug!(target: "author-filter", "Eligible Authors: {:?}", eligible); + debug!(target: "author-filter", "Ineligible Authors: {:?}", &ineligible); + debug!(target: "author-filter", + "Current author, {:?}, is eligible: {}", + author, + eligible.contains(author) + ); + + eligible.contains(author) + } + #[cfg(feature = "runtime-benchmarks")] + fn get_authors(slot: &u32) -> Vec { + // Compute pseudo-random subset of potential authors + let (eligible, _) = compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); + eligible + } + } + + #[pallet::call] + impl Pallet { + /// Update the eligible count. Intended to be called by governance. + #[pallet::weight(T::WeightInfo::set_eligible())] + pub fn set_eligible( + origin: OriginFor, + new: EligibilityValue, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + EligibleCount::::put(&new); + >::deposit_event(Event::EligibleUpdated(new)); + + Ok(Default::default()) + } + } + + /// The type of eligibility to use + pub type EligibilityValue = NonZeroU32; + + impl EligibilityValue { + /// Default total number of eligible authors, must NOT be 0. + pub fn default() -> Self { + NonZeroU32::new_unchecked(50) + } + } + + #[pallet::storage] + #[pallet::getter(fn eligible_ratio)] + #[deprecated(note = "use `pallet::EligibleCount` instead")] + pub type EligibleRatio = StorageValue<_, Percent, ValueQuery, Half>; + + // Default value for the `EligibleRatio` is one half. + #[pallet::type_value] + pub fn Half() -> Percent { + Percent::from_percent(50) + } + + /// The number of active authors that will be eligible at each height. + #[pallet::storage] + #[pallet::getter(fn eligible_count)] + pub type EligibleCount = + StorageValue<_, EligibilityValue, ValueQuery, DefaultEligibilityValue>; + + // Default value for the `EligibleCount`. + #[pallet::type_value] + pub fn DefaultEligibilityValue() -> EligibilityValue { + EligibilityValue::default() + } + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub eligible_count: EligibilityValue, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + eligible_count: EligibilityValue::default(), + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + EligibleCount::::put(self.eligible_count.clone()); + } + } + + #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] + pub enum Event { + /// The amount of eligible authors for the filter to select has been changed. + EligibleUpdated(EligibilityValue), + } +} diff --git a/external/pallets/author-slot-filter/src/migration.rs b/external/pallets/author-slot-filter/src/migration.rs new file mode 100644 index 000000000..79f02023d --- /dev/null +++ b/external/pallets/author-slot-filter/src/migration.rs @@ -0,0 +1,102 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use core::marker::PhantomData; +use frame_support::traits::Get; +use frame_support::traits::OnRuntimeUpgrade; +use frame_support::weights::Weight; +use parity_scale_codec::{Decode, Encode}; +use sp_runtime::Percent; +use sp_std::vec::Vec; + +use super::num::NonZeroU32; +use super::pallet::Config; +use super::pallet::EligibilityValue; +use super::pallet::EligibleCount; +use super::pallet::Pallet; +pub struct EligibleRatioToEligiblityCount(PhantomData); + +impl OnRuntimeUpgrade for EligibleRatioToEligiblityCount +where + T: Config, +{ + fn on_runtime_upgrade() -> Weight { + log::info!(target: "EligibleRatioToEligiblityCount", "starting migration"); + + let old_value = >::eligible_ratio(); + let total_authors = ::PotentialAuthors::get().len(); + let new_value = percent_of_num(old_value, total_authors as u32); + let new_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); + >::put(new_value); + + T::DbWeight::get().reads_writes(1, 1) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let old_value = >::eligible_ratio(); + + let total_authors = ::PotentialAuthors::get().len(); + let new_value = percent_of_num(old_value, total_authors as u32); + let expected_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); + + Ok(expected_value.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + let expected: NonZeroU32 = + Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + let actual = >::eligible_count(); + + assert_eq!(expected, actual); + + Ok(()) + } +} + +fn percent_of_num(percent: Percent, num: u32) -> u32 { + percent.mul_ceil(num as u32) +} + +#[cfg(test)] +mod tests { + use super::percent_of_num; + use super::*; + + #[test] + fn test_percent_of_num_ceils_value() { + let fifty_percent = Percent::from_float(0.5); + + let actual = percent_of_num(fifty_percent, 5); + assert_eq!(3, actual); + + let actual = percent_of_num(fifty_percent, 20); + assert_eq!(10, actual); + } + + #[test] + fn test_percent_of_num_hundred_percent_uses_full_value() { + let one_hundred_percent = Percent::from_float(1.0); + + let actual = percent_of_num(one_hundred_percent, 5); + assert_eq!(5, actual); + + let actual = percent_of_num(one_hundred_percent, 20); + assert_eq!(20, actual); + } +} diff --git a/external/pallets/author-slot-filter/src/mock.rs b/external/pallets/author-slot-filter/src/mock.rs new file mode 100644 index 000000000..1fdbe069a --- /dev/null +++ b/external/pallets/author-slot-filter/src/mock.rs @@ -0,0 +1,92 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use crate as pallet_testing; +use frame_support::parameter_types; +use frame_support::sp_io; +use frame_support::traits::ConstU32; +use frame_support::weights::RuntimeDbWeight; +use frame_support_test::TestRandomness; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + AuthorSlotFilter: pallet_testing::{Pallet, Call, Storage, Event}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub Authors: Vec = vec![1, 2, 3, 4, 5]; + pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 1, + write: 10, + }; +} + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = TestDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_testing::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RandomnessSource = TestRandomness; + type PotentialAuthors = Authors; + type WeightInfo = (); +} + +/// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + frame_system::GenesisConfig::default() + .build_storage::() + .unwrap() + .into() +} diff --git a/external/pallets/author-slot-filter/src/num.rs b/external/pallets/author-slot-filter/src/num.rs new file mode 100644 index 000000000..e38daad73 --- /dev/null +++ b/external/pallets/author-slot-filter/src/num.rs @@ -0,0 +1,127 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +//! Implements a [NonZeroU32] type that interplays nicely with the +//! subtrate storage and the SCALE codec. + +use parity_scale_codec::{Decode, Encode, Error, Input}; +use scale_info::TypeInfo; +use serde::de::Error as DeserializeError; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Clone, Debug, TypeInfo, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct NonZeroU32(u32); + +impl core::ops::Deref for NonZeroU32 { + type Target = u32; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl parity_scale_codec::EncodeLike for NonZeroU32 {} + +impl NonZeroU32 { + /// Creates a new `Some(NonZeroU32)` instance if value is 0, `None` otherwise. + #[inline] + pub const fn new(n: u32) -> Option { + if n != 0 { + Some(Self(n)) + } else { + None + } + } + + /// new_unchecked creats a `NonZeroU32` where the user MUST guarantee + /// that the value is nonzero. + #[inline] + pub const fn new_unchecked(n: u32) -> Self { + Self(n) + } + + /// Returns the the underlying number + pub fn get(&self) -> u32 { + self.0 + } +} + +#[cfg(feature = "std")] +impl Serialize for NonZeroU32 { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.clone().get().serialize(serializer) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for NonZeroU32 { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = Deserialize::deserialize(deserializer)?; + match NonZeroU32::new(value) { + Some(nonzero) => Ok(nonzero), + None => Err(DeserializeError::custom("expected a non-zero value")), + } + } +} + +impl Decode for NonZeroU32 { + fn decode(input: &mut I) -> Result { + Self::new(Decode::decode(input)?) + .ok_or_else(|| Error::from("cannot create non-zero number from 0")) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use parity_scale_codec::Encode; + + #[test] + fn test_new_returns_none_if_zero() { + assert_eq!(None, NonZeroU32::new(0)); + } + + #[test] + fn test_new_returns_some_if_nonzero() { + let n = 10; + let expected = Some(NonZeroU32::new_unchecked(n)); + + let actual = NonZeroU32::new(n); + assert_eq!(expected, actual); + assert_eq!(n, actual.unwrap().get()); + } + + #[test] + fn test_decode_errors_if_zero_value() { + let buf: Vec = 0u32.encode(); + let result = NonZeroU32::decode(&mut &buf[..]); + assert!(result.is_err(), "expected error, got {:?}", result); + } + + #[test] + fn test_decode_succeeds_if_nonzero_value() { + let buf: Vec = 1u32.encode(); + + let result = NonZeroU32::decode(&mut &buf[..]); + assert!(result.is_ok(), "unexpected error, got {:?}", result); + assert_eq!(Ok(NonZeroU32::new_unchecked(1)), result); + } +} diff --git a/external/pallets/author-slot-filter/src/tests.rs b/external/pallets/author-slot-filter/src/tests.rs new file mode 100644 index 000000000..cae418ad8 --- /dev/null +++ b/external/pallets/author-slot-filter/src/tests.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Nimbus. + +// Nimbus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Nimbus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Nimbus. If not, see . + +use super::*; +use crate::mock::*; +use crate::num::NonZeroU32; + +use frame_support::assert_ok; +use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; +use sp_runtime::Percent; + +#[test] +fn test_set_eligibility_works() { + new_test_ext().execute_with(|| { + let value = num::NonZeroU32::new_unchecked(34); + + assert_ok!(AuthorSlotFilter::set_eligible( + RuntimeOrigin::root(), + value.clone() + )); + assert_eq!(AuthorSlotFilter::eligible_count(), value) + }); +} + +#[allow(deprecated)] +#[test] +fn test_migration_works_for_converting_existing_eligible_ratio_to_eligible_count() { + new_test_ext().execute_with(|| { + let input_eligible_ratio = Percent::from_percent(50); + let total_author_count = mock::Authors::get().len(); + let eligible_author_count = input_eligible_ratio.mul_ceil(total_author_count) as u32; + let expected_eligible_count = NonZeroU32::new_unchecked(eligible_author_count); + let expected_weight = + Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); + + >::put(input_eligible_ratio); + + let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); + assert_eq!(expected_weight, actual_weight); + + let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); + let actual_eligible_count = AuthorSlotFilter::eligible_count(); + assert_eq!(expected_eligible_count, actual_eligible_count); + assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); + }); +} + +#[allow(deprecated)] +#[test] +fn test_migration_works_for_converting_existing_zero_eligible_ratio_to_default_eligible_count() { + new_test_ext().execute_with(|| { + let input_eligible_ratio = Percent::from_percent(0); + let expected_eligible_count = EligibilityValue::default(); + let expected_weight = + Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); + + >::put(input_eligible_ratio); + + let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); + assert_eq!(expected_weight, actual_weight); + + let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); + let actual_eligible_count = AuthorSlotFilter::eligible_count(); + assert_eq!(expected_eligible_count, actual_eligible_count); + assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); + }); +} + +#[allow(deprecated)] +#[test] +fn test_migration_inserts_default_value_for_missing_eligible_ratio() { + new_test_ext().execute_with(|| { + let default_eligible_ratio = Percent::from_percent(50); + let expected_default_eligible_count = + NonZeroU32::new_unchecked(default_eligible_ratio.mul_ceil(Authors::get().len() as u32)); + let expected_weight = + Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); + + let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); + assert_eq!(expected_weight, actual_weight); + + let actual_eligible_count = AuthorSlotFilter::eligible_count(); + assert_eq!(expected_default_eligible_count, actual_eligible_count); + }); +} diff --git a/external/pallets/author-slot-filter/src/weights.rs b/external/pallets/author-slot-filter/src/weights.rs new file mode 100644 index 000000000..8542f0aa7 --- /dev/null +++ b/external/pallets/author-slot-filter/src/weights.rs @@ -0,0 +1,71 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Autogenerated weights for pallet_author_slot_filter +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-07, STEPS: `32`, REPEAT: 64, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// --chain +// dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// pallet_author_slot_filter +// --extrinsic +// * +// --steps +// 32 +// --repeat +// 64 +// --template=./benchmarking/frame-weight-template.hbs +// --output +// /tmp/ +// --record-proof + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_author_slot_filter. +pub trait WeightInfo { + fn set_eligible() -> Weight; +} + +/// Weights for pallet_author_slot_filter using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn set_eligible() -> Weight { + Weight::from_ref_time(13_250_000 as u64).saturating_add(T::DbWeight::get().writes(1 as u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn set_eligible() -> Weight { + Weight::from_ref_time(13_250_000 as u64) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } +} diff --git a/external/pallets/parachain-staking/Cargo.toml b/external/pallets/parachain-staking/Cargo.toml new file mode 100644 index 000000000..70e74825d --- /dev/null +++ b/external/pallets/parachain-staking/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pallet-parachain-staking" +authors = [ "PureStake" ] +description = "parachain staking pallet for collator selection and reward distribution" +edition = "2021" +version = "3.0.0" + +[dependencies] +log = "0.4" +serde = { version = "1.0.101", optional = true } + +# Substrate +frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", optional = true, default-features = false } +frame-support = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +frame-system = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-std = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } + +# Nimbus +nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } + +[dev-dependencies] +pallet-balances = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +similar-asserts = "1.1.0" +sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-io = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } + +[features] +default = [ "std" ] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ "frame-benchmarking" ] +try-runtime = [ "frame-support/try-runtime" ] diff --git a/external/pallets/parachain-staking/README.md b/external/pallets/parachain-staking/README.md new file mode 100644 index 000000000..e169fe702 --- /dev/null +++ b/external/pallets/parachain-staking/README.md @@ -0,0 +1,26 @@ +# DPoS Pallet for Parachain Staking + +## Formatting Rules + +- dependencies in alphabetical order in the `Cargo.toml` and at the top of each file +- prefer explicit imports to glob import syntax i.e. prefer `use::crate::{Ex1, Ex2, ..};` to `use super::*;` + +## Description + +Implements Delegated Proof of Stake to + +1. select the active set of eligible block producers +2. reward block authors +3. enable delegators and collators to participate in inflationary rewards + +Links: + +- [Rust Documentation](https://purestake.github.io/moonbeam/pallet_parachain_staking/index.html) +- [Unofficial Documentation](https://meta5.world/parachain-staking-docs/) +- [(Outdated) Blog Post with Justification](https://meta5.world/posts/parachain-staking) + +## History + +Since January 2021, Moonbeam's team has maintained this Delegated Proof of Stake (DPoS) pallet designed specifically for parachains. + +Since April 2021, the development of this pallet has been supported by [a Web3 Foundation grant](https://github.com/w3f/Grants-Program/pull/389). The [first milestone](https://github.com/w3f/Grant-Milestone-Delivery/pull/218) was approved in June 2021. diff --git a/external/pallets/parachain-staking/migrations.md b/external/pallets/parachain-staking/migrations.md new file mode 100644 index 000000000..d2277ffcd --- /dev/null +++ b/external/pallets/parachain-staking/migrations.md @@ -0,0 +1,42 @@ +# Migration History + +## Calculate outgoing rewards based on pending revoke and decrease changes + +- [Migration PR `#1408`](https://github.com/PureStake/moonbeam/pull/1408) + +## Patch delegations total mismatch + +- [Migration PR `#1291`](https://github.com/PureStake/moonbeam/pull/1291) + +## Split candidate state for PoV optimization + +- [Migration PR `#1117`](https://github.com/PureStake/moonbeam/pull/1117) + +## Increase max delegations per candidate + +- [Migration PR `#1096`](https://github.com/PureStake/moonbeam/pull/1096) +- [Migratio bugfix `#1112`](https://github.com/PureStake/moonbeam/pull/1112) + +## Manual Exits and Patch Lack of Delay for bond\_{more, less} + +- [Migration PR `#810`](https://github.com/PureStake/moonbeam/pull/810) +- [Migration Removal PR `#?`]() + +## Purge Stale Storage + +- [Migration PR `#970`](https://github.com/PureStake/moonbeam/pull/970) + +## Delay nominator exits by changing NominatorState and ExitQueue + +- [Migration PR `#610`](https://github.com/PureStake/moonbeam/pull/610) +- [Migration Removal PR `#662`](https://github.com/PureStake/moonbeam/pull/662) + +## Patch nomination DOS attack vector by changing CollatorState + +- [Migration PR `#505`](https://github.com/PureStake/moonbeam/pull/505) +- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) + +## Patch underflow bug and correct Total storage item + +- [Migration PR `#502`](https://github.com/PureStake/moonbeam/pull/502) +- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) diff --git a/external/pallets/parachain-staking/src/auto_compound.rs b/external/pallets/parachain-staking/src/auto_compound.rs new file mode 100644 index 000000000..653c96ff9 --- /dev/null +++ b/external/pallets/parachain-staking/src/auto_compound.rs @@ -0,0 +1,377 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Auto-compounding functionality for staking rewards + +use crate::pallet::{ + AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, CandidateInfo, + Config, DelegatorState, Error, Event, Pallet, Total, +}; +use crate::types::{Bond, BondAdjust, Delegator}; +use frame_support::ensure; +use frame_support::traits::Get; +use frame_support::{dispatch::DispatchResultWithPostInfo, RuntimeDebug}; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_runtime::traits::Saturating; +use sp_runtime::Percent; +use sp_std::prelude::*; +use sp_std::vec::Vec; + +/// Represents the auto-compounding amount for a delegation. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] +pub struct AutoCompoundConfig { + pub delegator: AccountId, + pub value: Percent, +} + +/// Represents the auto-compounding [Delegations] for `T: Config` +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +pub struct AutoCompoundDelegations(Vec>); + +impl AutoCompoundDelegations +where + T: Config, +{ + /// Creates a new instance of [AutoCompoundingDelegations] from a vector of sorted_delegations. + /// This is used for testing purposes only. + #[cfg(test)] + pub fn new(sorted_delegations: Vec>) -> Self { + Self(sorted_delegations) + } + + /// Retrieves an instance of [AutoCompoundingDelegations] storage as [AutoCompoundDelegations]. + pub fn get_storage(candidate: &T::AccountId) -> Self { + Self(>::get(candidate)) + } + + /// Inserts the current state to [AutoCompoundingDelegations] storage. + pub fn set_storage(self, candidate: &T::AccountId) { + >::insert(candidate, self.0) + } + + /// Retrieves the auto-compounding value for a delegation. The `delegations_config` must be a + /// sorted vector for binary_search to work. + pub fn get_for_delegator(&self, delegator: &T::AccountId) -> Option { + match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { + Ok(index) => Some(self.0[index].value), + Err(_) => None, + } + } + + /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted + /// vector for binary_search to work. + pub fn set_for_delegator(&mut self, delegator: T::AccountId, value: Percent) -> bool { + match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { + Ok(index) => { + if self.0[index].value == value { + false + } else { + self.0[index].value = value; + true + } + } + Err(index) => { + self.0 + .insert(index, AutoCompoundConfig { delegator, value }); + true + } + } + } + + /// Removes the auto-compounding value for a delegation. + /// Returns `true` if the entry was removed, `false` otherwise. The `delegations_config` must be a + /// sorted vector for binary_search to work. + pub fn remove_for_delegator(&mut self, delegator: &T::AccountId) -> bool { + match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { + Ok(index) => { + self.0.remove(index); + true + } + Err(_) => false, + } + } + + /// Returns the length of the inner vector. + pub fn len(&self) -> u32 { + self.0.len() as u32 + } + + /// Returns a reference to the inner vector. + #[cfg(test)] + pub fn inner(&self) -> &Vec> { + &self.0 + } + + /// Converts the [AutoCompoundDelegations] into the inner vector. + #[cfg(test)] + pub fn into_inner(self) -> Vec> { + self.0 + } + + // -- pallet functions -- + + /// Delegates and sets the auto-compounding config. The function skips inserting auto-compound + /// storage and validation, if the auto-compound value is 0%. + pub(crate) fn delegate_with_auto_compound( + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + auto_compound: Percent, + candidate_delegation_count_hint: u32, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + // check that caller can lock the amount before any changes to storage + ensure!( + >::get_delegator_stakable_free_balance(&delegator) >= amount, + Error::::InsufficientBalance + ); + + let mut delegator_state = if let Some(mut state) = >::get(&delegator) { + // delegation after first + ensure!( + amount >= T::MinDelegation::get(), + Error::::DelegationBelowMin + ); + ensure!( + delegation_count_hint >= state.delegations.0.len() as u32, + Error::::TooLowDelegationCountToDelegate + ); + ensure!( + (state.delegations.0.len() as u32) < T::MaxDelegationsPerDelegator::get(), + Error::::ExceedMaxDelegationsPerDelegator + ); + ensure!( + state.add_delegation(Bond { + owner: candidate.clone(), + amount + }), + Error::::AlreadyDelegatedCandidate + ); + state + } else { + // first delegation + ensure!( + amount >= T::MinDelegatorStk::get(), + Error::::DelegatorBondBelowMin + ); + ensure!( + !>::is_candidate(&delegator), + Error::::CandidateExists + ); + Delegator::new(delegator.clone(), candidate.clone(), amount) + }; + let mut candidate_state = + >::get(&candidate).ok_or(Error::::CandidateDNE)?; + ensure!( + candidate_delegation_count_hint >= candidate_state.delegation_count, + Error::::TooLowCandidateDelegationCountToDelegate + ); + + let auto_compounding_state = if !auto_compound.is_zero() { + let auto_compounding_state = Self::get_storage(&candidate); + ensure!( + auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, + >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, + ); + Some(auto_compounding_state) + } else { + None + }; + + // add delegation to candidate + let (delegator_position, less_total_staked) = candidate_state.add_delegation::( + &candidate, + Bond { + owner: delegator.clone(), + amount, + }, + )?; + + // lock delegator amount + delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; + + // adjust total locked, + // only is_some if kicked the lowest bottom as a consequence of this new delegation + let net_total_increase = if let Some(less) = less_total_staked { + amount.saturating_sub(less) + } else { + amount + }; + let new_total_locked = >::get().saturating_add(net_total_increase); + + // maybe set auto-compound config, state is Some if the percent is non-zero + if let Some(mut state) = auto_compounding_state { + state.set_for_delegator(delegator.clone(), auto_compound.clone()); + state.set_storage(&candidate); + } + + >::put(new_total_locked); + >::insert(&candidate, candidate_state); + >::insert(&delegator, delegator_state); + >::deposit_event(Event::Delegation { + delegator: delegator, + locked_amount: amount, + candidate: candidate, + delegator_position: delegator_position, + auto_compound, + }); + + Ok(().into()) + } + + /// Sets the auto-compounding value for a delegation. The config is removed if value is zero. + pub(crate) fn set_auto_compound( + candidate: T::AccountId, + delegator: T::AccountId, + value: Percent, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + let delegator_state = + >::get(&delegator).ok_or(>::DelegatorDNE)?; + ensure!( + delegator_state.delegations.0.len() <= delegation_count_hint as usize, + >::TooLowDelegationCountToAutoCompound, + ); + ensure!( + delegator_state + .delegations + .0 + .iter() + .any(|b| b.owner == candidate), + >::DelegationDNE, + ); + + let mut auto_compounding_state = Self::get_storage(&candidate); + ensure!( + auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, + >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + ); + let state_updated = if value.is_zero() { + auto_compounding_state.remove_for_delegator(&delegator) + } else { + auto_compounding_state.set_for_delegator(delegator.clone(), value) + }; + if state_updated { + auto_compounding_state.set_storage(&candidate); + } + + >::deposit_event(Event::AutoCompoundSet { + candidate, + delegator, + value, + }); + + Ok(().into()) + } + + /// Removes the auto-compounding value for a delegation. This should be called when the + /// delegation is revoked to cleanup storage. Storage is only written iff the entry existed. + pub(crate) fn remove_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) { + let mut auto_compounding_state = Self::get_storage(candidate); + if auto_compounding_state.remove_for_delegator(delegator) { + auto_compounding_state.set_storage(&candidate); + } + } + + /// Returns the value of auto-compound, if it exists for a given delegation, zero otherwise. + pub(crate) fn auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { + let delegations_config = Self::get_storage(candidate); + delegations_config + .get_for_delegator(&delegator) + .unwrap_or_else(|| Percent::zero()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::Test; + + #[test] + fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { + let mut delegations_config = AutoCompoundDelegations::::new(vec![]); + assert_eq!( + true, + delegations_config.set_for_delegator(1, Percent::from_percent(50)) + ); + assert_eq!( + vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(50), + }], + delegations_config.into_inner(), + ); + } + + #[test] + fn test_set_for_delegator_updates_config_and_returns_true_if_entry_changed() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }]); + assert_eq!( + true, + delegations_config.set_for_delegator(1, Percent::from_percent(50)) + ); + assert_eq!( + vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(50), + }], + delegations_config.into_inner(), + ); + } + + #[test] + fn test_set_for_delegator_updates_config_and_returns_false_if_entry_unchanged() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }]); + assert_eq!( + false, + delegations_config.set_for_delegator(1, Percent::from_percent(10)) + ); + assert_eq!( + vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }], + delegations_config.into_inner(), + ); + } + + #[test] + fn test_remove_for_delegator_returns_false_if_entry_was_missing() { + let mut delegations_config = AutoCompoundDelegations::::new(vec![]); + assert_eq!(false, delegations_config.remove_for_delegator(&1),); + } + + #[test] + fn test_remove_delegation_config_returns_true_if_entry_existed() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }]); + assert_eq!(true, delegations_config.remove_for_delegator(&1)); + } +} diff --git a/external/pallets/parachain-staking/src/benchmarks.rs b/external/pallets/parachain-staking/src/benchmarks.rs new file mode 100644 index 000000000..a34536d04 --- /dev/null +++ b/external/pallets/parachain-staking/src/benchmarks.rs @@ -0,0 +1,1502 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +//! Benchmarking +use crate::{ + AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, + ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, + Staked, TopDelegations, +}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; +use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; +use frame_system::RawOrigin; +use sp_runtime::{Perbill, Percent}; +use sp_std::vec::Vec; + +/// Minimum collator candidate stake +fn min_candidate_stk() -> BalanceOf { + <::MinCollatorStk as Get>>::get() +} + +/// Minimum delegator stake +fn min_delegator_stk() -> BalanceOf { + <::MinDelegatorStk as Get>>::get() +} + +/// Create a funded user. +/// Extra + min_candidate_stk is total minted funds +/// Returns tuple (id, balance) +fn create_funded_user( + string: &'static str, + n: u32, + extra: BalanceOf, +) -> (T::AccountId, BalanceOf) { + const SEED: u32 = 0; + let user = account(string, n, SEED); + let min_candidate_stk = min_candidate_stk::(); + let total = min_candidate_stk + extra; + T::Currency::make_free_balance_be(&user, total); + T::Currency::issue(total); + (user, total) +} + +/// Create a funded delegator. +fn create_funded_delegator( + string: &'static str, + n: u32, + extra: BalanceOf, + collator: T::AccountId, + min_bond: bool, + collator_delegator_count: u32, +) -> Result { + let (user, total) = create_funded_user::(string, n, extra); + let bond = if min_bond { + min_delegator_stk::() + } else { + total + }; + Pallet::::delegate( + RawOrigin::Signed(user.clone()).into(), + collator, + bond, + collator_delegator_count, + 0u32, // first delegation for all calls + )?; + Ok(user) +} + +/// Create a funded collator. +fn create_funded_collator( + string: &'static str, + n: u32, + extra: BalanceOf, + min_bond: bool, + candidate_count: u32, +) -> Result { + let (user, total) = create_funded_user::(string, n, extra); + let bond = if min_bond { + min_candidate_stk::() + } else { + total + }; + Pallet::::join_candidates( + RawOrigin::Signed(user.clone()).into(), + bond, + candidate_count, + )?; + Ok(user) +} + +// Simulate staking on finalize by manually setting points +fn parachain_staking_on_finalize(author: T::AccountId) { + let now = >::get().current; + let score_plus_20 = >::get(now, &author).saturating_add(20); + >::insert(now, author, score_plus_20); + >::mutate(now, |x| *x = x.saturating_add(20)); +} + +/// Run to end block and author +fn roll_to_and_author(round_delay: u32, author: T::AccountId) { + let total_rounds = round_delay + 1u32; + let round_length: T::BlockNumber = Pallet::::round().length.into(); + let mut now = >::block_number() + 1u32.into(); + let end = Pallet::::round().first + (round_length * total_rounds.into()); + while now < end { + parachain_staking_on_finalize::(author.clone()); + >::on_finalize(>::block_number()); + >::set_block_number( + >::block_number() + 1u32.into(), + ); + >::on_initialize(>::block_number()); + Pallet::::on_initialize(>::block_number()); + now += 1u32.into(); + } +} + +const USER_SEED: u32 = 999666; +struct Seed { + pub inner: u32, +} +impl Seed { + fn new() -> Self { + Seed { inner: USER_SEED } + } + + pub fn take(&mut self) -> u32 { + let v = self.inner; + self.inner += 1; + v + } +} + +benchmarks! { + // MONETARY ORIGIN DISPATCHABLES + set_staking_expectations { + let stake_range: Range> = Range { + min: 100u32.into(), + ideal: 200u32.into(), + max: 300u32.into(), + }; + }: _(RawOrigin::Root, stake_range) + verify { + assert_eq!(Pallet::::inflation_config().expect, stake_range); + } + + set_inflation { + let inflation_range: Range = Range { + min: Perbill::from_perthousand(1), + ideal: Perbill::from_perthousand(2), + max: Perbill::from_perthousand(3), + }; + + }: _(RawOrigin::Root, inflation_range) + verify { + assert_eq!(Pallet::::inflation_config().annual, inflation_range); + } + + set_parachain_bond_account { + let parachain_bond_account: T::AccountId = account("TEST", 0u32, USER_SEED); + }: _(RawOrigin::Root, parachain_bond_account.clone()) + verify { + assert_eq!(Pallet::::parachain_bond_info().account, parachain_bond_account); + } + + set_parachain_bond_reserve_percent { + }: _(RawOrigin::Root, Percent::from_percent(33)) + verify { + assert_eq!(Pallet::::parachain_bond_info().percent, Percent::from_percent(33)); + } + + // ROOT DISPATCHABLES + + set_total_selected { + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; + }: _(RawOrigin::Root, 100u32) + verify { + assert_eq!(Pallet::::total_selected(), 100u32); + } + + set_collator_commission {}: _(RawOrigin::Root, Perbill::from_percent(33)) + verify { + assert_eq!(Pallet::::collator_commission(), Perbill::from_percent(33)); + } + + set_blocks_per_round {}: _(RawOrigin::Root, 1200u32) + verify { + assert_eq!(Pallet::::round().length, 1200u32); + } + + // USER DISPATCHABLES + + join_candidates { + let x in 3..1_000; + // Worst Case Complexity is insertion into an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let (caller, min_candidate_stk) = create_funded_user::("caller", USER_SEED, 0u32.into()); + }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk, candidate_count) + verify { + assert!(Pallet::::is_candidate(&caller)); + } + + // This call schedules the collator's exit and removes them from the candidate pool + // -> it retains the self-bond and delegator bonds + schedule_leave_candidates { + let x in 3..1_000; + // Worst Case Complexity is removal from an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let caller: T::AccountId = create_funded_collator::( + "caller", + USER_SEED, + 0u32.into(), + true, + candidate_count, + )?; + candidate_count += 1u32; + }: _(RawOrigin::Signed(caller.clone()), candidate_count) + verify { + assert!(Pallet::::candidate_info(&caller).unwrap().is_leaving()); + } + + execute_leave_candidates { + // x is total number of delegations for the candidate + let x in 2..(<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get()); + let candidate: T::AccountId = create_funded_collator::( + "unique_caller", + USER_SEED - 100, + 0u32.into(), + true, + 1u32, + )?; + // 2nd delegation required for all delegators to ensure DelegatorState updated not removed + let second_candidate: T::AccountId = create_funded_collator::( + "unique__caller", + USER_SEED - 99, + 0u32.into(), + true, + 2u32, + )?; + let mut delegators: Vec = Vec::new(); + let mut col_del_count = 0u32; + for i in 1..x { + let seed = USER_SEED + i; + let delegator = create_funded_delegator::( + "delegator", + seed, + min_delegator_stk::(), + candidate.clone(), + true, + col_del_count, + )?; + Pallet::::delegate( + RawOrigin::Signed(delegator.clone()).into(), + second_candidate.clone(), + min_delegator_stk::(), + col_del_count, + 1u32, + )?; + Pallet::::schedule_revoke_delegation( + RawOrigin::Signed(delegator.clone()).into(), + candidate.clone() + )?; + delegators.push(delegator); + col_del_count += 1u32; + } + Pallet::::schedule_leave_candidates( + RawOrigin::Signed(candidate.clone()).into(), + 3u32 + )?; + roll_to_and_author::(2, candidate.clone()); + }: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count) + verify { + assert!(Pallet::::candidate_info(&candidate).is_none()); + assert!(Pallet::::candidate_info(&second_candidate).is_some()); + for delegator in delegators { + assert!(Pallet::::is_delegator(&delegator)); + } + } + + cancel_leave_candidates { + let x in 3..1_000; + // Worst Case Complexity is removal from an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let caller: T::AccountId = create_funded_collator::( + "caller", + USER_SEED, + 0u32.into(), + true, + candidate_count, + )?; + candidate_count += 1u32; + Pallet::::schedule_leave_candidates( + RawOrigin::Signed(caller.clone()).into(), + candidate_count + )?; + candidate_count -= 1u32; + }: _(RawOrigin::Signed(caller.clone()), candidate_count) + verify { + assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); + } + + go_offline { + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(!Pallet::::candidate_info(&caller).unwrap().is_active()); + } + + go_online { + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + Pallet::::go_offline(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); + } + + candidate_bond_more { + let more = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + more, + true, + 1u32, + )?; + }: _(RawOrigin::Signed(caller.clone()), more) + verify { + let expected_bond = more * 2u32.into(); + assert_eq!( + Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, + expected_bond, + ); + } + + schedule_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk) + verify { + let state = Pallet::::candidate_info(&caller).expect("request bonded less so exists"); + assert_eq!( + state.request, + Some(CandidateBondLessRequest { + amount: min_candidate_stk, + when_executable: 3, + }) + ); + } + + execute_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + Pallet::::schedule_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + min_candidate_stk + )?; + roll_to_and_author::(2, caller.clone()); + }: { + Pallet::::execute_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + caller.clone() + )?; + } verify { + assert_eq!( + Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, + min_candidate_stk, + ); + } + + cancel_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + Pallet::::schedule_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + min_candidate_stk + )?; + }: { + Pallet::::cancel_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + )?; + } verify { + assert!( + Pallet::::candidate_info(&caller).unwrap().request.is_none() + ); + } + + delegate { + let x in 3..<::MaxDelegationsPerDelegator as Get>::get(); + let y in 2..<::MaxTopDelegationsPerCandidate as Get>::get(); + // Worst Case is full of delegations before calling `delegate` + let mut collators: Vec = Vec::new(); + // Initialize MaxDelegationsPerDelegator collator candidates + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + collators.len() as u32 + 1u32, + )?; + collators.push(collator.clone()); + } + let bond = <::MinDelegatorStk as Get>>::get(); + let extra = if (bond * (collators.len() as u32 + 1u32).into()) > min_candidate_stk::() { + (bond * (collators.len() as u32 + 1u32).into()) - min_candidate_stk::() + } else { + 0u32.into() + }; + let (caller, _) = create_funded_user::("caller", USER_SEED, extra.into()); + // Delegation count + let mut del_del_count = 0u32; + // Nominate MaxDelegationsPerDelegators collator candidates + for col in collators.clone() { + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), col, bond, 0u32, del_del_count + )?; + del_del_count += 1u32; + } + // Last collator to be delegated + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + collators.len() as u32 + 1u32, + )?; + // Worst Case Complexity is insertion into an almost full collator + let mut col_del_count = 0u32; + for i in 1..y { + let seed = USER_SEED + i; + let _ = create_funded_delegator::( + "delegator", + seed, + 0u32.into(), + collator.clone(), + true, + col_del_count, + )?; + col_del_count += 1u32; + } + }: _(RawOrigin::Signed(caller.clone()), collator, bond, col_del_count, del_del_count) + verify { + assert!(Pallet::::is_delegator(&caller)); + } + + schedule_leave_delegators { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!( + Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|r| r.delegator == caller && matches!(r.action, DelegationAction::Revoke(_))) + ); + } + + execute_leave_delegators { + let x in 2..<::MaxDelegationsPerDelegator as Get>::get(); + // Worst Case is full of delegations before execute exit + let mut collators: Vec = Vec::new(); + // Initialize MaxDelegationsPerDelegator collator candidates + for i in 1..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + collators.len() as u32 + 1u32 + )?; + collators.push(collator.clone()); + } + let bond = <::MinDelegatorStk as Get>>::get(); + let need = bond * (collators.len() as u32).into(); + let default_minted = min_candidate_stk::(); + let need: BalanceOf = if need > default_minted { + need - default_minted + } else { + 0u32.into() + }; + // Fund the delegator + let (caller, _) = create_funded_user::("caller", USER_SEED, need); + // Delegation count + let mut delegation_count = 0u32; + let author = collators[0].clone(); + // Nominate MaxDelegationsPerDelegators collator candidates + for col in collators { + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), + col, + bond, + 0u32, + delegation_count + )?; + delegation_count += 1u32; + } + Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; + roll_to_and_author::(2, author); + }: _(RawOrigin::Signed(caller.clone()), caller.clone(), delegation_count) + verify { + assert!(Pallet::::delegator_state(&caller).is_none()); + } + + cancel_leave_delegators { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(Pallet::::delegator_state(&caller).unwrap().is_active()); + } + + schedule_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone()), collator.clone()) + verify { + assert_eq!( + Pallet::::delegation_scheduled_requests(&collator), + vec![ScheduledRequest { + delegator: caller, + when_executable: 3, + action: DelegationAction::Revoke(bond), + }], + ); + } + + delegator_bond_more { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond) + verify { + let expected_bond = bond * 2u32.into(); + assert_eq!( + Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, + expected_bond, + ); + } + + schedule_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond_less) + verify { + let state = Pallet::::delegator_state(&caller) + .expect("just request bonded less so exists"); + assert_eq!( + Pallet::::delegation_scheduled_requests(&collator), + vec![ScheduledRequest { + delegator: caller, + when_executable: 3, + action: DelegationAction::Decrease(bond_less), + }], + ); + } + + execute_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_revoke_delegation(RawOrigin::Signed( + caller.clone()).into(), + collator.clone() + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::execute_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + caller.clone(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::is_delegator(&caller) + ); + } + + execute_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + Pallet::::schedule_delegator_bond_less( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond_less + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::execute_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + caller.clone(), + collator.clone() + )?; + } verify { + let expected = total - bond_less; + assert_eq!( + Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, + expected, + ); + } + + cancel_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_revoke_delegation( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + }: { + Pallet::::cancel_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|x| &x.delegator == &caller) + ); + } + + cancel_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + Pallet::::schedule_delegator_bond_less( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond_less + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::cancel_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|x| &x.delegator == &caller) + ); + } + + // ON_INITIALIZE + + prepare_staking_payouts { + let reward_delay = <::RewardPaymentDelay as Get>::get(); + let round = reward_delay + 2u32; + let payout_round = round - reward_delay; + // may need: + // > + // > + // > + // ensure parachain bond account exists so that deposit_into_existing succeeds + >::insert(payout_round, 100); + >::insert(payout_round, min_candidate_stk::()); + + // set an account in the bond config so that we will measure the payout to it + let account = create_funded_user::( + "parachain_bond", + 0, + min_candidate_stk::(), + ).0; + >::put(ParachainBondConfig { + account, + percent: Percent::from_percent(50), + }); + + }: { Pallet::::prepare_staking_payouts(round); } + verify { + } + + get_rewardable_delegators { + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators + + let high_inflation: Range = Range { + min: Perbill::one(), + ideal: Perbill::one(), + max: Perbill::one(), + }; + Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; + Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; + + let collator = create_funded_collator::( + "collator", + 0, + min_candidate_stk::() * 1_000_000u32.into(), + true, + 1, + )?; + + // create delegators + for i in 0..y { + let seed = USER_SEED + i + 1; + let delegator = create_funded_delegator::( + "delegator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + collator.clone(), + true, + i, + )?; + } + + let mut _results = None; + + }: { _results = Some(Pallet::::get_rewardable_delegators(&collator)); } + verify { + let counted_delegations = _results.expect("get_rewardable_delegators returned some results"); + assert!(counted_delegations.uncounted_stake == 0u32.into()); + assert!(counted_delegations.rewardable_delegations.len() as u32 == y); + let top_delegations = >::get(collator.clone()) + .expect("delegations were set for collator through delegate() calls"); + assert!(top_delegations.delegations.len() as u32 == y); + } + + select_top_candidates { + let x in 0..50; // num collators + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators + + let high_inflation: Range = Range { + min: Perbill::one(), + ideal: Perbill::one(), + max: Perbill::one(), + }; + Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; + Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; + + let mut seed = USER_SEED + 1; + + for _ in 0..x { + let collator = create_funded_collator::( + "collator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + true, + 999999, + )?; + seed += 1; + + // create delegators + for _ in 0..y { + let delegator = create_funded_delegator::( + "delegator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + collator.clone(), + true, + 9999999, + )?; + seed += 1; + } + } + + }: { Some(Pallet::::select_top_candidates(1)); } + verify { + } + + pay_one_collator_reward { + // y controls number of delegations, its maximum per collator is the max top delegations + let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); + + // must come after 'let foo in 0..` statements for macro + use crate::{ + DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points, + AwardedPts, + }; + + let before_running_round_index = Pallet::::round().current; + let initial_stake_amount = min_candidate_stk::() * 1_000_000u32.into(); + + let mut total_staked = 0u32.into(); + + // initialize our single collator + let sole_collator = create_funded_collator::( + "collator", + 0, + initial_stake_amount, + true, + 1u32, + )?; + total_staked += initial_stake_amount; + + // generate funded collator accounts + let mut delegators: Vec = Vec::new(); + for i in 0..y { + let seed = USER_SEED + i; + let delegator = create_funded_delegator::( + "delegator", + seed, + initial_stake_amount, + sole_collator.clone(), + true, + delegators.len() as u32, + )?; + delegators.push(delegator); + total_staked += initial_stake_amount; + } + + // rather than roll through rounds in order to initialize the storage we want, we set it + // directly and then call pay_one_collator_reward directly. + + let round_for_payout = 5; + >::insert(&round_for_payout, DelayedPayout { + // NOTE: round_issuance is not correct here, but it doesn't seem to cause problems + round_issuance: 1000u32.into(), + total_staking_reward: total_staked, + collator_commission: Perbill::from_rational(1u32, 100u32), + }); + + let mut delegations: Vec>> = Vec::new(); + for delegator in &delegators { + delegations.push(BondWithAutoCompound { + owner: delegator.clone(), + amount: 100u32.into(), + auto_compound: Percent::zero(), + }); + } + + >::insert(round_for_payout, &sole_collator, CollatorSnapshot { + bond: 1_000u32.into(), + delegations, + total: 1_000_000u32.into(), + }); + + >::insert(round_for_payout, 100); + >::insert(round_for_payout, &sole_collator, 20); + + }: { + let round_for_payout = 5; + // TODO: this is an extra read right here (we should whitelist it?) + let payout_info = Pallet::::delayed_payouts(round_for_payout).expect("payout expected"); + let result = Pallet::::pay_one_collator_reward(round_for_payout, payout_info); + // TODO: how to keep this in scope so it can be done in verify block? + assert!(matches!(result.0, RewardPayment::Paid)); + } + verify { + // collator should have been paid + assert!( + T::Currency::free_balance(&sole_collator) > initial_stake_amount, + "collator should have been paid in pay_one_collator_reward" + ); + // nominators should have been paid + for delegator in &delegators { + assert!( + T::Currency::free_balance(&delegator) > initial_stake_amount, + "delegator should have been paid in pay_one_collator_reward" + ); + } + } + + base_on_initialize { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let start = >::block_number(); + parachain_staking_on_finalize::(collator.clone()); + >::on_finalize(start); + >::set_block_number( + start + 1u32.into() + ); + let end = >::block_number(); + >::on_initialize(end); + }: { Pallet::::on_initialize(end); } + verify { + // Round transitions + assert_eq!(start + 1u32.into(), end); + } + + set_auto_compound { + // x controls number of distinct auto-compounding delegations the prime collator will have + // y controls number of distinct delegations the prime delegator will have + let x in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); + + use crate::auto_compound::AutoCompoundDelegations; + + let min_candidate_stake = min_candidate_stk::(); + let min_delegator_stake = min_delegator_stk::(); + let mut seed = Seed::new(); + + // initialize the prime collator + let prime_candidate = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + 1, + )?; + + // initialize the prime delegator + let prime_delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake * (y+1).into(), + prime_candidate.clone(), + true, + 0, + )?; + + // have x-1 distinct auto-compounding delegators delegate to prime collator + // we directly set the storage, since benchmarks don't work when the same extrinsic is + // called from within the benchmark. + let mut auto_compounding_state = >::get_storage(&prime_candidate); + for i in 1..x { + let delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake, + prime_candidate.clone(), + true, + i, + )?; + auto_compounding_state.set_for_delegator( + delegator, + Percent::from_percent(100), + ); + } + auto_compounding_state.set_storage(&prime_candidate); + + // delegate to y-1 distinct collators from the prime delegator + for i in 1..y { + let collator = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + i+1, + )?; + Pallet::::delegate( + RawOrigin::Signed(prime_delegator.clone()).into(), + collator, + min_delegator_stake, + 0, + i, + )?; + } + }: { + Pallet::::set_auto_compound( + RawOrigin::Signed(prime_delegator.clone()).into(), + prime_candidate.clone(), + Percent::from_percent(50), + x, + y+1, + )?; + } + verify { + let actual_auto_compound = >::get_storage(&prime_candidate) + .get_for_delegator(&prime_delegator); + let expected_auto_compound = Some(Percent::from_percent(50)); + assert_eq!( + expected_auto_compound, + actual_auto_compound, + "delegation must have an auto-compound entry", + ); + } + + delegate_with_auto_compound { + // x controls number of distinct delegations the prime collator will have + // y controls number of distinct auto-compounding delegations the prime collator will have + // z controls number of distinct delegations the prime delegator will have + let x in 0..(<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get()); + let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get(); + let z in 0..<::MaxDelegationsPerDelegator as Get>::get(); + + use crate::auto_compound::AutoCompoundDelegations; + + let min_candidate_stake = min_candidate_stk::(); + let min_delegator_stake = min_delegator_stk::(); + let mut seed = Seed::new(); + + // initialize the prime collator + let prime_candidate = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + 1, + )?; + + // initialize the future delegator + let (prime_delegator, _) = create_funded_user::( + "delegator", + seed.take(), + min_delegator_stake * (z+1).into(), + ); + + // have x-1 distinct delegators delegate to prime collator, of which y are auto-compounding. + // we can directly set the storage here. + let auto_compound_z = x * y / 100; + for i in 1..x { + let delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake, + prime_candidate.clone(), + true, + i, + )?; + if i <= y { + Pallet::::set_auto_compound( + RawOrigin::Signed(delegator.clone()).into(), + prime_candidate.clone(), + Percent::from_percent(100), + i+1, + i, + )?; + } + } + + // delegate to z-1 distinct collators from the prime delegator + for i in 1..z { + let collator = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + i+1, + )?; + Pallet::::delegate( + RawOrigin::Signed(prime_delegator.clone()).into(), + collator, + min_delegator_stake, + 0, + i, + )?; + } + }: { + Pallet::::delegate_with_auto_compound( + RawOrigin::Signed(prime_delegator.clone()).into(), + prime_candidate.clone(), + min_delegator_stake, + Percent::from_percent(50), + x, + y, + z, + )?; + } + verify { + assert!(Pallet::::is_delegator(&prime_delegator)); + let actual_auto_compound = >::get_storage(&prime_candidate) + .get_for_delegator(&prime_delegator); + let expected_auto_compound = Some(Percent::from_percent(50)); + assert_eq!( + expected_auto_compound, + actual_auto_compound, + "delegation must have an auto-compound entry", + ); + } + + mint_collator_reward { + let mut seed = Seed::new(); + let collator = create_funded_collator::( + "collator", + seed.take(), + 0u32.into(), + true, + 1, + )?; + let original_free_balance = T::Currency::free_balance(&collator); + }: { + Pallet::::mint_collator_reward(1u32.into(), collator.clone(), 50u32.into()) + } + verify { + assert_eq!(T::Currency::free_balance(&collator), original_free_balance + 50u32.into()); + } +} + +#[cfg(test)] +mod tests { + use crate::benchmarks::*; + use crate::mock::Test; + use frame_support::assert_ok; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + TestExternalities::new(t) + } + + #[test] + fn bench_set_staking_expectations() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_staking_expectations()); + }); + } + + #[test] + fn bench_set_inflation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_inflation()); + }); + } + + #[test] + fn bench_set_parachain_bond_account() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_parachain_bond_account()); + }); + } + + #[test] + fn bench_set_parachain_bond_reserve_percent() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_parachain_bond_reserve_percent()); + }); + } + + #[test] + fn bench_set_total_selected() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_total_selected()); + }); + } + + #[test] + fn bench_set_collator_commission() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_collator_commission()); + }); + } + + #[test] + fn bench_set_blocks_per_round() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_blocks_per_round()); + }); + } + + #[test] + fn bench_join_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_join_candidates()); + }); + } + + #[test] + fn bench_schedule_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_leave_candidates()); + }); + } + + #[test] + fn bench_execute_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_leave_candidates()); + }); + } + + #[test] + fn bench_cancel_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_leave_candidates()); + }); + } + + #[test] + fn bench_go_offline() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_go_offline()); + }); + } + + #[test] + fn bench_go_online() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_go_online()); + }); + } + + #[test] + fn bench_candidate_bond_more() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_candidate_bond_more()); + }); + } + + #[test] + fn bench_schedule_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_candidate_bond_less()); + }); + } + + #[test] + fn bench_execute_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_candidate_bond_less()); + }); + } + + #[test] + fn bench_cancel_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_candidate_bond_less()); + }); + } + + #[test] + fn bench_delegate() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_delegate()); + }); + } + + #[test] + fn bench_schedule_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_leave_delegators()); + }); + } + + #[test] + fn bench_execute_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_leave_delegators()); + }); + } + + #[test] + fn bench_cancel_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_leave_delegators()); + }); + } + + #[test] + fn bench_schedule_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_revoke_delegation()); + }); + } + + #[test] + fn bench_delegator_bond_more() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_delegator_bond_more()); + }); + } + + #[test] + fn bench_schedule_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_delegator_bond_less()); + }); + } + + #[test] + fn bench_execute_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_revoke_delegation()); + }); + } + + #[test] + fn bench_execute_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_delegator_bond_less()); + }); + } + + #[test] + fn bench_cancel_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_revoke_delegation()); + }); + } + + #[test] + fn bench_cancel_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_delegator_bond_less()); + }); + } + + #[test] + fn bench_base_on_initialize() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_base_on_initialize()); + }); + } +} + +impl_benchmark_test_suite!( + Pallet, + crate::benchmarks::tests::new_test_ext(), + crate::mock::Test +); diff --git a/external/pallets/parachain-staking/src/delegation_requests.rs b/external/pallets/parachain-staking/src/delegation_requests.rs new file mode 100644 index 000000000..6ca5e6411 --- /dev/null +++ b/external/pallets/parachain-staking/src/delegation_requests.rs @@ -0,0 +1,704 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Scheduled requests functionality for delegators + +use crate::pallet::{ + BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, Event, + Pallet, Round, RoundIndex, Total, +}; +use crate::{auto_compound::AutoCompoundDelegations, Delegator, DelegatorStatus}; +use frame_support::ensure; +use frame_support::traits::Get; +use frame_support::{dispatch::DispatchResultWithPostInfo, RuntimeDebug}; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_runtime::traits::Saturating; +use sp_std::{vec, vec::Vec}; + +/// An action that can be performed upon a delegation +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] +pub enum DelegationAction { + Revoke(Balance), + Decrease(Balance), +} + +impl DelegationAction { + /// Returns the wrapped amount value. + pub fn amount(&self) -> Balance { + match self { + DelegationAction::Revoke(amount) => *amount, + DelegationAction::Decrease(amount) => *amount, + } + } +} + +/// Represents a scheduled request that define a [DelegationAction]. The request is executable +/// iff the provided [RoundIndex] is achieved. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] +pub struct ScheduledRequest { + pub delegator: AccountId, + pub when_executable: RoundIndex, + pub action: DelegationAction, +} + +/// Represents a cancelled scheduled request for emitting an event. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct CancelledScheduledRequest { + pub when_executable: RoundIndex, + pub action: DelegationAction, +} + +impl From> for CancelledScheduledRequest { + fn from(request: ScheduledRequest) -> Self { + CancelledScheduledRequest { + when_executable: request.when_executable, + action: request.action, + } + } +} + +impl Pallet { + /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. + pub(crate) fn delegation_schedule_revoke( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + ensure!( + !scheduled_requests + .iter() + .any(|req| req.delegator == delegator), + >::PendingDelegationRequestAlreadyExists, + ); + + let bonded_amount = state + .get_bond_amount(&collator) + .ok_or(>::DelegationDNE)?; + let now = >::get().current; + let when = now.saturating_add(T::RevokeDelegationDelay::get()); + scheduled_requests.push(ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Revoke(bonded_amount), + when_executable: when, + }); + state.less_total = state.less_total.saturating_add(bonded_amount); + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::DelegationRevocationScheduled { + round: now, + delegator, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Schedules a [DelegationAction::Decrease] for the delegator, towards a given collator. + pub(crate) fn delegation_schedule_bond_decrease( + collator: T::AccountId, + delegator: T::AccountId, + decrease_amount: BalanceOf, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + ensure!( + !scheduled_requests + .iter() + .any(|req| req.delegator == delegator), + >::PendingDelegationRequestAlreadyExists, + ); + + let bonded_amount = state + .get_bond_amount(&collator) + .ok_or(>::DelegationDNE)?; + ensure!( + bonded_amount > decrease_amount, + >::DelegatorBondBelowMin + ); + let new_amount: BalanceOf = (bonded_amount - decrease_amount).into(); + ensure!( + new_amount >= T::MinDelegation::get(), + >::DelegationBelowMin + ); + + // Net Total is total after pending orders are executed + let net_total = state.total().saturating_sub(state.less_total); + // Net Total is always >= MinDelegatorStk + let max_subtracted_amount = net_total.saturating_sub(T::MinDelegatorStk::get().into()); + ensure!( + decrease_amount <= max_subtracted_amount, + >::DelegatorBondBelowMin + ); + + let now = >::get().current; + let when = now.saturating_add(T::RevokeDelegationDelay::get()); + scheduled_requests.push(ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Decrease(decrease_amount), + when_executable: when, + }); + state.less_total = state.less_total.saturating_add(decrease_amount); + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::DelegationDecreaseScheduled { + delegator, + candidate: collator, + amount_to_decrease: decrease_amount, + execute_round: when, + }); + Ok(().into()) + } + + /// Cancels the delegator's existing [ScheduledRequest] towards a given collator. + pub(crate) fn delegation_cancel_request( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) + .ok_or(>::PendingDelegationRequestDNE)?; + + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::CancelledDelegationRequest { + delegator, + collator, + cancelled_request: request.into(), + }); + Ok(().into()) + } + + fn cancel_request_with_state( + delegator: &T::AccountId, + state: &mut Delegator>, + scheduled_requests: &mut Vec>>, + ) -> Option>> { + let request_idx = scheduled_requests + .iter() + .position(|req| &req.delegator == delegator)?; + + let request = scheduled_requests.remove(request_idx); + let amount = request.action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + Some(request) + } + + /// Executes the delegator's existing [ScheduledRequest] towards a given collator. + pub(crate) fn delegation_execute_scheduled_request( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + let request_idx = scheduled_requests + .iter() + .position(|req| req.delegator == delegator) + .ok_or(>::PendingDelegationRequestDNE)?; + let request = &scheduled_requests[request_idx]; + + let now = >::get().current; + ensure!( + request.when_executable <= now, + >::PendingDelegationRequestNotDueYet + ); + + match request.action { + DelegationAction::Revoke(amount) => { + // revoking last delegation => leaving set of delegators + let leaving = if state.delegations.0.len() == 1usize { + true + } else { + ensure!( + state + .total() + .saturating_sub(T::MinDelegatorStk::get().into()) + >= amount, + >::DelegatorBondBelowMin + ); + false + }; + + // remove from pending requests + let amount = scheduled_requests.remove(request_idx).action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + + // remove delegation from delegator state + state.rm_delegation::(&collator); + + // remove delegation from auto-compounding info + >::remove_auto_compound(&collator, &delegator); + + // remove delegation from collator state delegations + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), amount)?; + Self::deposit_event(Event::DelegationRevoked { + delegator: delegator.clone(), + candidate: collator.clone(), + unstaked_amount: amount, + }); + + >::insert(collator, scheduled_requests); + if leaving { + >::remove(&delegator); + Self::deposit_event(Event::DelegatorLeft { + delegator, + unstaked_amount: amount, + }); + } else { + >::insert(&delegator, state); + } + Ok(().into()) + } + DelegationAction::Decrease(_) => { + // remove from pending requests + let amount = scheduled_requests.remove(request_idx).action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + + // decrease delegation + for bond in &mut state.delegations.0 { + if bond.owner == collator { + return if bond.amount > amount { + let amount_before: BalanceOf = bond.amount.into(); + bond.amount = bond.amount.saturating_sub(amount); + let mut collator_info = >::get(&collator) + .ok_or(>::CandidateDNE)?; + + state.total_sub_if::(amount, |total| { + let new_total: BalanceOf = total.into(); + ensure!( + new_total >= T::MinDelegation::get(), + >::DelegationBelowMin + ); + ensure!( + new_total >= T::MinDelegatorStk::get(), + >::DelegatorBondBelowMin + ); + + Ok(()) + })?; + + // need to go into decrease_delegation + let in_top = collator_info.decrease_delegation::( + &collator, + delegator.clone(), + amount_before, + amount, + )?; + >::insert(&collator, collator_info); + let new_total_staked = >::get().saturating_sub(amount); + >::put(new_total_staked); + + >::insert( + collator.clone(), + scheduled_requests, + ); + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegationDecreased { + delegator, + candidate: collator.clone(), + amount, + in_top, + }); + Ok(().into()) + } else { + // must rm entire delegation if bond.amount <= less or cancel request + Err(>::DelegationBelowMin.into()) + }; + } + } + Err(>::DelegationDNE.into()) + } + } + } + + /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. + /// The last fulfilled request causes the delegator to leave the set of delegators. + pub(crate) fn delegator_schedule_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut updated_scheduled_requests = vec![]; + let now = >::get().current; + let when = now.saturating_add(T::LeaveDelegatorsDelay::get()); + + // lazy migration for DelegatorStatus::Leaving + #[allow(deprecated)] + if matches!(state.status, DelegatorStatus::Leaving(_)) { + state.status = DelegatorStatus::Active; + >::insert(delegator.clone(), state.clone()); + } + + // it is assumed that a multiple delegations to the same collator does not exist, else this + // will cause a bug - the last duplicate delegation update will be the only one applied. + let mut existing_revoke_count = 0; + for bond in state.delegations.0.clone() { + let collator = bond.owner; + let bonded_amount = bond.amount; + let mut scheduled_requests = >::get(&collator); + + // cancel any existing requests + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + let request = match request { + Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { + existing_revoke_count += 1; + revoke_req // re-insert the same Revoke request + } + _ => ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Revoke(bonded_amount.clone()), + when_executable: when, + }, + }; + + scheduled_requests.push(request); + state.less_total = state.less_total.saturating_add(bonded_amount); + updated_scheduled_requests.push((collator, scheduled_requests)); + } + + if existing_revoke_count == state.delegations.0.len() { + return Err(>::DelegatorAlreadyLeaving.into()); + } + + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegatorExitScheduled { + round: now, + delegator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. + /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be + /// executed in the current round, for this function to succeed. + pub(crate) fn delegator_cancel_scheduled_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut updated_scheduled_requests = vec![]; + + // backwards compatible handling for DelegatorStatus::Leaving + #[allow(deprecated)] + if matches!(state.status, DelegatorStatus::Leaving(_)) { + state.status = DelegatorStatus::Active; + >::insert(delegator.clone(), state.clone()); + Self::deposit_event(Event::DelegatorExitCancelled { delegator }); + return Ok(().into()); + } + + // pre-validate that all delegations have a Revoke request. + for bond in &state.delegations.0 { + let collator = bond.owner.clone(); + let scheduled_requests = >::get(&collator); + scheduled_requests + .iter() + .find(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + .ok_or(>::DelegatorNotLeaving)?; + } + + // cancel all requests + for bond in state.delegations.0.clone() { + let collator = bond.owner.clone(); + let mut scheduled_requests = >::get(&collator); + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + updated_scheduled_requests.push((collator, scheduled_requests)); + } + + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegatorExitCancelled { delegator }); + + Ok(().into()) + } + + /// Executes every [DelegationAction::Revoke] request for a delegator towards a collator. + /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be + /// executed in the current round, for this function to succeed. + pub(crate) fn delegator_execute_scheduled_revoke_all( + delegator: T::AccountId, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + ensure!( + delegation_count >= (state.delegations.0.len() as u32), + Error::::TooLowDelegationCountToLeaveDelegators + ); + let now = >::get().current; + + // backwards compatible handling for DelegatorStatus::Leaving + #[allow(deprecated)] + if let DelegatorStatus::Leaving(when) = state.status { + ensure!( + >::get().current >= when, + Error::::DelegatorCannotLeaveYet + ); + + for bond in state.delegations.0.clone() { + if let Err(error) = Self::delegator_leaves_candidate( + bond.owner.clone(), + delegator.clone(), + bond.amount, + ) { + log::warn!( + "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", + error + ); + } + + Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); + >::remove_auto_compound(&bond.owner, &delegator); + } + >::remove(&delegator); + Self::deposit_event(Event::DelegatorLeft { + delegator, + unstaked_amount: state.total, + }); + return Ok(().into()); + } + + let mut validated_scheduled_requests = vec![]; + // pre-validate that all delegations have a Revoke request that can be executed now. + for bond in &state.delegations.0 { + let scheduled_requests = >::get(&bond.owner); + let request_idx = scheduled_requests + .iter() + .position(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + .ok_or(>::DelegatorNotLeaving)?; + let request = &scheduled_requests[request_idx]; + + ensure!( + request.when_executable <= now, + >::DelegatorCannotLeaveYet + ); + + validated_scheduled_requests.push((bond.clone(), scheduled_requests, request_idx)) + } + + let mut updated_scheduled_requests = vec![]; + // we do not update the delegator state, since the it will be completely removed + for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { + let collator = bond.owner; + + if let Err(error) = + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) + { + log::warn!( + "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", + delegator, + error + ); + } + + // remove the scheduled request, since it is fulfilled + scheduled_requests.remove(request_idx).action.amount(); + updated_scheduled_requests.push((collator.clone(), scheduled_requests)); + + // remove the auto-compounding entry for the delegation + >::remove_auto_compound(&collator, &delegator); + } + + // set state.total so that state.adjust_bond_lock will remove lock + let unstaked_amount = state.total(); + state.total_sub::(unstaked_amount)?; + + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + Self::deposit_event(Event::DelegatorLeft { + delegator: delegator.clone(), + unstaked_amount, + }); + >::remove(&delegator); + + Ok(().into()) + } + + /// Removes the delegator's existing [ScheduledRequest] towards a given collator, if exists. + /// The state needs to be persisted by the caller of this function. + pub(crate) fn delegation_remove_request_with_state( + collator: &T::AccountId, + delegator: &T::AccountId, + state: &mut Delegator>, + ) { + let mut scheduled_requests = >::get(collator); + + let maybe_request_idx = scheduled_requests + .iter() + .position(|req| &req.delegator == delegator); + + if let Some(request_idx) = maybe_request_idx { + let request = scheduled_requests.remove(request_idx); + let amount = request.action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + >::insert(collator, scheduled_requests); + } + } + + /// Returns true if a [ScheduledRequest] exists for a given delegation + pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { + >::get(collator) + .iter() + .any(|req| &req.delegator == delegator) + } + + /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation + pub fn delegation_request_revoke_exists( + collator: &T::AccountId, + delegator: &T::AccountId, + ) -> bool { + >::get(collator) + .iter() + .any(|req| { + &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{mock::Test, set::OrderedSet, Bond}; + + #[test] + fn test_cancel_request_with_state_removes_request_for_correct_delegator_and_updates_state() { + let mut state = Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { + amount: 100, + owner: 2, + }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + }; + let mut scheduled_requests = vec![ + ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }, + ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }, + ]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + + assert_eq!( + removed_request, + Some(ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }) + ); + assert_eq!( + scheduled_requests, + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] + ); + assert_eq!( + state, + Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { + amount: 100, + owner: 2, + }]), + total: 100, + less_total: 0, + status: crate::DelegatorStatus::Active, + } + ); + } + + #[test] + fn test_cancel_request_with_state_does_nothing_when_request_does_not_exist() { + let mut state = Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { + amount: 100, + owner: 2, + }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + }; + let mut scheduled_requests = vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + + assert_eq!(removed_request, None,); + assert_eq!( + scheduled_requests, + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] + ); + assert_eq!( + state, + Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { + amount: 100, + owner: 2, + }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + } + ); + } +} diff --git a/external/pallets/parachain-staking/src/inflation.rs b/external/pallets/parachain-staking/src/inflation.rs new file mode 100644 index 000000000..edc246575 --- /dev/null +++ b/external/pallets/parachain-staking/src/inflation.rs @@ -0,0 +1,228 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Helper methods for computing issuance based on inflation +use crate::pallet::{BalanceOf, Config, Pallet}; +use frame_support::traits::Currency; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_runtime::PerThing; +use sp_runtime::{Perbill, RuntimeDebug}; +use substrate_fixed::transcendental::pow as floatpow; +use substrate_fixed::types::I64F64; + +const SECONDS_PER_YEAR: u32 = 31557600; +const SECONDS_PER_BLOCK: u32 = 12; +pub const BLOCKS_PER_YEAR: u32 = SECONDS_PER_YEAR / SECONDS_PER_BLOCK; + +fn rounds_per_year() -> u32 { + let blocks_per_round = >::round().length; + BLOCKS_PER_YEAR / blocks_per_round +} + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive( + Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, +)] +pub struct Range { + pub min: T, + pub ideal: T, + pub max: T, +} + +impl Range { + pub fn is_valid(&self) -> bool { + self.max >= self.ideal && self.ideal >= self.min + } +} + +impl From for Range { + fn from(other: T) -> Range { + Range { + min: other, + ideal: other, + max: other, + } + } +} +/// Convert an annual inflation to a round inflation +/// round = (1+annual)^(1/rounds_per_year) - 1 +pub fn perbill_annual_to_perbill_round( + annual: Range, + rounds_per_year: u32, +) -> Range { + let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); + let annual_to_round = |annual: Perbill| -> Perbill { + let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); + let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) + .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); + Perbill::from_parts( + ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) + .ceil() + .to_num::(), + ) + }; + Range { + min: annual_to_round(annual.min), + ideal: annual_to_round(annual.ideal), + max: annual_to_round(annual.max), + } +} +/// Convert annual inflation rate range to round inflation range +pub fn annual_to_round(annual: Range) -> Range { + let periods = rounds_per_year::(); + perbill_annual_to_perbill_round(annual, periods) +} + +/// Compute round issuance range from round inflation range and current total issuance +pub fn round_issuance_range(round: Range) -> Range> { + let circulating = T::Currency::total_issuance(); + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } +} + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +pub struct InflationInfo { + /// Staking expectations + pub expect: Range, + /// Annual inflation range + pub annual: Range, + /// Round inflation range + pub round: Range, +} + +impl InflationInfo { + pub fn new( + annual: Range, + expect: Range, + ) -> InflationInfo { + InflationInfo { + expect, + annual, + round: annual_to_round::(annual), + } + } + /// Set round inflation range according to input annual inflation range + pub fn set_round_from_annual(&mut self, new: Range) { + self.round = annual_to_round::(new); + } + /// Reset round inflation rate based on changes to round length + pub fn reset_round(&mut self, new_length: u32) { + let periods = BLOCKS_PER_YEAR / new_length; + self.round = perbill_annual_to_perbill_round(self.annual, periods); + } + /// Set staking expectations + pub fn set_expectations(&mut self, expect: Range) { + self.expect = expect; + } +} + +#[cfg(test)] +mod tests { + use super::*; + fn mock_annual_to_round(annual: Range, rounds_per_year: u32) -> Range { + perbill_annual_to_perbill_round(annual, rounds_per_year) + } + fn mock_round_issuance_range( + // Total circulating before minting + circulating: u128, + // Round inflation range + round: Range, + ) -> Range { + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } + } + #[test] + fn simple_issuance_conversion() { + // 5% inflation for 10_000_0000 = 500,000 minted over the year + // let's assume there are 10 periods in a year + // => mint 500_000 over 10 periods => 50_000 minted per period + let expected_round_issuance_range: Range = Range { + min: 48_909, + ideal: 48_909, + max: 48_909, + }; + let schedule = Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_issuance_range, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) + ); + } + #[test] + fn range_issuance_conversion() { + // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year + // let's assume there are 10 periods in a year + // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period + let expected_round_issuance_range: Range = Range { + min: 29_603, + ideal: 39298, + max: 48_909, + }; + let schedule = Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_issuance_range, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) + ); + } + #[test] + fn expected_parameterization() { + let expected_round_schedule: Range = Range { + min: 45, + ideal: 56, + max: 56, + }; + let schedule = Range { + min: Perbill::from_percent(4), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_schedule, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) + ); + } + #[test] + fn inflation_does_not_panic_at_round_number_limit() { + let schedule = Range { + min: Perbill::from_percent(100), + ideal: Perbill::from_percent(100), + max: Perbill::from_percent(100), + }; + mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1)); + mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1)); + mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, 1)); + } +} diff --git a/external/pallets/parachain-staking/src/lib.rs b/external/pallets/parachain-staking/src/lib.rs new file mode 100644 index 000000000..eaabd4255 --- /dev/null +++ b/external/pallets/parachain-staking/src/lib.rs @@ -0,0 +1,1926 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! # Parachain Staking +//! Minimal staking pallet that implements collator selection by total backed stake. +//! The main difference between this pallet and `frame/pallet-staking` is that this pallet +//! uses direct delegation. Delegators choose exactly who they delegate and with what stake. +//! This is different from `frame/pallet-staking` where delegators approval vote and run Phragmen. +//! +//! ### Rules +//! There is a new round every `>::get().length` blocks. +//! +//! At the start of every round, +//! * issuance is calculated for collators (and their delegators) for block authoring +//! `T::RewardPaymentDelay` rounds ago +//! * a new set of collators is chosen from the candidates +//! +//! Immediately following a round change, payments are made once-per-block until all payments have +//! been made. In each such block, one collator is chosen for a rewards payment and is paid along +//! with each of its top `T::MaxTopDelegationsPerCandidate` delegators. +//! +//! To join the set of candidates, call `join_candidates` with `bond >= MinCandidateStk`. +//! To leave the set of candidates, call `schedule_leave_candidates`. If the call succeeds, +//! the collator is removed from the pool of candidates so they cannot be selected for future +//! collator sets, but they are not unbonded until their exit request is executed. Any signed +//! account may trigger the exit `T::LeaveCandidatesDelay` rounds after the round in which the +//! original request was made. +//! +//! To join the set of delegators, call `delegate` and pass in an account that is +//! already a collator candidate and `bond >= MinDelegatorStk`. Each delegator can delegate up to +//! `T::MaxDelegationsPerDelegator` collator candidates by calling `delegate`. +//! +//! To revoke a delegation, call `revoke_delegation` with the collator candidate's account. +//! To leave the set of delegators and revoke all delegations, call `leave_delegators`. + +#![cfg_attr(not(feature = "std"), no_std)] + +mod auto_compound; +mod delegation_requests; +pub mod inflation; +pub mod migrations; +pub mod traits; +pub mod types; +pub mod weights; + +#[cfg(any(test, feature = "runtime-benchmarks"))] +mod benchmarks; +#[cfg(test)] +mod mock; +mod set; +#[cfg(test)] +mod tests; + +use frame_support::pallet; +pub use inflation::{InflationInfo, Range}; +use weights::WeightInfo; + +pub use auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}; +pub use delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}; +pub use pallet::*; +pub use traits::*; +pub use types::*; +pub use RoundIndex; + +#[pallet] +pub mod pallet { + use crate::delegation_requests::{ + CancelledScheduledRequest, DelegationAction, ScheduledRequest, + }; + use crate::{set::OrderedSet, traits::*, types::*, InflationInfo, Range, WeightInfo}; + use crate::{AutoCompoundConfig, AutoCompoundDelegations}; + use frame_support::pallet_prelude::*; + use frame_support::traits::{ + tokens::WithdrawReasons, Currency, Get, Imbalance, LockIdentifier, LockableCurrency, + ReservableCurrency, + }; + use frame_system::pallet_prelude::*; + use sp_runtime::{ + traits::{Saturating, Zero}, + Perbill, Percent, + }; + use sp_std::{collections::btree_map::BTreeMap, prelude::*}; + + /// Pallet for parachain staking + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + pub type RoundIndex = u32; + type RewardPoint = u32; + pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + pub const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol"; + pub const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel"; + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type + type Event: From> + IsType<::Event>; + /// The currency type + type Currency: Currency + + ReservableCurrency + + LockableCurrency; + /// The origin for monetary governance + type MonetaryGovernanceOrigin: EnsureOrigin; + /// Minimum number of blocks per round + #[pallet::constant] + type MinBlocksPerRound: Get; + /// Number of rounds that candidates remain bonded before exit request is executable + #[pallet::constant] + type LeaveCandidatesDelay: Get; + /// Number of rounds candidate requests to decrease self-bond must wait to be executable + #[pallet::constant] + type CandidateBondLessDelay: Get; + /// Number of rounds that delegators remain bonded before exit request is executable + #[pallet::constant] + type LeaveDelegatorsDelay: Get; + /// Number of rounds that delegations remain bonded before revocation request is executable + #[pallet::constant] + type RevokeDelegationDelay: Get; + /// Number of rounds that delegation less requests must wait before executable + #[pallet::constant] + type DelegationBondLessDelay: Get; + /// Number of rounds after which block authors are rewarded + #[pallet::constant] + type RewardPaymentDelay: Get; + /// Minimum number of selected candidates every round + #[pallet::constant] + type MinSelectedCandidates: Get; + /// Maximum top delegations counted per candidate + #[pallet::constant] + type MaxTopDelegationsPerCandidate: Get; + /// Maximum bottom delegations (not counted) per candidate + #[pallet::constant] + type MaxBottomDelegationsPerCandidate: Get; + /// Maximum delegations per delegator + #[pallet::constant] + type MaxDelegationsPerDelegator: Get; + /// Minimum stake required for any candidate to be in `SelectedCandidates` for the round + #[pallet::constant] + type MinCollatorStk: Get>; + /// Minimum stake required for any account to be a collator candidate + #[pallet::constant] + type MinCandidateStk: Get>; + /// Minimum stake for any registered on-chain account to delegate + #[pallet::constant] + type MinDelegation: Get>; + /// Minimum stake for any registered on-chain account to be a delegator + #[pallet::constant] + type MinDelegatorStk: Get>; + /// Get the current block author + type BlockAuthor: Get; + /// Handler to notify the runtime when a collator is paid. + /// If you don't need it, you can specify the type `()`. + type OnCollatorPayout: OnCollatorPayout>; + /// Handler to distribute a collator's reward. + /// To use the default implementation of minting rewards, specify the type `()`. + type PayoutCollatorReward: PayoutCollatorReward; + /// Handler to notify the runtime when a new round begin. + /// If you don't need it, you can specify the type `()`. + type OnNewRound: OnNewRound; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + DelegatorDNE, + DelegatorDNEinTopNorBottom, + DelegatorDNEInDelegatorSet, + CandidateDNE, + DelegationDNE, + DelegatorExists, + CandidateExists, + CandidateBondBelowMin, + InsufficientBalance, + DelegatorBondBelowMin, + DelegationBelowMin, + AlreadyOffline, + AlreadyActive, + DelegatorAlreadyLeaving, + DelegatorNotLeaving, + DelegatorCannotLeaveYet, + CannotDelegateIfLeaving, + CandidateAlreadyLeaving, + CandidateNotLeaving, + CandidateCannotLeaveYet, + CannotGoOnlineIfLeaving, + ExceedMaxDelegationsPerDelegator, + AlreadyDelegatedCandidate, + InvalidSchedule, + CannotSetBelowMin, + RoundLengthMustBeGreaterThanTotalSelectedCollators, + NoWritingSameValue, + TooLowCandidateCountWeightHintJoinCandidates, + TooLowCandidateCountWeightHintCancelLeaveCandidates, + TooLowCandidateCountToLeaveCandidates, + TooLowDelegationCountToDelegate, + TooLowCandidateDelegationCountToDelegate, + TooLowCandidateDelegationCountToLeaveCandidates, + TooLowDelegationCountToLeaveDelegators, + PendingCandidateRequestsDNE, + PendingCandidateRequestAlreadyExists, + PendingCandidateRequestNotDueYet, + PendingDelegationRequestDNE, + PendingDelegationRequestAlreadyExists, + PendingDelegationRequestNotDueYet, + CannotDelegateLessThanOrEqualToLowestBottomWhenFull, + PendingDelegationRevoke, + TooLowDelegationCountToAutoCompound, + TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + TooLowCandidateAutoCompoundingDelegationCountToDelegate, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// Started new round. + NewRound { + starting_block: T::BlockNumber, + round: RoundIndex, + selected_collators_number: u32, + total_balance: BalanceOf, + }, + /// Account joined the set of collator candidates. + JoinedCollatorCandidates { + account: T::AccountId, + amount_locked: BalanceOf, + new_total_amt_locked: BalanceOf, + }, + /// Candidate selected for collators. Total Exposed Amount includes all delegations. + CollatorChosen { + round: RoundIndex, + collator_account: T::AccountId, + total_exposed_amount: BalanceOf, + }, + /// Candidate requested to decrease a self bond. + CandidateBondLessRequested { + candidate: T::AccountId, + amount_to_decrease: BalanceOf, + execute_round: RoundIndex, + }, + /// Candidate has increased a self bond. + CandidateBondedMore { + candidate: T::AccountId, + amount: BalanceOf, + new_total_bond: BalanceOf, + }, + /// Candidate has decreased a self bond. + CandidateBondedLess { + candidate: T::AccountId, + amount: BalanceOf, + new_bond: BalanceOf, + }, + /// Candidate temporarily leave the set of collator candidates without unbonding. + CandidateWentOffline { candidate: T::AccountId }, + /// Candidate rejoins the set of collator candidates. + CandidateBackOnline { candidate: T::AccountId }, + /// Candidate has requested to leave the set of candidates. + CandidateScheduledExit { + exit_allowed_round: RoundIndex, + candidate: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Cancelled request to leave the set of candidates. + CancelledCandidateExit { candidate: T::AccountId }, + /// Cancelled request to decrease candidate's bond. + CancelledCandidateBondLess { + candidate: T::AccountId, + amount: BalanceOf, + execute_round: RoundIndex, + }, + /// Candidate has left the set of candidates. + CandidateLeft { + ex_candidate: T::AccountId, + unlocked_amount: BalanceOf, + new_total_amt_locked: BalanceOf, + }, + /// Delegator requested to decrease a bond for the collator candidate. + DelegationDecreaseScheduled { + delegator: T::AccountId, + candidate: T::AccountId, + amount_to_decrease: BalanceOf, + execute_round: RoundIndex, + }, + // Delegation increased. + DelegationIncreased { + delegator: T::AccountId, + candidate: T::AccountId, + amount: BalanceOf, + in_top: bool, + }, + // Delegation decreased. + DelegationDecreased { + delegator: T::AccountId, + candidate: T::AccountId, + amount: BalanceOf, + in_top: bool, + }, + /// Delegator requested to leave the set of delegators. + DelegatorExitScheduled { + round: RoundIndex, + delegator: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Delegator requested to revoke delegation. + DelegationRevocationScheduled { + round: RoundIndex, + delegator: T::AccountId, + candidate: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Delegator has left the set of delegators. + DelegatorLeft { + delegator: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Delegation revoked. + DelegationRevoked { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Delegation kicked. + DelegationKicked { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Cancelled a pending request to exit the set of delegators. + DelegatorExitCancelled { delegator: T::AccountId }, + /// Cancelled request to change an existing delegation. + CancelledDelegationRequest { + delegator: T::AccountId, + cancelled_request: CancelledScheduledRequest>, + collator: T::AccountId, + }, + /// New delegation (increase of the existing one). + Delegation { + delegator: T::AccountId, + locked_amount: BalanceOf, + candidate: T::AccountId, + delegator_position: DelegatorAdded>, + auto_compound: Percent, + }, + /// Delegation from candidate state has been remove. + DelegatorLeftCandidate { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + total_candidate_staked: BalanceOf, + }, + /// Paid the account (delegator or collator) the balance as liquid rewards. + Rewarded { + account: T::AccountId, + rewards: BalanceOf, + }, + /// Transferred to account which holds funds reserved for parachain bond. + ReservedForParachainBond { + account: T::AccountId, + value: BalanceOf, + }, + /// Account (re)set for parachain bond treasury. + ParachainBondAccountSet { + old: T::AccountId, + new: T::AccountId, + }, + /// Percent of inflation reserved for parachain bond (re)set. + ParachainBondReservePercentSet { old: Percent, new: Percent }, + /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) + InflationSet { + annual_min: Perbill, + annual_ideal: Perbill, + annual_max: Perbill, + round_min: Perbill, + round_ideal: Perbill, + round_max: Perbill, + }, + /// Staking expectations set. + StakeExpectationsSet { + expect_min: BalanceOf, + expect_ideal: BalanceOf, + expect_max: BalanceOf, + }, + /// Set total selected candidates to this value. + TotalSelectedSet { old: u32, new: u32 }, + /// Set collator commission to this value. + CollatorCommissionSet { old: Perbill, new: Perbill }, + /// Set blocks per round + BlocksPerRoundSet { + current_round: RoundIndex, + first_block: T::BlockNumber, + old: u32, + new: u32, + new_per_round_inflation_min: Perbill, + new_per_round_inflation_ideal: Perbill, + new_per_round_inflation_max: Perbill, + }, + /// Auto-compounding reward percent was set for a delegation. + AutoCompoundSet { + candidate: T::AccountId, + delegator: T::AccountId, + value: Percent, + }, + /// Compounded a portion of rewards towards the delegation. + Compounded { + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + }, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(n: T::BlockNumber) -> Weight { + let mut weight = T::WeightInfo::base_on_initialize(); + + let mut round = >::get(); + if round.should_update(n) { + // mutate round + round.update(n); + // notify that new round begin + weight = weight.saturating_add(T::OnNewRound::on_new_round(round.current)); + // pay all stakers for T::RewardPaymentDelay rounds ago + weight = weight.saturating_add(Self::prepare_staking_payouts(round.current)); + // select top collator candidates for next round + let (extra_weight, collator_count, _delegation_count, total_staked) = + Self::select_top_candidates(round.current); + weight = weight.saturating_add(extra_weight); + // start next round + >::put(round); + // snapshot total stake + >::insert(round.current, >::get()); + Self::deposit_event(Event::NewRound { + starting_block: round.first, + round: round.current, + selected_collators_number: collator_count, + total_balance: total_staked, + }); + // account for Round and Staked writes + weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 2)); + } else { + weight = weight.saturating_add(Self::handle_delayed_payouts(round.current)); + } + + // add on_finalize weight + // read: Author, Points, AwardedPts + // write: Points, AwardedPts + weight = weight.saturating_add(T::DbWeight::get().reads_writes(3, 2)); + weight + } + fn on_finalize(_n: T::BlockNumber) { + Self::award_points_to_block_author(); + } + } + + #[pallet::storage] + #[pallet::getter(fn collator_commission)] + /// Commission percent taken off of rewards for all collators + type CollatorCommission = StorageValue<_, Perbill, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total_selected)] + /// The total candidates selected every round + pub(crate) type TotalSelected = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn parachain_bond_info)] + /// Parachain bond config info { account, percent_of_inflation } + pub(crate) type ParachainBondInfo = + StorageValue<_, ParachainBondConfig, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn round)] + /// Current round index and next round scheduled transition + pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn delegator_state)] + /// Get delegator state associated with an account if account is delegating else None + pub(crate) type DelegatorState = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegator>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn candidate_info)] + /// Get collator candidate info associated with an account if account is candidate else None + pub(crate) type CandidateInfo = + StorageMap<_, Twox64Concat, T::AccountId, CandidateMetadata>, OptionQuery>; + + /// Stores outstanding delegation requests per collator. + #[pallet::storage] + #[pallet::getter(fn delegation_scheduled_requests)] + pub(crate) type DelegationScheduledRequests = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec>>, + ValueQuery, + >; + + /// Stores auto-compounding configuration per collator. + #[pallet::storage] + #[pallet::getter(fn auto_compounding_delegations)] + pub(crate) type AutoCompoundingDelegations = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec>, + ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn top_delegations)] + /// Top delegations for collator candidate + pub(crate) type TopDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn bottom_delegations)] + /// Bottom delegations for collator candidate + pub(crate) type BottomDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn selected_candidates)] + /// The collator candidates selected for the current round + type SelectedCandidates = StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total)] + /// Total capital locked by this staking pallet + pub(crate) type Total = StorageValue<_, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn candidate_pool)] + /// The pool of collator candidates, each with their total backing stake + pub(crate) type CandidatePool = + StorageValue<_, OrderedSet>>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn at_stake)] + /// Snapshot of collator delegation stake at the start of the round + pub type AtStake = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + CollatorSnapshot>, + ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn delayed_payouts)] + /// Delayed payouts + pub type DelayedPayouts = + StorageMap<_, Twox64Concat, RoundIndex, DelayedPayout>, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn staked)] + /// Total counted stake for selected candidates in the round + pub type Staked = StorageMap<_, Twox64Concat, RoundIndex, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn inflation_config)] + /// Inflation configuration + pub type InflationConfig = StorageValue<_, InflationInfo>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn points)] + /// Total points awarded to collators for block production in the round + pub type Points = StorageMap<_, Twox64Concat, RoundIndex, RewardPoint, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn awarded_pts)] + /// Points for each collator per round + pub type AwardedPts = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + RewardPoint, + ValueQuery, + >; + + #[pallet::genesis_config] + pub struct GenesisConfig { + /// Initialize balance and register all as collators: `(collator AccountId, balance Amount)` + pub candidates: Vec<(T::AccountId, BalanceOf)>, + /// Initialize balance and make delegations: + /// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding Percent)` + pub delegations: Vec<(T::AccountId, T::AccountId, BalanceOf, Percent)>, + /// Inflation configuration + pub inflation_config: InflationInfo>, + /// Default fixed percent a collator takes off the top of due rewards + pub collator_commission: Perbill, + /// Default percent of inflation set aside for parachain bond every round + pub parachain_bond_reserve_percent: Percent, + /// Default number of blocks in a round + pub blocks_per_round: u32, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + candidates: vec![], + delegations: vec![], + inflation_config: Default::default(), + collator_commission: Default::default(), + parachain_bond_reserve_percent: Default::default(), + blocks_per_round: 1u32, + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + assert!(self.blocks_per_round > 0, "Blocks per round must be > 0"); + >::put(self.inflation_config.clone()); + let mut candidate_count = 0u32; + // Initialize the candidates + for &(ref candidate, balance) in &self.candidates { + assert!( + >::get_collator_stakable_free_balance(candidate) >= balance, + "Account does not have enough balance to bond as a candidate." + ); + if let Err(error) = >::join_candidates( + T::Origin::from(Some(candidate.clone()).into()), + balance, + candidate_count, + ) { + log::warn!("Join candidates failed in genesis with error {:?}", error); + } else { + candidate_count = candidate_count.saturating_add(1u32); + } + } + + let mut col_delegator_count: BTreeMap = BTreeMap::new(); + let mut col_auto_compound_delegator_count: BTreeMap = + BTreeMap::new(); + let mut del_delegation_count: BTreeMap = BTreeMap::new(); + // Initialize the delegations + for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { + assert!( + >::get_delegator_stakable_free_balance(delegator) >= balance, + "Account does not have enough balance to place delegation." + ); + let cd_count = if let Some(x) = col_delegator_count.get(target) { + *x + } else { + 0u32 + }; + let dd_count = if let Some(x) = del_delegation_count.get(delegator) { + *x + } else { + 0u32 + }; + let cd_auto_compound_count = col_auto_compound_delegator_count + .get(target) + .cloned() + .unwrap_or_default(); + if let Err(error) = >::delegate_with_auto_compound( + T::Origin::from(Some(delegator.clone()).into()), + target.clone(), + balance, + auto_compound, + cd_count, + cd_auto_compound_count, + dd_count, + ) { + log::warn!("Delegate failed in genesis with error {:?}", error); + } else { + if let Some(x) = col_delegator_count.get_mut(target) { + *x = x.saturating_add(1u32); + } else { + col_delegator_count.insert(target.clone(), 1u32); + }; + if let Some(x) = del_delegation_count.get_mut(delegator) { + *x = x.saturating_add(1u32); + } else { + del_delegation_count.insert(delegator.clone(), 1u32); + }; + if !auto_compound.is_zero() { + col_auto_compound_delegator_count + .entry(target.clone()) + .and_modify(|x| *x = x.saturating_add(1)) + .or_insert(1); + } + } + } + // Set collator commission to default config + >::put(self.collator_commission); + // Set parachain bond config to default config + >::put(ParachainBondConfig { + // must be set soon; if not => due inflation will be sent to collators/delegators + account: T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + percent: self.parachain_bond_reserve_percent, + }); + // Set total selected candidates to minimum config + >::put(T::MinSelectedCandidates::get()); + // Choose top TotalSelected collator candidates + let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); + // Start Round 1 at Block 0 + let round: RoundInfo = + RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); + >::put(round); + // Snapshot total stake + >::insert(1u32, >::get()); + >::deposit_event(Event::NewRound { + starting_block: T::BlockNumber::zero(), + round: 1u32, + selected_collators_number: v_count, + total_balance: total_staked, + }); + } + } + + #[pallet::call] + impl Pallet { + #[pallet::weight(::WeightInfo::set_staking_expectations())] + /// Set the expectations for total staked. These expectations determine the issuance for + /// the round according to logic in `fn compute_issuance` + pub fn set_staking_expectations( + origin: OriginFor, + expectations: Range>, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + ensure!(expectations.is_valid(), Error::::InvalidSchedule); + let mut config = >::get(); + ensure!( + config.expect != expectations, + Error::::NoWritingSameValue + ); + config.set_expectations(expectations); + Self::deposit_event(Event::StakeExpectationsSet { + expect_min: config.expect.min, + expect_ideal: config.expect.ideal, + expect_max: config.expect.max, + }); + >::put(config); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_inflation())] + /// Set the annual inflation rate to derive per-round inflation + pub fn set_inflation( + origin: OriginFor, + schedule: Range, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + ensure!(schedule.is_valid(), Error::::InvalidSchedule); + let mut config = >::get(); + ensure!(config.annual != schedule, Error::::NoWritingSameValue); + config.annual = schedule; + config.set_round_from_annual::(schedule); + Self::deposit_event(Event::InflationSet { + annual_min: config.annual.min, + annual_ideal: config.annual.ideal, + annual_max: config.annual.max, + round_min: config.round.min, + round_ideal: config.round.ideal, + round_max: config.round.max, + }); + >::put(config); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_parachain_bond_account())] + /// Set the account that will hold funds set aside for parachain bond + pub fn set_parachain_bond_account( + origin: OriginFor, + new: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + let ParachainBondConfig { + account: old, + percent, + } = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(ParachainBondConfig { + account: new.clone(), + percent, + }); + Self::deposit_event(Event::ParachainBondAccountSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] + /// Set the percent of inflation set aside for parachain bond + pub fn set_parachain_bond_reserve_percent( + origin: OriginFor, + new: Percent, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + let ParachainBondConfig { + account, + percent: old, + } = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(ParachainBondConfig { + account, + percent: new, + }); + Self::deposit_event(Event::ParachainBondReservePercentSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_total_selected())] + /// Set the total number of collator candidates selected per round + /// - changes are not applied until the start of the next round + pub fn set_total_selected(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + ensure!( + new >= T::MinSelectedCandidates::get(), + Error::::CannotSetBelowMin + ); + let old = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + ensure!( + new <= >::get().length, + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + >::put(new); + Self::deposit_event(Event::TotalSelectedSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_collator_commission())] + /// Set the commission for all collators + pub fn set_collator_commission( + origin: OriginFor, + new: Perbill, + ) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + let old = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(new); + Self::deposit_event(Event::CollatorCommissionSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_blocks_per_round())] + /// Set blocks per round + /// - if called with `new` less than length of current round, will transition immediately + /// in the next block + /// - also updates per-round inflation config + pub fn set_blocks_per_round(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + ensure!( + new >= T::MinBlocksPerRound::get(), + Error::::CannotSetBelowMin + ); + let mut round = >::get(); + let (now, first, old) = (round.current, round.first, round.length); + ensure!(old != new, Error::::NoWritingSameValue); + ensure!( + new >= >::get(), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + round.length = new; + // update per-round inflation given new rounds per year + let mut inflation_config = >::get(); + inflation_config.reset_round(new); + >::put(round); + Self::deposit_event(Event::BlocksPerRoundSet { + current_round: now, + first_block: first, + old: old, + new: new, + new_per_round_inflation_min: inflation_config.round.min, + new_per_round_inflation_ideal: inflation_config.round.ideal, + new_per_round_inflation_max: inflation_config.round.max, + }); + >::put(inflation_config); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::join_candidates(*candidate_count))] + /// Join the set of collator candidates + pub fn join_candidates( + origin: OriginFor, + bond: BalanceOf, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let acc = ensure_signed(origin)?; + ensure!(!Self::is_candidate(&acc), Error::::CandidateExists); + ensure!(!Self::is_delegator(&acc), Error::::DelegatorExists); + ensure!( + bond >= T::MinCandidateStk::get(), + Error::::CandidateBondBelowMin + ); + let mut candidates = >::get(); + let old_count = candidates.0.len() as u32; + ensure!( + candidate_count >= old_count, + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + ensure!( + candidates.insert(Bond { + owner: acc.clone(), + amount: bond + }), + Error::::CandidateExists + ); + ensure!( + Self::get_collator_stakable_free_balance(&acc) >= bond, + Error::::InsufficientBalance, + ); + T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); + let candidate = CandidateMetadata::new(bond); + >::insert(&acc, candidate); + let empty_delegations: Delegations> = Default::default(); + // insert empty top delegations + >::insert(&acc, empty_delegations.clone()); + // insert empty bottom delegations + >::insert(&acc, empty_delegations); + >::put(candidates); + let new_total = >::get().saturating_add(bond); + >::put(new_total); + Self::deposit_event(Event::JoinedCollatorCandidates { + account: acc, + amount_locked: bond, + new_total_amt_locked: new_total, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] + /// Request to leave the set of candidates. If successful, the account is immediately + /// removed from the candidate pool to prevent selection as a collator. + pub fn schedule_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let (now, when) = state.schedule_leave::()?; + let mut candidates = >::get(); + ensure!( + candidate_count >= candidates.0.len() as u32, + Error::::TooLowCandidateCountToLeaveCandidates + ); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateScheduledExit { + exit_allowed_round: now, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + #[pallet::weight( + ::WeightInfo::execute_leave_candidates(*candidate_delegation_count) + )] + /// Execute leave candidates request + pub fn execute_leave_candidates( + origin: OriginFor, + candidate: T::AccountId, + candidate_delegation_count: u32, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + ensure!( + state.delegation_count <= candidate_delegation_count, + Error::::TooLowCandidateDelegationCountToLeaveCandidates + ); + state.can_leave::()?; + let return_stake = |bond: Bond>| -> DispatchResult { + // remove delegation from delegator state + let mut delegator = DelegatorState::::get(&bond.owner).expect( + "Collator state and delegator state are consistent. + Collator state has a record of this delegation. Therefore, + Delegator state also has a record. qed.", + ); + + if let Some(remaining) = delegator.rm_delegation::(&candidate) { + Self::delegation_remove_request_with_state( + &candidate, + &bond.owner, + &mut delegator, + ); + >::remove_auto_compound(&candidate, &bond.owner); + + if remaining.is_zero() { + // we do not remove the scheduled delegation requests from other collators + // since it is assumed that they were removed incrementally before only the + // last delegation was left. + >::remove(&bond.owner); + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); + } else { + >::insert(&bond.owner, delegator); + } + } else { + // TODO: review. we assume here that this delegator has no remaining staked + // balance, so we ensure the lock is cleared + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); + } + Ok(()) + }; + // total backing stake is at least the candidate self bond + let mut total_backing = state.bond; + // return all top delegations + let top_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in top_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(top_delegations.total); + // return all bottom delegations + let bottom_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in bottom_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(bottom_delegations.total); + // return stake to collator + T::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + let new_total_staked = >::get().saturating_sub(total_backing); + >::put(new_total_staked); + Self::deposit_event(Event::CandidateLeft { + ex_candidate: candidate, + unlocked_amount: total_backing, + new_total_amt_locked: new_total_staked, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] + /// Cancel open request to leave candidates + /// - only callable by collator account + /// - result upon successful call is the candidate is active in the candidate pool + pub fn cancel_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(state.is_leaving(), Error::::CandidateNotLeaving); + state.go_online(); + let mut candidates = >::get(); + ensure!( + candidates.0.len() as u32 <= candidate_count, + Error::::TooLowCandidateCountWeightHintCancelLeaveCandidates + ); + ensure!( + candidates.insert(Bond { + owner: collator.clone(), + amount: state.total_counted + }), + Error::::AlreadyActive + ); + >::put(candidates); + >::insert(&collator, state); + Self::deposit_event(Event::CancelledCandidateExit { + candidate: collator, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::go_offline())] + /// Temporarily leave the set of collator candidates without unbonding + pub fn go_offline(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(state.is_active(), Error::::AlreadyOffline); + state.go_offline(); + let mut candidates = >::get(); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateWentOffline { + candidate: collator, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::go_online())] + /// Rejoin the set of collator candidates if previously had called `go_offline` + pub fn go_online(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(!state.is_active(), Error::::AlreadyActive); + ensure!(!state.is_leaving(), Error::::CannotGoOnlineIfLeaving); + state.go_online(); + let mut candidates = >::get(); + ensure!( + candidates.insert(Bond { + owner: collator.clone(), + amount: state.total_counted + }), + Error::::AlreadyActive + ); + >::put(candidates); + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBackOnline { + candidate: collator, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::candidate_bond_more())] + /// Increase collator candidate self bond by `more` + pub fn candidate_bond_more( + origin: OriginFor, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + state.bond_more::(collator.clone(), more)?; + let (is_active, total_counted) = (state.is_active(), state.total_counted); + >::insert(&collator, state); + if is_active { + Self::update_active(collator, total_counted); + } + Ok(().into()) + } + #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] + /// Request by collator candidate to decrease self bond by `less` + pub fn schedule_candidate_bond_less( + origin: OriginFor, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let when = state.schedule_bond_less::(less)?; + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBondLessRequested { + candidate: collator, + amount_to_decrease: less, + execute_round: when, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::execute_candidate_bond_less())] + /// Execute pending request to adjust the collator candidate self bond + pub fn execute_candidate_bond_less( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; // we may want to reward this if caller != candidate + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.execute_bond_less::(candidate.clone())?; + >::insert(&candidate, state); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::cancel_candidate_bond_less())] + /// Cancel pending request to adjust the collator candidate self bond + pub fn cancel_candidate_bond_less(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + state.cancel_bond_less::(collator.clone())?; + >::insert(&collator, state); + Ok(().into()) + } + #[pallet::weight( + ::WeightInfo::delegate( + *candidate_delegation_count, + *delegation_count + ) + )] + /// If caller is not a delegator and not a collator, then join the set of delegators + /// If caller is a delegator, then makes delegation to change their delegation state + pub fn delegate( + origin: OriginFor, + candidate: T::AccountId, + amount: BalanceOf, + candidate_delegation_count: u32, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::delegate_with_auto_compound( + candidate, + delegator, + amount, + Percent::zero(), + candidate_delegation_count, + 0, + delegation_count, + ) + } + + /// If caller is not a delegator and not a collator, then join the set of delegators + /// If caller is a delegator, then makes delegation to change their delegation state + /// Sets the auto-compound config for the delegation + #[pallet::weight( + ::WeightInfo::delegate_with_auto_compound( + *candidate_delegation_count, + *candidate_auto_compounding_delegation_count, + *delegation_count, + ) + )] + pub fn delegate_with_auto_compound( + origin: OriginFor, + candidate: T::AccountId, + amount: BalanceOf, + auto_compound: Percent, + candidate_delegation_count: u32, + candidate_auto_compounding_delegation_count: u32, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::delegate_with_auto_compound( + candidate, + delegator, + amount, + auto_compound, + candidate_delegation_count, + candidate_auto_compounding_delegation_count, + delegation_count, + ) + } + + /// DEPRECATED use batch util with schedule_revoke_delegation for all delegations + /// Request to leave the set of delegators. If successful, the caller is scheduled to be + /// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations. + /// Success forbids future delegation requests until the request is invoked or cancelled. + #[pallet::weight(::WeightInfo::schedule_leave_delegators())] + pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegator_schedule_revoke_all(delegator) + } + + /// DEPRECATED use batch util with execute_delegation_request for all delegations + /// Execute the right to exit the set of delegators and revoke all ongoing delegations. + #[pallet::weight(::WeightInfo::execute_leave_delegators(*delegation_count))] + pub fn execute_leave_delegators( + origin: OriginFor, + delegator: T::AccountId, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count) + } + + /// DEPRECATED use batch util with cancel_delegation_request for all delegations + /// Cancel a pending request to exit the set of delegators. Success clears the pending exit + /// request (thereby resetting the delay upon another `leave_delegators` call). + #[pallet::weight(::WeightInfo::cancel_leave_delegators())] + pub fn cancel_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegator_cancel_scheduled_revoke_all(delegator) + } + + #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] + /// Request to revoke an existing delegation. If successful, the delegation is scheduled + /// to be allowed to be revoked via the `execute_delegation_request` extrinsic. + /// The delegation receives no rewards for the rounds while a revoke is pending. + /// A revoke may not be performed if any other scheduled request is pending. + pub fn schedule_revoke_delegation( + origin: OriginFor, + collator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_schedule_revoke(collator, delegator) + } + + #[pallet::weight(::WeightInfo::delegator_bond_more())] + /// Bond more for delegators wrt a specific collator candidate. + pub fn delegator_bond_more( + origin: OriginFor, + candidate: T::AccountId, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + let in_top = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + more.clone(), + )?; + Pallet::::deposit_event(Event::DelegationIncreased { + delegator, + candidate, + amount: more, + in_top, + }); + + Ok(().into()) + } + + #[pallet::weight(::WeightInfo::schedule_delegator_bond_less())] + /// Request bond less for delegators wrt a specific collator candidate. The delegation's + /// rewards for rounds while the request is pending use the reduced bonded amount. + /// A bond less may not be performed if any other scheduled request is pending. + pub fn schedule_delegator_bond_less( + origin: OriginFor, + candidate: T::AccountId, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_schedule_bond_decrease(candidate, delegator, less) + } + + #[pallet::weight(::WeightInfo::execute_delegator_bond_less())] + /// Execute pending request to change an existing delegation + pub fn execute_delegation_request( + origin: OriginFor, + delegator: T::AccountId, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; // we may want to reward caller if caller != delegator + Self::delegation_execute_scheduled_request(candidate, delegator) + } + + #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] + /// Cancel request to change an existing delegation. + pub fn cancel_delegation_request( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_cancel_request(candidate, delegator) + } + + /// Sets the auto-compounding reward percentage for a delegation. + #[pallet::weight(::WeightInfo::set_auto_compound( + *candidate_auto_compounding_delegation_count_hint, + *delegation_count_hint, + ))] + pub fn set_auto_compound( + origin: OriginFor, + candidate: T::AccountId, + value: Percent, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::set_auto_compound( + candidate, + delegator, + value, + candidate_auto_compounding_delegation_count_hint, + delegation_count_hint, + ) + } + + /// Hotfix to remove existing empty entries for candidates that have left. + #[pallet::weight( + T::DbWeight::get().reads_writes(2 * candidates.len() as u64, candidates.len() as u64) + )] + pub fn hotfix_remove_delegation_requests_exited_candidates( + origin: OriginFor, + candidates: Vec, + ) -> DispatchResult { + ensure_signed(origin)?; + ensure!(candidates.len() < 100, >::InsufficientBalance); + for candidate in &candidates { + ensure!( + >::get(&candidate).is_none(), + >::CandidateNotLeaving + ); + ensure!( + >::get(&candidate).is_empty(), + >::CandidateNotLeaving + ); + } + + for candidate in candidates { + >::remove(candidate); + } + + Ok(().into()) + } + } + + /// Represents a payout made via `pay_one_collator_reward`. + pub(crate) enum RewardPayment { + /// A collator was paid + Paid, + /// A collator was skipped for payment. This can happen if they haven't been awarded any + /// points, that is, they did not produce any blocks. + Skipped, + /// All collator payments have been processed. + Finished, + } + + impl Pallet { + pub fn is_delegator(acc: &T::AccountId) -> bool { + >::get(acc).is_some() + } + pub fn is_candidate(acc: &T::AccountId) -> bool { + >::get(acc).is_some() + } + pub fn is_selected_candidate(acc: &T::AccountId) -> bool { + >::get().binary_search(acc).is_ok() + } + /// Returns an account's free balance which is not locked in delegation staking + pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { + let mut balance = T::Currency::free_balance(acc); + if let Some(state) = >::get(acc) { + balance = balance.saturating_sub(state.total()); + } + balance + } + /// Returns an account's free balance which is not locked in collator staking + pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { + let mut balance = T::Currency::free_balance(acc); + if let Some(info) = >::get(acc) { + balance = balance.saturating_sub(info.bond); + } + balance + } + /// Returns a delegations auto-compound value. + pub fn delegation_auto_compound( + candidate: &T::AccountId, + delegator: &T::AccountId, + ) -> Percent { + >::auto_compound(candidate, delegator) + } + /// Caller must ensure candidate is active before calling + pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { + let mut candidates = >::get(); + candidates.remove(&Bond::from_owner(candidate.clone())); + candidates.insert(Bond { + owner: candidate, + amount: total, + }); + >::put(candidates); + } + /// Compute round issuance based on total staked for the given round + fn compute_issuance(staked: BalanceOf) -> BalanceOf { + let config = >::get(); + let round_issuance = crate::inflation::round_issuance_range::(config.round); + // TODO: consider interpolation instead of bounded range + if staked < config.expect.min { + round_issuance.min + } else if staked > config.expect.max { + round_issuance.max + } else { + round_issuance.ideal + } + } + /// Remove delegation from candidate state + /// Amount input should be retrieved from delegator and it informs the storage lookups + pub(crate) fn delegator_leaves_candidate( + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.rm_delegation_if_exists::(&candidate, delegator.clone(), amount)?; + let new_total_locked = >::get().saturating_sub(amount); + >::put(new_total_locked); + let new_total = state.total_counted; + >::insert(&candidate, state); + Self::deposit_event(Event::DelegatorLeftCandidate { + delegator: delegator, + candidate: candidate, + unstaked_amount: amount, + total_candidate_staked: new_total, + }); + Ok(()) + } + pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { + // payout is now - delay rounds ago => now - delay > 0 else return early + let delay = T::RewardPaymentDelay::get(); + if now <= delay { + return Weight::zero(); + } + let round_to_payout = now.saturating_sub(delay); + let total_points = >::get(round_to_payout); + if total_points.is_zero() { + return Weight::zero(); + } + let total_staked = >::take(round_to_payout); + let total_issuance = Self::compute_issuance(total_staked); + let mut left_issuance = total_issuance; + // reserve portion of issuance for parachain bond account + let bond_config = >::get(); + let parachain_bond_reserve = bond_config.percent * total_issuance; + if let Ok(imb) = + T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) + { + // update round issuance iff transfer succeeds + left_issuance = left_issuance.saturating_sub(imb.peek()); + Self::deposit_event(Event::ReservedForParachainBond { + account: bond_config.account, + value: imb.peek(), + }); + } + + let payout = DelayedPayout { + round_issuance: total_issuance, + total_staking_reward: left_issuance, + collator_commission: >::get(), + }; + + >::insert(round_to_payout, payout); + T::WeightInfo::prepare_staking_payouts() + } + + /// Wrapper around pay_one_collator_reward which handles the following logic: + /// * whether or not a payout needs to be made + /// * cleaning up when payouts are done + /// * returns the weight consumed by pay_one_collator_reward if applicable + fn handle_delayed_payouts(now: RoundIndex) -> Weight { + let delay = T::RewardPaymentDelay::get(); + + // don't underflow uint + if now < delay { + return Weight::from_ref_time(0u64); + } + + let paid_for_round = now.saturating_sub(delay); + + if let Some(payout_info) = >::get(paid_for_round) { + let result = Self::pay_one_collator_reward(paid_for_round, payout_info); + + // clean up storage items that we no longer need + if matches!(result.0, RewardPayment::Finished) { + >::remove(paid_for_round); + >::remove(paid_for_round); + } + result.1 // weight consumed by pay_one_collator_reward + } else { + Weight::from_ref_time(0u64) + } + } + + /// Payout a single collator from the given round. + /// + /// Returns an optional tuple of (Collator's AccountId, total paid) + /// or None if there were no more payouts to be made for the round. + pub(crate) fn pay_one_collator_reward( + paid_for_round: RoundIndex, + payout_info: DelayedPayout>, + ) -> (RewardPayment, Weight) { + // 'early_weight' tracks weight used for reads/writes done early in this fn before its + // early-exit codepaths. + let mut early_weight = Weight::zero(); + + // TODO: it would probably be optimal to roll Points into the DelayedPayouts storage + // item so that we do fewer reads each block + let total_points = >::get(paid_for_round); + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 0)); + + if total_points.is_zero() { + // TODO: this case is obnoxious... it's a value query, so it could mean one of two + // different logic errors: + // 1. we removed it before we should have + // 2. we called pay_one_collator_reward when we were actually done with deferred + // payouts + log::warn!("pay_one_collator_reward called with no > for the round!"); + return (RewardPayment::Finished, early_weight); + } + + let collator_fee = payout_info.collator_commission; + let collator_issuance = collator_fee * payout_info.round_issuance; + + if let Some((collator, state)) = + >::iter_prefix(paid_for_round).drain().next() + { + // read and kill AtStake + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + + // Take the awarded points for the collator + let pts = >::take(paid_for_round, &collator); + // read and kill AwardedPts + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + if pts == 0 { + return (RewardPayment::Skipped, early_weight); + } + + // 'extra_weight' tracks weight returned from fns that we delegate to which can't be + // known ahead of time. + let mut extra_weight = Weight::zero(); + let pct_due = Perbill::from_rational(pts, total_points); + let total_paid = pct_due * payout_info.total_staking_reward; + let mut amt_due = total_paid; + + let num_delegators = state.delegations.len(); + if state.delegations.is_empty() { + // solo collator with no delegators + extra_weight = extra_weight + .saturating_add(T::PayoutCollatorReward::payout_collator_reward( + paid_for_round, + collator.clone(), + amt_due, + )) + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator.clone(), + amt_due, + )); + } else { + // pay collator first; commission + due_portion + let collator_pct = Perbill::from_rational(state.bond, state.total); + let commission = pct_due * collator_issuance; + amt_due = amt_due.saturating_sub(commission); + let collator_reward = (collator_pct * amt_due).saturating_add(commission); + extra_weight = extra_weight + .saturating_add(T::PayoutCollatorReward::payout_collator_reward( + paid_for_round, + collator.clone(), + collator_reward, + )) + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator.clone(), + collator_reward, + )); + + // pay delegators due portion + for BondWithAutoCompound { + owner, + amount, + auto_compound, + } in state.delegations + { + let percent = Perbill::from_rational(amount, state.total); + let due = percent * amt_due; + if !due.is_zero() { + extra_weight = extra_weight.saturating_add(Self::mint_and_compound( + due, + auto_compound.clone(), + collator.clone(), + owner.clone(), + )); + } + } + } + + ( + RewardPayment::Paid, + T::WeightInfo::pay_one_collator_reward(num_delegators as u32) + .saturating_add(extra_weight), + ) + } else { + // Note that we don't clean up storage here; it is cleaned up in + // handle_delayed_payouts() + (RewardPayment::Finished, Weight::from_ref_time(0u64.into())) + } + } + + /// Compute the top `TotalSelected` candidates in the CandidatePool and return + /// a vec of their AccountIds (in the order of selection) + pub fn compute_top_candidates() -> Vec { + let mut candidates = >::get().0; + // order candidates by stake (least to greatest so requires `rev()`) + candidates.sort_by(|a, b| a.amount.cmp(&b.amount)); + let top_n = >::get() as usize; + // choose the top TotalSelected qualified candidates, ordered by stake + let mut collators = candidates + .into_iter() + .rev() + .take(top_n) + .filter(|x| x.amount >= T::MinCollatorStk::get()) + .map(|x| x.owner) + .collect::>(); + collators.sort(); + collators + } + /// Best as in most cumulatively supported in terms of stake + /// Returns [collator_count, delegation_count, total staked] + pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { + let (mut collator_count, mut delegation_count, mut total) = + (0u32, 0u32, BalanceOf::::zero()); + // choose the top TotalSelected qualified candidates, ordered by stake + let collators = Self::compute_top_candidates(); + if collators.is_empty() { + // SELECTION FAILED TO SELECT >=1 COLLATOR => select collators from previous round + let last_round = now.saturating_sub(1u32); + let mut total_per_candidate: BTreeMap> = BTreeMap::new(); + // set this round AtStake to last round AtStake + for (account, snapshot) in >::iter_prefix(last_round) { + collator_count = collator_count.saturating_add(1u32); + delegation_count = + delegation_count.saturating_add(snapshot.delegations.len() as u32); + total = total.saturating_add(snapshot.total); + total_per_candidate.insert(account.clone(), snapshot.total); + >::insert(now, account, snapshot); + } + // `SelectedCandidates` remains unchanged from last round + // emit CollatorChosen event for tools that use this event + for candidate in >::get() { + let snapshot_total = total_per_candidate + .get(&candidate) + .expect("all selected candidates have snapshots"); + Self::deposit_event(Event::CollatorChosen { + round: now, + collator_account: candidate, + total_exposed_amount: *snapshot_total, + }) + } + let weight = T::WeightInfo::select_top_candidates(0, 0); + return (weight, collator_count, delegation_count, total); + } + + // snapshot exposure for round for weighting reward distribution + for account in collators.iter() { + let state = >::get(account) + .expect("all members of CandidateQ must be candidates"); + + collator_count = collator_count.saturating_add(1u32); + delegation_count = delegation_count.saturating_add(state.delegation_count); + total = total.saturating_add(state.total_counted); + let CountedDelegations { + uncounted_stake, + rewardable_delegations, + } = Self::get_rewardable_delegators(&account); + let total_counted = state.total_counted.saturating_sub(uncounted_stake); + + let auto_compounding_delegations = >::get(&account) + .into_iter() + .map(|x| (x.delegator, x.value)) + .collect::>(); + let rewardable_delegations = rewardable_delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner.clone(), + amount: d.amount, + auto_compound: auto_compounding_delegations + .get(&d.owner) + .cloned() + .unwrap_or_else(|| Percent::zero()), + }) + .collect(); + + let snapshot = CollatorSnapshot { + bond: state.bond, + delegations: rewardable_delegations, + total: total_counted, + }; + >::insert(now, account, snapshot); + Self::deposit_event(Event::CollatorChosen { + round: now, + collator_account: account.clone(), + total_exposed_amount: state.total_counted, + }); + } + // insert canonical collator set + >::put(collators); + + let avg_delegator_count = delegation_count.checked_div(collator_count).unwrap_or(0); + let weight = T::WeightInfo::select_top_candidates(collator_count, avg_delegator_count); + (weight, collator_count, delegation_count, total) + } + + /// Apply the delegator intent for revoke and decrease in order to build the + /// effective list of delegators with their intended bond amount. + /// + /// This will: + /// - if [DelegationChange::Revoke] is outstanding, set the bond amount to 0. + /// - if [DelegationChange::Decrease] is outstanding, subtract the bond by specified amount. + /// - else, do nothing + /// + /// The intended bond amounts will be used while calculating rewards. + pub(crate) fn get_rewardable_delegators(collator: &T::AccountId) -> CountedDelegations { + let requests = >::get(collator) + .into_iter() + .map(|x| (x.delegator, x.action)) + .collect::>(); + let mut uncounted_stake = BalanceOf::::zero(); + let rewardable_delegations = >::get(collator) + .expect("all members of CandidateQ must be candidates") + .delegations + .into_iter() + .map(|mut bond| { + bond.amount = match requests.get(&bond.owner) { + None => bond.amount, + Some(DelegationAction::Revoke(_)) => { + uncounted_stake = uncounted_stake.saturating_add(bond.amount); + BalanceOf::::zero() + } + Some(DelegationAction::Decrease(amount)) => { + uncounted_stake = uncounted_stake.saturating_add(*amount); + bond.amount.saturating_sub(*amount) + } + }; + + bond + }) + .collect(); + CountedDelegations { + uncounted_stake, + rewardable_delegations, + } + } + + /// This function exists as a helper to delegator_bond_more & auto_compound functionality. + /// Any changes to this function must align with both user-initiated bond increases and + /// auto-compounding bond increases. + /// Any feature-specific preconditions should be validated before this function is invoked. + /// Any feature-specific events must be emitted after this function is invoked. + pub fn delegation_bond_more_without_event( + delegator: T::AccountId, + candidate: T::AccountId, + more: BalanceOf, + ) -> Result { + ensure!( + !Self::delegation_request_revoke_exists(&candidate, &delegator), + Error::::PendingDelegationRevoke + ); + let mut state = >::get(&delegator).ok_or(Error::::DelegatorDNE)?; + state.increase_delegation::(candidate.clone(), more) + } + + /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. + pub fn mint(amt: BalanceOf, to: T::AccountId) { + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { + Self::deposit_event(Event::Rewarded { + account: to.clone(), + rewards: amount_transferred.peek(), + }); + } + } + + /// Mint a specified reward amount to the collator's account. Emits the [Rewarded] event. + pub fn mint_collator_reward( + _paid_for_round: RoundIndex, + collator_id: T::AccountId, + amt: BalanceOf, + ) -> Weight { + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&collator_id, amt) { + Self::deposit_event(Event::Rewarded { + account: collator_id.clone(), + rewards: amount_transferred.peek(), + }); + } + T::WeightInfo::mint_collator_reward() + } + + /// Mint and compound delegation rewards. The function mints the amount towards the + /// delegator and tries to compound a specified percent of it back towards the delegation. + /// If a scheduled delegation revoke exists, then the amount is only minted, and nothing is + /// compounded. Emits the [Compounded] event. + pub fn mint_and_compound( + amt: BalanceOf, + compound_percent: Percent, + candidate: T::AccountId, + delegator: T::AccountId, + ) -> Weight { + let mut weight = T::WeightInfo::mint_collator_reward(); + if let Ok(amount_transferred) = + T::Currency::deposit_into_existing(&delegator, amt.clone()) + { + Self::deposit_event(Event::Rewarded { + account: delegator.clone(), + rewards: amount_transferred.peek(), + }); + + let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); + if compound_amount.is_zero() { + return weight; + } + + if let Err(err) = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + compound_amount.clone(), + ) { + log::debug!( + "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", + candidate, + delegator, + err + ); + return weight; + }; + weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); + + Pallet::::deposit_event(Event::Compounded { + delegator, + candidate, + amount: compound_amount.clone(), + }); + }; + + weight + } + } + + /// Add reward points to block authors: + /// * 20 points to the block producer for producing a block in the chain + impl Pallet { + fn award_points_to_block_author() { + let author = T::BlockAuthor::get(); + let now = >::get().current; + let score_plus_20 = >::get(now, &author).saturating_add(20); + >::insert(now, author, score_plus_20); + >::mutate(now, |x| *x = x.saturating_add(20)); + } + } + + impl nimbus_primitives::CanAuthor for Pallet { + fn can_author(account: &T::AccountId, _slot: &u32) -> bool { + Self::is_selected_candidate(account) + } + } + + impl Get> for Pallet { + fn get() -> Vec { + Self::selected_candidates() + } + } +} diff --git a/external/pallets/parachain-staking/src/migrations.rs b/external/pallets/parachain-staking/src/migrations.rs new file mode 100644 index 000000000..db7128f88 --- /dev/null +++ b/external/pallets/parachain-staking/src/migrations.rs @@ -0,0 +1,182 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! # Migrations + +#![allow(unused)] + +use crate::delegation_requests::{DelegationAction, ScheduledRequest}; +use crate::pallet::{DelegationScheduledRequests, DelegatorState, Total}; +#[allow(deprecated)] +use crate::types::deprecated::{ + CollatorSnapshot as OldCollatorSnapshot, DelegationChange, Delegator as OldDelegator, +}; +use crate::types::{CollatorSnapshot, Delegator}; +use crate::{ + AtStake, BalanceOf, Bond, BondWithAutoCompound, BottomDelegations, CandidateInfo, + CandidateMetadata, CapacityStatus, CollatorCandidate, Config, DelayedPayouts, Delegations, + Event, Pallet, Points, Round, RoundIndex, Staked, TopDelegations, +}; +use frame_support::Twox64Concat; +use parity_scale_codec::{Decode, Encode}; +extern crate alloc; +#[cfg(feature = "try-runtime")] +use alloc::{format, string::ToString}; +use frame_support::{ + migration::storage_key_iter, + pallet_prelude::PhantomData, + storage, + traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, + weights::Weight, +}; +#[cfg(feature = "try-runtime")] +use scale_info::prelude::string::String; +use sp_runtime::traits::{Saturating, Zero}; +use sp_runtime::Percent; +use sp_std::{convert::TryInto, vec, vec::Vec}; + +/// Migrate `AtStake` storage item to include auto-compound value for unpaid rounds. +pub struct MigrateAtStakeAutoCompound(PhantomData); +impl MigrateAtStakeAutoCompound { + /// Get keys for the `AtStake` storage for the rounds up to `RewardPaymentDelay` rounds ago. + /// We migrate only the last unpaid rounds due to the presence of stale entries in `AtStake` + /// which significantly increase the PoV size. + fn unpaid_rounds_keys() -> impl Iterator)> { + let current_round = >::get().current; + let max_unpaid_round = current_round.saturating_sub(T::RewardPaymentDelay::get()); + (max_unpaid_round..=current_round) + .into_iter() + .flat_map(|round| { + >::iter_key_prefix(round).map(move |candidate| { + let key = >::hashed_key_for(round.clone(), candidate.clone()); + (round, candidate, key) + }) + }) + } +} +impl OnRuntimeUpgrade for MigrateAtStakeAutoCompound { + #[allow(deprecated)] + fn on_runtime_upgrade() -> Weight { + log::info!( + target: "MigrateAtStakeAutoCompound", + "running migration to add auto-compound values" + ); + let mut reads = 0u64; + let mut writes = 0u64; + for (round, candidate, key) in Self::unpaid_rounds_keys() { + let old_state: OldCollatorSnapshot> = + storage::unhashed::get(&key).expect("unable to decode value"); + reads = reads.saturating_add(1); + writes = writes.saturating_add(1); + log::info!( + target: "MigrateAtStakeAutoCompound", + "migration from old format round {:?}, candidate {:?}", round, candidate + ); + let new_state = CollatorSnapshot { + bond: old_state.bond, + delegations: old_state + .delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner, + amount: d.amount, + auto_compound: Percent::zero(), + }) + .collect(), + total: old_state.total, + }; + storage::unhashed::put(&key, &new_state); + } + + T::DbWeight::get().reads_writes(reads, writes) + } + + #[allow(deprecated)] + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let mut num_to_update = 0u32; + let mut rounds_candidates: Vec<(RoundIndex, T::AccountId)> = vec![]; + use sp_std::collections::btree_map::BTreeMap; + let mut state_map: BTreeMap = BTreeMap::new(); + + for (round, candidate, key) in Self::unpaid_rounds_keys() { + let state: OldCollatorSnapshot> = + storage::unhashed::get(&key).expect("unable to decode value"); + + num_to_update = num_to_update.saturating_add(1); + rounds_candidates.push((round.clone(), candidate.clone())); + let mut delegation_str = vec![]; + for d in state.delegations { + delegation_str.push(format!( + "owner={:?}_amount={:?}_autoCompound=0%", + d.owner, d.amount + )); + } + state_map.insert( + (&*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string(), + format!( + "bond={:?}_total={:?}_delegations={:?}", + state.bond, state.total, delegation_str + ), + ); + } + + rounds_candidates.sort(); + Ok((state_map, rounds_candidates, num_to_update).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let (state_map, rounds_candidates_received, num_updated_received): ( + BTreeMap, + Vec<(RoundIndex, T::AccountId)>, + u32, + ) = Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + let mut num_updated = 0u32; + let mut rounds_candidates = vec![]; + for (round, candidate, _) in Self::unpaid_rounds_keys() { + let state = >::get(&round, &candidate); + num_updated = num_updated.saturating_add(1); + rounds_candidates.push((round.clone(), candidate.clone())); + let mut delegation_str = vec![]; + for d in state.delegations { + delegation_str.push(format!( + "owner={:?}_amount={:?}_autoCompound={:?}", + d.owner, d.amount, d.auto_compound + )); + } + assert_eq!( + Some(&format!( + "bond={:?}_total={:?}_delegations={:?}", + state.bond, state.total, delegation_str + )), + state_map + .get(&((&*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string())), + "incorrect delegations migration for round_{:?}_candidate_{:?}", + round, + candidate, + ); + } + + rounds_candidates.sort(); + assert_eq!(rounds_candidates, rounds_candidates_received); + assert_eq!(num_updated, num_updated_received); + Ok(()) + } +} diff --git a/external/pallets/parachain-staking/src/mock.rs b/external/pallets/parachain-staking/src/mock.rs new file mode 100644 index 000000000..da794efa7 --- /dev/null +++ b/external/pallets/parachain-staking/src/mock.rs @@ -0,0 +1,1061 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Test utilities +use crate as pallet_parachain_staking; +use crate::{ + pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, + COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, +}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, GenesisBuild, LockIdentifier, OnFinalize, OnInitialize}, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_core::H256; +use sp_io; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + Perbill, Percent, +}; + +pub type AccountId = u64; +pub type Balance = u128; +pub type BlockNumber = u32; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Config, Event}, + BlockAuthor: block_author::{Pallet, Storage}, + } +); + +parameter_types! { + pub const BlockHashCount: u32 = 250; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const SS58Prefix: u8 = 42; +} +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} +impl pallet_balances::Config for Test { + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +impl block_author::Config for Test {} +const GENESIS_BLOCKS_PER_ROUND: u32 = 5; +const GENESIS_COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20); +const GENESIS_PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30); +parameter_types! { + pub const MinBlocksPerRound: u32 = 3; + pub const LeaveCandidatesDelay: u32 = 2; + pub const CandidateBondLessDelay: u32 = 2; + pub const LeaveDelegatorsDelay: u32 = 2; + pub const RevokeDelegationDelay: u32 = 2; + pub const DelegationBondLessDelay: u32 = 2; + pub const RewardPaymentDelay: u32 = 2; + pub const MinSelectedCandidates: u32 = 5; + pub const MaxTopDelegationsPerCandidate: u32 = 4; + pub const MaxBottomDelegationsPerCandidate: u32 = 4; + pub const MaxDelegationsPerDelegator: u32 = 4; + pub const MinCollatorStk: u128 = 10; + pub const MinDelegatorStk: u128 = 5; + pub const MinDelegation: u128 = 3; +} +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; + type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; + type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; + type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MinCollatorStk = MinCollatorStk; + type MinCandidateStk = MinCollatorStk; + type MinDelegatorStk = MinDelegatorStk; + type MinDelegation = MinDelegation; + type BlockAuthor = BlockAuthor; + type OnCollatorPayout = (); + type PayoutCollatorReward = (); + type OnNewRound = (); + type WeightInfo = (); +} + +pub(crate) struct ExtBuilder { + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, delegation_amount, auto_compound_percent] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // inflation config + inflation: InflationInfo, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + delegations: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { + min: 700, + ideal: 700, + max: 700, + }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + } + } +} + +impl ExtBuilder { + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub(crate) fn with_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance)>, + ) -> Self { + self.delegations = delegations + .into_iter() + .map(|d| (d.0, d.1, d.2, Percent::zero())) + .collect(); + self + } + + pub(crate) fn with_auto_compounding_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + ) -> Self { + self.delegations = delegations; + self + } + + #[allow(dead_code)] + pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: self.balances, + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + collator_commission: GENESIS_COLLATOR_COMMISSION, + parachain_bond_reserve_percent: GENESIS_PARACHAIN_BOND_RESERVE_PERCENT, + blocks_per_round: GENESIS_BLOCKS_PER_ROUND, + } + .assimilate_storage(&mut t) + .expect("Parachain Staking's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +/// Rolls forward one block. Returns the new block number. +fn roll_one_block() -> BlockNumber { + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::reset_events(); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + System::block_number() +} + +/// Rolls to the desired block. Returns the number of blocks played. +pub(crate) fn roll_to(n: BlockNumber) -> u32 { + let mut num_blocks = 0; + let mut block = System::block_number(); + while block < n { + block = roll_one_block(); + num_blocks += 1; + } + num_blocks +} + +/// Rolls desired number of blocks. Returns the final block. +pub(crate) fn roll_blocks(num_blocks: u32) -> BlockNumber { + let mut block = System::block_number(); + for _ in 0..num_blocks { + block = roll_one_block(); + } + block +} + +/// Rolls block-by-block to the beginning of the specified round. +/// This will complete the block in which the round change occurs. +/// Returns the number of blocks played. +pub(crate) fn roll_to_round_begin(round: BlockNumber) -> BlockNumber { + let block = (round - 1) * GENESIS_BLOCKS_PER_ROUND; + roll_to(block) +} + +/// Rolls block-by-block to the end of the specified round. +/// The block following will be the one in which the specified round change occurs. +pub(crate) fn roll_to_round_end(round: BlockNumber) -> BlockNumber { + let block = round * GENESIS_BLOCKS_PER_ROUND - 1; + roll_to(block) +} + +pub(crate) fn events() -> Vec> { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| { + if let RuntimeEvent::ParachainStaking(inner) = e { + Some(inner) + } else { + None + } + }) + .collect::>() +} + +/// Asserts that some events were never emitted. +/// +/// # Example +/// +/// ``` +/// assert_no_events!(); +/// ``` +#[macro_export] +macro_rules! assert_no_events { + () => { + similar_asserts::assert_eq!(Vec::>::new(), crate::mock::events()) + }; +} + +/// Asserts that emitted events match exactly the given input. +/// +/// # Example +/// +/// ``` +/// assert_events_eq!( +/// Foo { x: 1, y: 2 }, +/// Bar { value: "test" }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_eq { + ($event:expr) => { + similar_asserts::assert_eq!(vec![$event], crate::mock::events()); + }; + ($($events:expr,)+) => { + similar_asserts::assert_eq!(vec![$($events,)+], crate::mock::events()); + }; +} + +/// Asserts that some emitted events match the given input. +/// +/// # Example +/// +/// ``` +/// assert_events_emitted!( +/// Foo { x: 1, y: 2 }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_emitted { + ($event:expr) => { + [$event].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x == &e).is_some(), + "Event {:?} was not found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; + ($($events:expr,)+) => { + [$($events,)+].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x == &e).is_some(), + "Event {:?} was not found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; +} + +/// Asserts that some events were never emitted. +/// +/// # Example +/// +/// ``` +/// assert_events_not_emitted!( +/// Foo { x: 1, y: 2 }, +/// Bar { value: "test" }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_not_emitted { + ($event:expr) => { + [$event].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x != &e).is_some(), + "Event {:?} was unexpectedly found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; + ($($events:expr,)+) => { + [$($events,)+].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x != &e).is_some(), + "Event {:?} was unexpectedly found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; +} + +/// Asserts that the emitted events are exactly equal to the input patterns. +/// +/// # Example +/// +/// ``` +/// assert_events_eq_match!( +/// Foo { x: 1, .. }, +/// Bar { .. }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_eq_match { + ($index:expr;) => { + assert_eq!( + $index, + crate::mock::events().len(), + "Found {} extra event(s): \n{:#?}", + crate::mock::events().len()-$index, + crate::mock::events() + ); + }; + ($index:expr; $event:pat_param, $($events:pat_param,)*) => { + assert!( + matches!( + crate::mock::events().get($index), + Some($event), + ), + "Event {:#?} was not found at index {}: \n{:#?}", + stringify!($event), + $index, + crate::mock::events() + ); + assert_events_eq_match!($index+1; $($events,)*); + }; + ($event:pat_param) => { + assert_events_eq_match!(0; $event,); + }; + ($($events:pat_param,)+) => { + assert_events_eq_match!(0; $($events,)+); + }; +} + +/// Asserts that some emitted events match the input patterns. +/// +/// # Example +/// +/// ``` +/// assert_events_emitted_match!( +/// Foo { x: 1, .. }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_emitted_match { + ($event:pat_param) => { + assert!( + crate::mock::events().into_iter().any(|x| matches!(x, $event)), + "Event {:?} was not found in events: \n{:#?}", + stringify!($event), + crate::mock::events() + ); + }; + ($event:pat_param, $($events:pat_param,)+) => { + assert_events_emitted_match!($event); + $( + assert_events_emitted_match!($events); + )+ + }; +} + +/// Asserts that the input patterns match none of the emitted events. +/// +/// # Example +/// +/// ``` +/// assert_events_not_emitted_match!( +/// Foo { x: 1, .. }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_not_emitted_match { + ($event:pat_param) => { + assert!( + crate::mock::events().into_iter().any(|x| !matches!(x, $event)), + "Event {:?} was unexpectedly found in events: \n{:#?}", + stringify!($event), + crate::mock::events() + ); + }; + ($event:pat_param, $($events:pat_param,)+) => { + assert_events_not_emitted_match!($event); + $( + assert_events_not_emitted_match!($events); + )+ + }; +} + +// Same storage changes as ParachainStaking::on_finalize +pub(crate) fn set_author(round: BlockNumber, acc: u64, pts: u32) { + >::mutate(round, |p| *p += pts); + >::mutate(round, acc, |p| *p += pts); +} + +/// fn to query the lock amount +pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option { + for lock in Balances::locks(&account_id) { + if lock.id == id { + return Some(lock.amount); + } + } + None +} + +#[test] +fn geneses() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + assert_eq!( + ParachainStaking::get_collator_stakable_free_balance(&1), + 500 + ); + assert_eq!(query_lock_amount(1, COLLATOR_LOCK_ID), Some(500)); + assert!(ParachainStaking::is_candidate(&1)); + assert_eq!(query_lock_amount(2, COLLATOR_LOCK_ID), Some(200)); + assert_eq!( + ParachainStaking::get_collator_stakable_free_balance(&2), + 100 + ); + assert!(ParachainStaking::is_candidate(&2)); + // delegators + for x in 3..7 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 0); + assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(100)); + } + // uninvolved + for x in 7..10 { + assert!(!ParachainStaking::is_delegator(&x)); + } + // no delegator staking locks + assert_eq!(query_lock_amount(7, DELEGATOR_LOCK_ID), None); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&7), + 100 + ); + assert_eq!(query_lock_amount(8, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&8), 9); + assert_eq!(query_lock_amount(9, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&9), 4); + // no collator staking locks + assert_eq!( + ParachainStaking::get_collator_stakable_free_balance(&7), + 100 + ); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&8), 9); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&9), 4); + }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![ + (6, 1, 10), + (7, 1, 10), + (8, 2, 10), + (9, 2, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + for x in 1..5 { + assert!(ParachainStaking::is_candidate(&x)); + assert_eq!(query_lock_amount(x, COLLATOR_LOCK_ID), Some(20)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&x), 80); + } + assert!(ParachainStaking::is_candidate(&5)); + assert_eq!(query_lock_amount(5, COLLATOR_LOCK_ID), Some(10)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&5), 90); + // delegators + for x in 6..11 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(10)); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&x), + 90 + ); + } + }); +} + +#[frame_support::pallet] +pub mod block_author { + use super::*; + use frame_support::pallet_prelude::*; + use frame_support::traits::Get; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn block_author)] + pub(super) type BlockAuthor = StorageValue<_, AccountId, ValueQuery>; + + impl Get for Pallet { + fn get() -> AccountId { + >::get() + } + } +} + +#[test] +fn roll_to_round_begin_works() { + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_begin(1); + assert_eq!(System::block_number(), 1); // no-op, we're already on this round + assert_eq!(num_blocks, 0); + + let num_blocks = roll_to_round_begin(2); + assert_eq!(System::block_number(), 5); + assert_eq!(num_blocks, 4); + + let num_blocks = roll_to_round_begin(3); + assert_eq!(System::block_number(), 10); + assert_eq!(num_blocks, 5); + }); +} + +#[test] +fn roll_to_round_end_works() { + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_end(1); + assert_eq!(System::block_number(), 4); + assert_eq!(num_blocks, 3); + + let num_blocks = roll_to_round_end(2); + assert_eq!(System::block_number(), 9); + assert_eq!(num_blocks, 5); + + let num_blocks = roll_to_round_end(3); + assert_eq!(System::block_number(), 14); + assert_eq!(num_blocks, 5); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_extra() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 200, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_wrong_order() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 50, + }, + ); + }); +} + +#[test] +fn test_assert_events_eq_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }); + + assert_events_eq!(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }); + }); +} + +#[test] +fn test_assert_events_eq_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!(ParachainStakingEvent::DelegatorExitScheduled { + round: 2, + delegator: 3, + scheduled_exit: 4, + }); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 50, + }); + }); +} + +#[test] +fn test_assert_events_emitted_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }); + + assert_events_emitted!(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }); + }); +} + +#[test] +fn test_assert_events_emitted_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_extra() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ParachainStakingEvent::Rewarded { .. }, + ParachainStakingEvent::Rewarded { .. }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_wrong_order() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::Rewarded { .. }, + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ParachainStakingEvent::Rewarded { rewards: 50, .. }, + ); + }); +} + +#[test] +fn test_assert_events_eq_match_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }); + + assert_events_eq_match!(ParachainStakingEvent::Rewarded { account: 1, .. }); + }); +} + +#[test] +fn test_assert_events_eq_match_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + .. + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + .. + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_match_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!(ParachainStakingEvent::DelegatorExitScheduled { + round: 2, + .. + }); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_match_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 50, .. }); + }); +} + +#[test] +fn test_assert_events_emitted_match_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }); + + assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 100, .. }); + }); +} + +#[test] +fn test_assert_events_emitted_match_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!( + ParachainStakingEvent::CollatorChosen { + total_exposed_amount: 10, + .. + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ); + }); +} + +fn inject_test_events() { + [ + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { + account: 1, + rewards: 100, + }, + ] + .into_iter() + .for_each(System::deposit_event); +} diff --git a/external/pallets/parachain-staking/src/set.rs b/external/pallets/parachain-staking/src/set.rs new file mode 100644 index 000000000..8e4e29648 --- /dev/null +++ b/external/pallets/parachain-staking/src/set.rs @@ -0,0 +1,89 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +/* TODO: use orml_utilities::OrderedSet without leaking substrate v2.0 dependencies*/ +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; + +/// An ordered set backed by `Vec` +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Default, Clone, TypeInfo)] +pub struct OrderedSet(pub Vec); + +impl OrderedSet { + /// Create a new empty set + pub fn new() -> Self { + Self(Vec::new()) + } + + /// Create a set from a `Vec`. + /// `v` will be sorted and dedup first. + pub fn from(mut v: Vec) -> Self { + v.sort(); + v.dedup(); + Self::from_sorted_set(v) + } + + /// Create a set from a `Vec`. + /// Assume `v` is sorted and contain unique elements. + pub fn from_sorted_set(v: Vec) -> Self { + Self(v) + } + + /// Insert an element. + /// Return true if insertion happened. + pub fn insert(&mut self, value: T) -> bool { + match self.0.binary_search(&value) { + Ok(_) => false, + Err(loc) => { + self.0.insert(loc, value); + true + } + } + } + + /// Remove an element. + /// Return true if removal happened. + pub fn remove(&mut self, value: &T) -> bool { + match self.0.binary_search(value) { + Ok(loc) => { + self.0.remove(loc); + true + } + Err(_) => false, + } + } + + /// Return if the set contains `value` + pub fn contains(&self, value: &T) -> bool { + self.0.binary_search(value).is_ok() + } + + /// Clear the set + pub fn clear(&mut self) { + self.0.clear(); + } +} + +impl From> for OrderedSet { + fn from(v: Vec) -> Self { + Self::from(v) + } +} diff --git a/external/pallets/parachain-staking/src/tests.rs b/external/pallets/parachain-staking/src/tests.rs new file mode 100644 index 000000000..113c21e96 --- /dev/null +++ b/external/pallets/parachain-staking/src/tests.rs @@ -0,0 +1,9025 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! # Staking Pallet Unit Tests +//! The unit tests are organized by the call they test. The order matches the order +//! of the calls in the `lib.rs`. +//! 1. Root +//! 2. Monetary Governance +//! 3. Public (Collator, Nominator) +//! 4. Miscellaneous Property-Based Tests + +use crate::auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}; +use crate::delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}; +use crate::mock::{ + roll_blocks, roll_to, roll_to_round_begin, roll_to_round_end, set_author, Balances, + BlockNumber, ExtBuilder, ParachainStaking, RuntimeOrigin, Test, +}; +use crate::{ + assert_events_emitted, assert_events_emitted_match, assert_events_eq, assert_no_events, + AtStake, Bond, CollatorStatus, DelegationScheduledRequests, DelegatorAdded, DelegatorState, + DelegatorStatus, Error, Event, Range, DELEGATOR_LOCK_ID, +}; +use frame_support::{assert_noop, assert_ok}; +use sp_runtime::{traits::Zero, DispatchError, ModuleError, Perbill, Percent}; + +// ~~ ROOT ~~ + +#[test] +fn invalid_root_origin_fails() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::signed(45), 6u32), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_collator_commission( + RuntimeOrigin::signed(45), + Perbill::from_percent(5) + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::signed(45), 3u32), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +// SET TOTAL SELECTED + +#[test] +fn set_total_selected_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + // before we can bump total_selected we must bump the blocks per round + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 6u32 + )); + roll_blocks(1); + assert_ok!(ParachainStaking::set_total_selected( + RuntimeOrigin::root(), + 6u32 + )); + assert_events_eq!(Event::TotalSelectedSet { + old: 5u32, + new: 6u32 + }); + }); +} + +#[test] +fn set_total_selected_fails_if_above_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); // test relies on this + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); +} + +#[test] +fn set_total_selected_passes_if_equal_to_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 10u32 + )); + assert_ok!(ParachainStaking::set_total_selected( + RuntimeOrigin::root(), + 10u32 + )); + }); +} + +#[test] +fn set_total_selected_passes_if_below_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 10u32 + )); + assert_ok!(ParachainStaking::set_total_selected( + RuntimeOrigin::root(), + 9u32 + )); + }); +} + +#[test] +fn set_blocks_per_round_fails_if_below_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 20u32 + )); + assert_ok!(ParachainStaking::set_total_selected( + RuntimeOrigin::root(), + 15u32 + )); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 14u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); +} + +#[test] +fn set_blocks_per_round_passes_if_equal_to_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 10u32 + )); + assert_ok!(ParachainStaking::set_total_selected( + RuntimeOrigin::root(), + 9u32 + )); + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 9u32 + )); + }); +} + +#[test] +fn set_blocks_per_round_passes_if_above_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); // test relies on this + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 6u32 + )); + }); +} + +#[test] +fn set_total_selected_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + // round length must be >= total_selected, so update that first + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 10u32 + )); + + assert_eq!(ParachainStaking::total_selected(), 5u32); + assert_ok!(ParachainStaking::set_total_selected( + RuntimeOrigin::root(), + 6u32 + )); + assert_eq!(ParachainStaking::total_selected(), 6u32); + }); +} + +#[test] +fn cannot_set_total_selected_to_current_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 5u32), + Error::::NoWritingSameValue + ); + }); +} + +#[test] +fn cannot_set_total_selected_below_module_min() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 4u32), + Error::::CannotSetBelowMin + ); + }); +} + +// SET COLLATOR COMMISSION + +#[test] +fn set_collator_commission_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(5) + )); + assert_events_eq!(Event::CollatorCommissionSet { + old: Perbill::from_percent(20), + new: Perbill::from_percent(5), + }); + }); +} + +#[test] +fn set_collator_commission_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + ParachainStaking::collator_commission(), + Perbill::from_percent(20) + ); + assert_ok!(ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(5) + )); + assert_eq!( + ParachainStaking::collator_commission(), + Perbill::from_percent(5) + ); + }); +} + +#[test] +fn cannot_set_collator_commission_to_current_collator_commission() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(20) + ), + Error::::NoWritingSameValue + ); + }); +} + +// SET BLOCKS PER ROUND + +#[test] +fn set_blocks_per_round_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 6u32 + )); + assert_events_eq!(Event::BlocksPerRoundSet { + current_round: 1, + first_block: 0, + old: 5, + new: 6, + new_per_round_inflation_min: Perbill::from_parts(926), + new_per_round_inflation_ideal: Perbill::from_parts(926), + new_per_round_inflation_max: Perbill::from_parts(926), + }); + }); +} + +#[test] +fn set_blocks_per_round_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 6u32 + )); + assert_eq!(ParachainStaking::round().length, 6); + }); +} + +#[test] +fn cannot_set_blocks_per_round_below_module_min() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 2u32), + Error::::CannotSetBelowMin + ); + }); +} + +#[test] +fn cannot_set_blocks_per_round_to_current_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32), + Error::::NoWritingSameValue + ); + }); +} + +#[test] +fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // we can't lower the blocks per round because it must be above the number of collators, + // and we can't lower the number of collators because it must be above + // MinSelectedCandidates. so we first raise blocks per round, then lower it. + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 10u32 + )); + + roll_to(10); + assert_events_emitted!(Event::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 20 + },); + roll_to(17); + assert_ok!(ParachainStaking::set_blocks_per_round( + RuntimeOrigin::root(), + 5u32 + )); + roll_to(18); + assert_events_emitted!(Event::NewRound { + starting_block: 18, + round: 3, + selected_collators_number: 1, + total_balance: 20 + }); + }); +} + +// ~~ MONETARY GOVERNANCE ~~ + +#[test] +fn invalid_monetary_origin_fails() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::signed(45), + Range { + min: 3u32.into(), + ideal: 4u32.into(), + max: 5u32.into() + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::signed(45), + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::signed(45), + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_parachain_bond_account(RuntimeOrigin::signed(45), 11), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::signed(45), + Percent::from_percent(2) + ), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +// SET STAKING EXPECTATIONS + +#[test] +fn set_staking_event_emits_event_correctly() { + ExtBuilder::default().build().execute_with(|| { + // valid call succeeds + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { + min: 3u128, + ideal: 4u128, + max: 5u128, + } + )); + assert_events_eq!(Event::StakeExpectationsSet { + expect_min: 3u128, + expect_ideal: 4u128, + expect_max: 5u128, + }); + }); +} + +#[test] +fn set_staking_updates_storage_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { + min: 700, + ideal: 700, + max: 700 + } + ); + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { + min: 3u128, + ideal: 4u128, + max: 5u128, + } + )); + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { + min: 3u128, + ideal: 4u128, + max: 5u128 + } + ); + }); +} + +#[test] +fn cannot_set_invalid_staking_expectations() { + ExtBuilder::default().build().execute_with(|| { + // invalid call fails + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { + min: 5u128, + ideal: 4u128, + max: 3u128 + } + ), + Error::::InvalidSchedule + ); + }); +} + +#[test] +fn cannot_set_same_staking_expectations() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { + min: 3u128, + ideal: 4u128, + max: 5u128 + } + )); + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { + min: 3u128, + ideal: 4u128, + max: 5u128 + } + ), + Error::::NoWritingSameValue + ); + }); +} + +// SET INFLATION + +#[test] +fn set_inflation_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = ( + Perbill::from_percent(3), + Perbill::from_percent(4), + Perbill::from_percent(5), + ); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + )); + assert_events_eq!(Event::InflationSet { + annual_min: min, + annual_ideal: ideal, + annual_max: max, + round_min: Perbill::from_parts(57), + round_ideal: Perbill::from_parts(75), + round_max: Perbill::from_parts(93), + }); + }); +} + +#[test] +fn set_inflation_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = ( + Perbill::from_percent(3), + Perbill::from_percent(4), + Perbill::from_percent(5), + ); + assert_eq!( + ParachainStaking::inflation_config().annual, + Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50) + } + ); + assert_eq!( + ParachainStaking::inflation_config().round, + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5) + } + ); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); + assert_eq!( + ParachainStaking::inflation_config().annual, + Range { min, ideal, max } + ); + assert_eq!( + ParachainStaking::inflation_config().round, + Range { + min: Perbill::from_parts(57), + ideal: Perbill::from_parts(75), + max: Perbill::from_parts(93) + } + ); + }); +} + +#[test] +fn cannot_set_invalid_inflation() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(3) + } + ), + Error::::InvalidSchedule + ); + }); +} + +#[test] +fn cannot_set_same_inflation() { + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = ( + Perbill::from_percent(3), + Perbill::from_percent(4), + Perbill::from_percent(5), + ); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); + assert_noop!( + ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), + Error::::NoWritingSameValue + ); + }); +} + +// SET PARACHAIN BOND ACCOUNT + +#[test] +fn set_parachain_bond_account_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_parachain_bond_account( + RuntimeOrigin::root(), + 11 + )); + assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); + }); +} + +#[test] +fn set_parachain_bond_account_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::parachain_bond_info().account, 0); + assert_ok!(ParachainStaking::set_parachain_bond_account( + RuntimeOrigin::root(), + 11 + )); + assert_eq!(ParachainStaking::parachain_bond_info().account, 11); + }); +} + +// SET PARACHAIN BOND RESERVE PERCENT + +#[test] +fn set_parachain_bond_reserve_percent_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_events_eq!(Event::ParachainBondReservePercentSet { + old: Percent::from_percent(30), + new: Percent::from_percent(50), + }); + }); +} + +#[test] +fn set_parachain_bond_reserve_percent_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + ParachainStaking::parachain_bond_info().percent, + Percent::from_percent(30) + ); + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_eq!( + ParachainStaking::parachain_bond_info().percent, + Percent::from_percent(50) + ); + }); +} + +#[test] +fn cannot_set_same_parachain_bond_reserve_percent() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(30) + ), + Error::::NoWritingSameValue + ); + }); +} + +// ~~ PUBLIC ~~ + +// JOIN CANDIDATES + +#[test] +fn join_candidates_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 10u128, + 0u32 + )); + assert_events_eq!(Event::JoinedCollatorCandidates { + account: 1, + amount_locked: 10u128, + new_total_amt_locked: 10u128, + }); + }); +} + +#[test] +fn join_candidates_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 10u128, + 0u32 + )); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); +} + +#[test] +fn join_candidates_increases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 0); + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 10u128, + 0u32 + )); + assert_eq!(ParachainStaking::total(), 10); + }); +} + +#[test] +fn join_candidates_creates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::candidate_info(1).is_none()); + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 10u128, + 0u32 + )); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just joined => exists"); + assert_eq!(candidate_state.bond, 10u128); + }); +} + +#[test] +fn join_candidates_adds_to_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 10u128, + 0u32 + )); + let candidate_pool = ParachainStaking::candidate_pool(); + assert_eq!(candidate_pool.0[0].owner, 1); + assert_eq!(candidate_pool.0[0].amount, 10); + }); +} + +#[test] +fn cannot_join_candidates_if_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_candidates(vec![(1, 500)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), + Error::::CandidateExists + ); + }); +} + +#[test] +fn cannot_join_candidates_if_delegator() { + ExtBuilder::default() + .with_balances(vec![(1, 50), (2, 20)]) + .with_candidates(vec![(1, 50)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(2), 10u128, 1u32), + Error::::DelegatorExists + ); + }); +} + +#[test] +fn cannot_join_candidates_without_min_bond() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 9u128, 100u32), + Error::::CandidateBondBelowMin + ); + }); +} + +#[test] +fn cannot_join_candidates_with_more_than_available_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 500)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 501u128, 100u32), + DispatchError::Module(ModuleError { + index: 2, + error: [8, 0, 0, 0], + message: Some("InsufficientBalance") + }) + ); + }); +} + +#[test] +fn insufficient_join_candidates_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + for i in 0..5 { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 20, i), + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + } + }); +} + +#[test] +fn sufficient_join_candidates_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + let mut count = 5u32; + for i in 6..10 { + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(i), + 20, + count + )); + count += 1u32; + } + }); +} + +// SCHEDULE LEAVE CANDIDATES + +#[test] +fn leave_candidates_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 1, + candidate: 1, + scheduled_exit: 3 + }); + }); +} + +#[test] +fn leave_candidates_removes_candidate_from_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); +} + +#[test] +fn cannot_leave_candidates_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_leave_candidates_if_already_leaving_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateAlreadyLeaving + ); + }); +} + +#[test] +fn insufficient_leave_candidates_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + for i in 1..6 { + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 4u32), + Error::::TooLowCandidateCountToLeaveCandidates + ); + } + }); +} + +#[test] +fn sufficient_leave_candidates_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + let mut count = 5u32; + for i in 1..6 { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + count + )); + count -= 1u32; + } + }); +} + +// EXECUTE LEAVE CANDIDATES + +#[test] +fn execute_leave_candidates_emits_event() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 0 + )); + assert_events_emitted!(Event::CandidateLeft { + ex_candidate: 1, + unlocked_amount: 10, + new_total_amt_locked: 0 + }); + }); +} + +#[test] +fn execute_leave_candidates_callable_by_any_signed() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(2), + 1, + 0 + )); + }); +} + +#[test] +fn execute_leave_candidates_requires_correct_weight_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 10), (3, 10), (4, 10)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 10), (4, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + roll_to(10); + for i in 0..3 { + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, i), + Error::::TooLowCandidateDelegationCountToLeaveCandidates + ); + } + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(2), + 1, + 3 + )); + }); +} + +#[test] +fn execute_leave_candidates_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 0 + )); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); +} + +#[test] +fn execute_leave_candidates_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 10); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 0 + )); + assert_eq!(ParachainStaking::total(), 0); + }); +} + +#[test] +fn execute_leave_candidates_removes_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 0 + )); + assert!(ParachainStaking::candidate_info(1).is_none()); + }); +} + +#[test] +fn execute_leave_candidates_removes_pending_delegation_requests() { + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 15)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 1 + )); + assert!(ParachainStaking::candidate_info(1).is_none()); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation request not removed" + ); + assert!( + !>::contains_key(&1), + "the key was not removed from storage" + ); + }); +} + +#[test] +fn cannot_execute_leave_candidates_before_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(9); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(3), + 1, + 0 + )); + }); +} + +// CANCEL LEAVE CANDIDATES + +#[test] +fn cancel_leave_candidates_emits_event() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert_ok!(ParachainStaking::cancel_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); + }); +} + +#[test] +fn cancel_leave_candidates_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert_ok!(ParachainStaking::cancel_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + let candidate = + ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); + assert!(candidate.is_active()); + }); +} + +#[test] +fn cancel_leave_candidates_adds_to_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1u32 + )); + assert_ok!(ParachainStaking::cancel_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); + }); +} + +// GO OFFLINE + +#[test] +fn go_offline_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); + }); +} + +#[test] +fn go_offline_removes_candidate_from_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); +} + +#[test] +fn go_offline_updates_candidate_state_to_idle() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("is candidate, just offline"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + }); +} + +#[test] +fn cannot_go_offline_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_go_offline_if_already_offline() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(1)), + Error::::AlreadyOffline + ); + }); +} + +// GO ONLINE + +#[test] +fn go_online_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + roll_blocks(1); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); + }); +} + +#[test] +fn go_online_adds_to_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); +} + +#[test] +fn go_online_storage_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("offline still exists"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + }); +} + +#[test] +fn cannot_go_online_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_go_online_if_already_online() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::AlreadyActive + ); + }); +} + +#[test] +fn cannot_go_online_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::CannotGoOnlineIfLeaving + ); + }); +} + +// CANDIDATE BOND MORE + +#[test] +fn candidate_bond_more_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::candidate_bond_more( + RuntimeOrigin::signed(1), + 30 + )); + assert_events_eq!(Event::CandidateBondedMore { + candidate: 1, + amount: 30, + new_total_bond: 50 + }); + }); +} + +#[test] +fn candidate_bond_more_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); + assert_ok!(ParachainStaking::candidate_bond_more( + RuntimeOrigin::signed(1), + 30 + )); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); +} + +#[test] +fn candidate_bond_more_increases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::candidate_bond_more( + RuntimeOrigin::signed(1), + 30 + )); + total += 30; + assert_eq!(ParachainStaking::total(), total); + }); +} + +#[test] +fn candidate_bond_more_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + assert_ok!(ParachainStaking::candidate_bond_more( + RuntimeOrigin::signed(1), + 30 + )); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 50); + }); +} + +#[test] +fn candidate_bond_more_updates_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + assert_ok!(ParachainStaking::candidate_bond_more( + RuntimeOrigin::signed(1), + 30 + )); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); + }); +} + +// SCHEDULE CANDIDATE BOND LESS + +#[test] +fn schedule_candidate_bond_less_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_events_eq!(Event::CandidateBondLessRequested { + candidate: 1, + amount_to_decrease: 10, + execute_round: 3, + }); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_request_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 5 + )); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), + Error::::PendingCandidateRequestAlreadyExists + ); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(6), 50), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), + Error::::CandidateBondBelowMin + ); + }); +} + +#[test] +fn can_schedule_candidate_bond_less_if_leaving_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_exited_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 0 + )); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), + Error::::CandidateDNE + ); + }); +} + +// 2. EXECUTE BOND LESS REQUEST + +#[test] +fn execute_candidate_bond_less_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 50)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 30 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_candidate_bond_less( + RuntimeOrigin::signed(1), + 1 + )); + assert_events_eq!(Event::CandidateBondedLess { + candidate: 1, + amount: 30, + new_bond: 20 + }); + }); +} + +#[test] +fn execute_candidate_bond_less_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less( + RuntimeOrigin::signed(1), + 1 + )); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); +} + +#[test] +fn execute_candidate_bond_less_decreases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less( + RuntimeOrigin::signed(1), + 1 + )); + total -= 10; + assert_eq!(ParachainStaking::total(), total); + }); +} + +#[test] +fn execute_candidate_bond_less_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less( + RuntimeOrigin::signed(1), + 1 + )); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + }); +} + +#[test] +fn execute_candidate_bond_less_updates_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less( + RuntimeOrigin::signed(1), + 1 + )); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); +} + +// CANCEL CANDIDATE BOND LESS REQUEST + +#[test] +fn cancel_candidate_bond_less_emits_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less( + RuntimeOrigin::signed(1) + )); + assert_events_emitted!(Event::CancelledCandidateBondLess { + candidate: 1, + amount: 10, + execute_round: 3, + }); + }); +} + +#[test] +fn cancel_candidate_bond_less_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less( + RuntimeOrigin::signed(1) + )); + assert!(ParachainStaking::candidate_info(&1) + .unwrap() + .request + .is_none()); + }); +} + +#[test] +fn only_candidate_can_cancel_candidate_bond_less_request() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_noop!( + ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), + Error::::CandidateDNE + ); + }); +} + +// DELEGATE + +#[test] +fn delegate_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 10, + 0, + 0 + )); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }); + }); +} + +#[test] +fn delegate_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 10 + ); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 10, + 0, + 0 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); +} + +#[test] +fn delegate_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_none()); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 10, + 0, + 0 + )); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); + assert_eq!(delegator_state.total(), 10); + assert_eq!(delegator_state.delegations.0[0].owner, 1); + assert_eq!(delegator_state.delegations.0[0].amount, 10); + }); +} + +#[test] +fn delegate_updates_collator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); + assert!(top_delegations.delegations.is_empty()); + assert!(top_delegations.total.is_zero()); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 10, + 0, + 0 + )); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); + assert_eq!(candidate_state.total_counted, 40); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); + assert_eq!(top_delegations.delegations[0].owner, 2); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + }); +} + +#[test] +fn can_delegate_immediately_after_other_join_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 20, + 0 + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 20, + 0, + 0 + )); + }); +} + +#[test] +fn can_delegate_if_revoking() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 4, + 10, + 0, + 2 + )); + }); +} + +#[test] +fn cannot_delegate_if_full_and_new_delegation_less_than_or_equal_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 10, 8, 0), + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + }); +} + +#[test] +fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 11), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(11), + 1, + 11, + 8, + 0 + )); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); + assert_events_emitted!(Event::DelegatorLeft { + delegator: 10, + unstaked_amount: 10 + }); + }); +} + +#[test] +fn can_still_delegate_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 3, + 10, + 0, + 1 + ),); + }); +} + +#[test] +fn cannot_delegate_if_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0), + Error::::CandidateExists + ); + }); +} + +#[test] +fn cannot_delegate_if_already_delegated() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 1), + Error::::AlreadyDelegatedCandidate + ); + }); +} + +#[test] +fn cannot_delegate_more_than_max_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 6, 10, 0, 4), + Error::::ExceedMaxDelegationsPerDelegator, + ); + }); +} + +#[test] +fn sufficient_delegate_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + let mut count = 4u32; + for i in 7..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); + count += 1u32; + } + let mut count = 0u32; + for i in 3..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 2, + 10, + count, + 1u32 + )); + count += 1u32; + } + }); +} + +#[test] +fn insufficient_delegate_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + let mut count = 3u32; + for i in 7..11 { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32), + Error::::TooLowCandidateDelegationCountToDelegate + ); + } + // to set up for next error test + count = 4u32; + for i in 7..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); + count += 1u32; + } + count = 0u32; + for i in 3..11 { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 0u32), + Error::::TooLowDelegationCountToDelegate + ); + count += 1u32; + } + }); +} + +// SCHEDULE LEAVE DELEGATORS + +#[test] +fn schedule_leave_delegators_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); + }); +} + +#[test] +fn cannot_schedule_leave_delegators_if_already_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorAlreadyLeaving + ); + }); +} + +#[test] +fn cannot_schedule_leave_delegators_if_not_delegator() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorDNE + ); + }); +} + +// EXECUTE LEAVE DELEGATORS + +#[test] +fn execute_leave_delegators_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeft { + delegator: 2, + unstaked_amount: 10 + }); + }); +} + +#[test] +fn execute_leave_delegators_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 00 + ); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 10 + ); + assert_eq!(crate::mock::query_lock_amount(2, DELEGATOR_LOCK_ID), None); + }); +} + +#[test] +fn execute_leave_delegators_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 30); + }); +} + +#[test] +fn execute_leave_delegators_removes_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_some()); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::delegator_state(2).is_none()); + }); +} + +#[test] +fn execute_leave_delegators_removes_pending_delegation_requests() { + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 15)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::delegator_state(2).is_none()); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation request not removed" + ) + }); +} + +#[test] +fn execute_leave_delegators_removes_delegations_from_collator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(2, 20), (3, 20), (4, 20), (5, 20)]) + .with_delegations(vec![(1, 2, 10), (1, 3, 10), (1, 4, 10), (1, 5, 10)]) + .build() + .execute_with(|| { + for i in 2..6 { + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + assert_eq!(top_delegations.delegations[0].owner, 1); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + } + assert_eq!( + ParachainStaking::delegator_state(1) + .unwrap() + .delegations + .0 + .len(), + 4usize + ); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(1) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(1), + 1, + 10 + )); + for i in 2..6 { + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + assert_eq!(candidate_state.total_counted, 20); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + assert!(top_delegations.delegations.is_empty()); + } + }); +} + +#[test] +fn cannot_execute_leave_delegators_before_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorCannotLeaveYet + ); + // can execute after delay + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); +} + +#[test] +fn cannot_execute_leave_delegators_if_single_delegation_revoke_manually_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 3 + )); + roll_to(10); + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2), + Error::::DelegatorNotLeaving + ); + // can execute after manually scheduling revoke, and the round delay after which + // all revokes can be executed + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 3 + )); + roll_to(20); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 2 + )); + }); +} + +#[test] +fn insufficient_execute_leave_delegators_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + for i in 3..7 { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(i) + )); + } + roll_to(10); + for i in 3..7 { + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 0), + Error::::TooLowDelegationCountToLeaveDelegators + ); + } + }); +} + +#[test] +fn sufficient_execute_leave_delegators_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + for i in 3..7 { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(i) + )); + } + roll_to(10); + for i in 3..7 { + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(i), + i, + 1 + )); + } + }); +} + +// CANCEL LEAVE DELEGATORS + +#[test] +fn cancel_leave_delegators_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_ok!(ParachainStaking::cancel_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_events_emitted!(Event::DelegatorExitCancelled { delegator: 2 }); + }); +} + +#[test] +fn cancel_leave_delegators_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_ok!(ParachainStaking::cancel_leave_delegators( + RuntimeOrigin::signed(2) + )); + let delegator = + ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); + assert!(delegator.is_active()); + }); +} + +#[test] +fn cannot_cancel_leave_delegators_if_single_delegation_revoke_manually_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 3 + )); + roll_to(10); + assert_noop!( + ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorNotLeaving + ); + // can execute after manually scheduling revoke, without waiting for round delay after + // which all revokes can be executed + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 3 + )); + assert_ok!(ParachainStaking::cancel_leave_delegators( + RuntimeOrigin::signed(2) + )); + }); +} + +// SCHEDULE REVOKE DELEGATION + +#[test] +fn revoke_delegation_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + roll_to_round_begin(3); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_eq!( + Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }, + Event::DelegationRevoked { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + }, + ); + }); +} + +#[test] +fn can_revoke_delegation_if_revoking_another_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + // this is an exit implicitly because last delegation revoked + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 3 + )); + }); +} + +#[test] +fn delegator_not_allowed_revoke_if_already_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), + >::PendingDelegationRequestAlreadyExists, + ); + }); +} + +#[test] +fn cannot_revoke_delegation_if_not_delegator() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1), + Error::::DelegatorDNE + ); + }); +} + +#[test] +fn cannot_revoke_delegation_that_dne() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), + Error::::DelegationDNE + ); + }); +} + +#[test] +// See `cannot_execute_revoke_delegation_below_min_delegator_stake` for where the "must be above +// MinDelegatorStk" rule is now enforced. +fn can_schedule_revoke_delegation_below_min_delegator_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 8), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + }); +} + +// DELEGATOR BOND MORE + +#[test] +fn delegator_bond_more_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); +} + +#[test] +fn delegator_bond_more_increases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_eq!(ParachainStaking::total(), 45); + }); +} + +#[test] +fn delegator_bond_more_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::delegator_state(2) + .expect("exists") + .total(), + 10 + ); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_eq!( + ParachainStaking::delegator_state(2) + .expect("exists") + .total(), + 15 + ); + }); +} + +#[test] +fn delegator_bond_more_updates_candidate_state_top_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, + 10 + ); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, + 15 + ); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 15); + }); +} + +#[test] +fn delegator_bond_more_updates_candidate_state_bottom_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + ]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::bottom_delegations(1) + .expect("exists") + .delegations[0] + .owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1) + .expect("exists") + .delegations[0] + .amount, + 10 + ); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_events_eq!(Event::DelegationIncreased { + delegator: 2, + candidate: 1, + amount: 5, + in_top: false + }); + assert_eq!( + ParachainStaking::bottom_delegations(1) + .expect("exists") + .delegations[0] + .owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1) + .expect("exists") + .delegations[0] + .amount, + 15 + ); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); + }); +} + +#[test] +fn delegator_bond_more_increases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_eq!(ParachainStaking::total(), 45); + }); +} + +#[test] +fn can_delegator_bond_more_for_leaving_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + }); +} + +#[test] +fn delegator_bond_more_disallowed_when_revoke_scheduled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_noop!( + ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5), + >::PendingDelegationRevoke + ); + }); +} + +#[test] +fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5, + )); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 1, + 5 + )); + }); +} + +// DELEGATOR BOND LESS + +#[test] +fn delegator_bond_less_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + delegator: 2, + candidate: 1, + amount_to_decrease: 5, + execute_round: 3, + }); + }); +} + +#[test] +fn delegator_bond_less_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + }); +} + +#[test] +fn delegator_not_allowed_bond_less_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), + >::PendingDelegationRequestAlreadyExists, + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_revoking() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), + Error::::PendingDelegationRequestAlreadyExists + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_not_delegator() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5), + Error::::DelegatorDNE + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_candidate_dne() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), + Error::::DelegationDNE + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_delegation_dne() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), + Error::::DelegationDNE + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_below_min_collator_stk() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 6), + Error::::DelegatorBondBelowMin + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_more_than_total_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 11), + Error::::DelegatorBondBelowMin + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_below_min_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 8), + Error::::DelegationBelowMin + ); + }); +} + +// EXECUTE PENDING DELEGATION REQUEST + +// 1. REVOKE DELEGATION + +#[test] +fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { + // last delegation is revocation + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + assert_events_emitted!(Event::DelegatorLeft { + delegator: 2, + unstaked_amount: 10 + }); + }); +} + +#[test] +fn cannot_execute_revoke_delegation_below_min_delegator_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 8), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_noop!( + ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorBondBelowMin + ); + // but delegator can cancel the request and request to leave instead: + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(20); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 2 + )); + }); +} + +#[test] +fn revoke_delegation_executes_exit_if_last_delegation() { + // last delegation is revocation + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + assert_events_emitted!(Event::DelegatorLeft { + delegator: 2, + unstaked_amount: 10 + }); + }); +} + +#[test] +fn execute_revoke_delegation_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + }); +} + +#[test] +fn execute_revoke_delegation_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 10 + ); + }); +} + +#[test] +fn execute_revoke_delegation_adds_revocation_to_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert!(ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + }); +} + +#[test] +fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execution() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + }); +} + +#[test] +fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation_leave() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation was not removed" + ); + }); +} + +#[test] +fn execute_revoke_delegation_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 30); + }); +} + +#[test] +fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_some()); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + // this will be confusing for people + // if status is leaving, then execute_delegation_request works if last delegation + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::delegator_state(2).is_none()); + }); +} + +#[test] +fn execute_revoke_delegation_removes_delegation_from_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::candidate_info(1) + .expect("exists") + .delegation_count, + 1u32 + ); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::candidate_info(1) + .expect("exists") + .delegation_count + .is_zero()); + }); +} + +#[test] +fn can_execute_revoke_delegation_for_leaving_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + // can execute delegation request for leaving candidate + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); +} + +#[test] +fn can_execute_leave_candidates_if_revoking_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + // revocation executes during execute leave candidates (callable by anyone) + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 1 + )); + assert!(!ParachainStaking::is_delegator(&2)); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 10); + }); +} + +#[test] +fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(2), + 3, + 10 + )); + roll_to(100); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::is_delegator(&2)); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 10 + ); + }); +} + +#[test] +fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), + Error::::PendingDelegationRequestAlreadyExists + ); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 3, + 2 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); + assert_events_eq!( + Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30, + }, + Event::DelegationRevoked { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + }, + Event::DelegationDecreased { + delegator: 2, + candidate: 3, + amount: 2, + in_top: true + }, + ); + assert!(ParachainStaking::is_delegator(&2)); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 22 + ); + }); +} + +// 2. EXECUTE BOND LESS + +#[test] +fn execute_delegator_bond_less_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); + }); +} + +#[test] +fn execute_delegator_bond_less_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 35); + }); +} + +#[test] +fn execute_delegator_bond_less_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::delegator_state(2) + .expect("exists") + .total(), + 10 + ); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::delegator_state(2) + .expect("exists") + .total(), + 5 + ); + }); +} + +#[test] +fn execute_delegator_bond_less_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, + 10 + ); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, + 5 + ); + }); +} + +#[test] +fn execute_delegator_bond_less_decreases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 35); + }); +} + +#[test] +fn execute_delegator_bond_less_updates_just_bottom_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 11), + (4, 1, 12), + (5, 1, 14), + (6, 1, 15), + ]) + .build() + .execute_with(|| { + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 2 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let post_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + let mut not_equal = false; + for Bond { owner, amount } in pre_call_bottom_delegations.delegations { + for Bond { + owner: post_owner, + amount: post_amount, + } in &post_call_bottom_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + not_equal = true; + break; + } + } + } + } + assert!(not_equal); + let mut equal = true; + for Bond { owner, amount } in pre_call_top_delegations.delegations { + for Bond { + owner: post_owner, + amount: post_amount, + } in &post_call_top_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + equal = false; + break; + } + } + } + } + assert!(equal); + assert_eq!( + pre_call_candidate_info.total_counted, + post_call_candidate_info.total_counted + ); + }); +} + +#[test] +fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 11), + (4, 1, 12), + (5, 1, 14), + (6, 1, 15), + ]) + .build() + .execute_with(|| { + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 4 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let post_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + let mut equal = true; + for Bond { owner, amount } in pre_call_bottom_delegations.delegations { + for Bond { + owner: post_owner, + amount: post_amount, + } in &post_call_bottom_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + equal = false; + break; + } + } + } + } + assert!(equal); + let mut not_equal = false; + for Bond { owner, amount } in pre_call_top_delegations.delegations { + for Bond { + owner: post_owner, + amount: post_amount, + } in &post_call_top_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + not_equal = true; + break; + } + } + } + } + assert!(not_equal); + assert_eq!( + pre_call_candidate_info.total_counted - 4, + post_call_candidate_info.total_counted + ); + }); +} + +#[test] +fn can_execute_delegator_bond_less_for_leaving_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 1 + )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + // can execute bond more delegation request for leaving candidate + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); +} + +// CANCEL PENDING DELEGATION REQUEST +// 1. CANCEL REVOKE DELEGATION + +#[test] +fn cancel_revoke_delegation_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + assert_events_emitted!(Event::CancelledDelegationRequest { + delegator: 2, + collator: 1, + cancelled_request: CancelledScheduledRequest { + when_executable: 3, + action: DelegationAction::Revoke(10), + }, + }); + }); +} + +#[test] +fn cancel_revoke_delegation_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(10), + }], + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10 + ); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); +} + +// 2. CANCEL DELEGATOR BOND LESS + +#[test] +fn cancel_delegator_bond_less_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + assert_events_emitted!(Event::CancelledDelegationRequest { + delegator: 2, + collator: 1, + cancelled_request: CancelledScheduledRequest { + when_executable: 3, + action: DelegationAction::Decrease(5), + }, + }); + }); +} + +#[test] +fn cancel_delegator_bond_less_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 5 + ); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); +} + +// ~~ PROPERTY-BASED TESTS ~~ + +#[test] +fn delegator_schedule_revocation_total() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10 + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 5, + 10, + 0, + 2 + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 3 + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 4 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 20, + ); + roll_to(20); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10, + ); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 4 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); +} + +#[ignore] +#[test] +fn parachain_bond_inflation_reserve_matches_config() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + (11, 1), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![ + (6, 1, 10), + (7, 1, 10), + (8, 2, 10), + (9, 2, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1); + // set parachain bond account so DefaultParachainBondReservePercent = 30% of inflation + // is allocated to this account hereafter + assert_ok!(ParachainStaking::set_parachain_bond_account( + RuntimeOrigin::root(), + 11 + )); + assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 2, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, + ); + assert_eq!(Balances::free_balance(&11), 1); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + // distribute total issuance to collator 1 and its delegators 6, 7, 19 + assert_eq!(Balances::free_balance(&11), 16); + // ~ set block author as 1 for all blocks this round + set_author(3, 1, 100); + set_author(4, 1, 100); + set_author(5, 1, 100); + // 1. ensure delegators are paid for 2 rounds after they leave + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), + Error::::DelegatorDNE + ); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(6) + )); + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 15, + }, + Event::CollatorChosen { + round: 4, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 4, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 4, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 4, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 4, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 5, + total_balance: 140, + }, + Event::DelegatorExitScheduled { + round: 4, + delegator: 6, + scheduled_exit: 6, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 20, + }, + Event::Rewarded { + account: 6, + rewards: 5, + }, + Event::Rewarded { + account: 7, + rewards: 5, + }, + Event::Rewarded { + account: 10, + rewards: 5, + }, + ); + // fast forward to block in which delegator 6 exit executes + roll_to_round_begin(5); + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 16, + }, + Event::CollatorChosen { + round: 5, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 5, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 5, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 5, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 5, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 21, + }, + Event::Rewarded { + account: 6, + rewards: 5, + }, + Event::Rewarded { + account: 7, + rewards: 5, + }, + Event::Rewarded { + account: 10, + rewards: 5, + }, + ); + roll_to_round_begin(6); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(6), + 6, + 10 + )); + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 16, + }, + Event::CollatorChosen { + round: 6, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 6, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 6, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 6, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 6, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 140, + }, + Event::DelegatorLeftCandidate { + delegator: 6, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 40, + }, + Event::DelegatorLeft { + delegator: 6, + unstaked_amount: 10, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 22, + }, + Event::Rewarded { + account: 6, + rewards: 6, + }, + Event::Rewarded { + account: 7, + rewards: 6, + }, + Event::Rewarded { + account: 10, + rewards: 6, + }, + ); + roll_to_round_begin(7); + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 17, + }, + Event::CollatorChosen { + round: 7, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 7, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 7, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 7, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 7, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 26, + }, + Event::Rewarded { + account: 7, + rewards: 7, + }, + Event::Rewarded { + account: 10, + rewards: 7, + }, + ); + assert_eq!(Balances::free_balance(&11), 65); + roll_blocks(1); + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_events_eq!(Event::ParachainBondReservePercentSet { + old: Percent::from_percent(30), + new: Percent::from_percent(50), + }); + // 6 won't be paid for this round because they left already + set_author(6, 1, 100); + roll_to_round_begin(8); + // keep paying 6 + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 30, + }, + Event::CollatorChosen { + round: 8, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 8, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 8, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 8, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 8, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 21, + }, + Event::Rewarded { + account: 7, + rewards: 5, + }, + Event::Rewarded { + account: 10, + rewards: 5, + }, + ); + assert_eq!(Balances::free_balance(&11), 95); + set_author(7, 1, 100); + roll_to_round_begin(9); + // no more paying 6 + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 32, + }, + Event::CollatorChosen { + round: 9, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 9, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 9, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 9, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 9, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 22, + }, + Event::Rewarded { + account: 7, + rewards: 5, + }, + Event::Rewarded { + account: 10, + rewards: 5, + }, + ); + assert_eq!(Balances::free_balance(&11), 127); + set_author(8, 1, 100); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(8), + 1, + 10, + 10, + 10 + )); + assert_events_eq!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + roll_to_round_begin(10); + // new delegation is not rewarded yet + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 33, + }, + Event::CollatorChosen { + round: 10, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 10, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 10, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 10, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 10, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 23, + }, + Event::Rewarded { + account: 7, + rewards: 5, + }, + Event::Rewarded { + account: 10, + rewards: 5, + }, + ); + assert_eq!(Balances::free_balance(&11), 160); + set_author(9, 1, 100); + set_author(10, 1, 100); + roll_to_round_begin(11); + // new delegation is still not rewarded yet + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 35, + }, + Event::CollatorChosen { + round: 11, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 11, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 11, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 11, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 11, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 24, + }, + Event::Rewarded { + account: 7, + rewards: 5, + }, + Event::Rewarded { + account: 10, + rewards: 5, + }, + ); + assert_eq!(Balances::free_balance(&11), 195); + roll_to_round_begin(12); + // new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2) + assert_events_eq!( + Event::ReservedForParachainBond { + account: 11, + value: 37, + }, + Event::CollatorChosen { + round: 12, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 12, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 12, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 12, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 12, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 24, + }, + Event::Rewarded { + account: 7, + rewards: 4, + }, + Event::Rewarded { + account: 10, + rewards: 4, + }, + Event::Rewarded { + account: 8, + rewards: 4, + }, + ); + assert_eq!(Balances::free_balance(&11), 232); + }); +} + +#[test] +fn paid_collator_commission_matches_config() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(4), + 20u128, + 100u32 + )); + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 1, + total_balance: 40, + }, + Event::JoinedCollatorCandidates { + account: 4, + amount_locked: 20, + new_total_amt_locked: 60, + }, + ); + + roll_blocks(1); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(5), + 4, + 10, + 10, + 10 + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(6), + 4, + 10, + 10, + 10 + )); + assert_events_eq!( + Event::Delegation { + delegator: 5, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }, + ); + + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { + round: 3, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 3, + collator_account: 4, + total_exposed_amount: 40, + }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 80, + }, + ); + // only reward author with id 4 + set_author(3, 4, 100); + roll_to_round_begin(5); + // 20% of 10 is commission + due_portion (0) = 2 + 4 = 6 + // all delegator payouts are 10-2 = 8 * stake_pct + assert_events_eq!( + Event::CollatorChosen { + round: 5, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 5, + collator_account: 4, + total_exposed_amount: 40, + }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 2, + total_balance: 80, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 4, + rewards: 18, + }, + Event::Rewarded { + account: 5, + rewards: 6, + }, + Event::Rewarded { + account: 6, + rewards: 6, + }, + ); + }); +} + +#[test] +fn collator_exit_executes_after_delay() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + roll_to(11); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(2), + 2 + )); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 3, + candidate: 2, + scheduled_exit: 5, + }); + let info = ParachainStaking::candidate_info(&2).unwrap(); + assert_eq!(info.status, CollatorStatus::Leaving(5)); + roll_to(21); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(2), + 2, + 2 + )); + // we must exclude leaving collators from rewards while + // holding them retroactively accountable for previous faults + // (within the last T::SlashingWindow blocks) + assert_events_eq!(Event::CandidateLeft { + ex_candidate: 2, + unlocked_amount: 400, + new_total_amt_locked: 700, + },); + }); +} + +#[test] +fn collator_selection_chooses_top_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 33), + (8, 33), + (9, 33), + ]) + .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(6), + 6 + )); + // should choose top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 100, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 90, + }, + Event::CollatorChosen { + round: 2, + collator_account: 3, + total_exposed_amount: 80, + }, + Event::CollatorChosen { + round: 2, + collator_account: 4, + total_exposed_amount: 70, + }, + Event::CollatorChosen { + round: 2, + collator_account: 5, + total_exposed_amount: 60, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 400, + }, + Event::CandidateScheduledExit { + exit_allowed_round: 2, + candidate: 6, + scheduled_exit: 4 + }, + ); + roll_to_round_begin(4); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(6), + 6, + 0 + )); + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(6), + 69u128, + 100u32 + )); + assert_events_eq!( + Event::CandidateLeft { + ex_candidate: 6, + unlocked_amount: 50, + new_total_amt_locked: 400, + }, + Event::JoinedCollatorCandidates { + account: 6, + amount_locked: 69u128, + new_total_amt_locked: 469u128, + }, + ); + roll_to_round_begin(6); + // should choose top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { + round: 6, + collator_account: 1, + total_exposed_amount: 100, + }, + Event::CollatorChosen { + round: 6, + collator_account: 2, + total_exposed_amount: 90, + }, + Event::CollatorChosen { + round: 6, + collator_account: 3, + total_exposed_amount: 80, + }, + Event::CollatorChosen { + round: 6, + collator_account: 4, + total_exposed_amount: 70, + }, + Event::CollatorChosen { + round: 6, + collator_account: 6, + total_exposed_amount: 69, + }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 409, + }, + ); + }); +} + +#[test] +fn payout_distribution_to_solo_collators() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (7, 33), + (8, 33), + (9, 33), + ]) + .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // should choose top TotalCandidatesSelected (5), in order + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 100, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 90, + }, + Event::CollatorChosen { + round: 2, + collator_account: 3, + total_exposed_amount: 80, + }, + Event::CollatorChosen { + round: 2, + collator_account: 4, + total_exposed_amount: 70, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 340, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + assert_events_eq!( + Event::CollatorChosen { + round: 4, + collator_account: 1, + total_exposed_amount: 100, + }, + Event::CollatorChosen { + round: 4, + collator_account: 2, + total_exposed_amount: 90, + }, + Event::CollatorChosen { + round: 4, + collator_account: 3, + total_exposed_amount: 80, + }, + Event::CollatorChosen { + round: 4, + collator_account: 4, + total_exposed_amount: 70, + }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 340, + }, + ); + // pay total issuance to 1 at 2nd block + roll_blocks(3); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 205, + }); + // ~ set block author as 1 for 3 blocks this round + set_author(4, 1, 60); + // ~ set block author as 2 for 2 blocks this round + set_author(4, 2, 40); + roll_to_round_begin(6); + // pay 60% total issuance to 1 and 40% total issuance to 2 + assert_events_eq!( + Event::CollatorChosen { + round: 6, + collator_account: 1, + total_exposed_amount: 100, + }, + Event::CollatorChosen { + round: 6, + collator_account: 2, + total_exposed_amount: 90, + }, + Event::CollatorChosen { + round: 6, + collator_account: 3, + total_exposed_amount: 80, + }, + Event::CollatorChosen { + round: 6, + collator_account: 4, + total_exposed_amount: 70, + }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 340, + }, + ); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 129, + }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 2, + rewards: 86, + },); + // ~ each collator produces 1 block this round + set_author(6, 1, 20); + set_author(6, 2, 20); + set_author(6, 3, 20); + set_author(6, 4, 20); + roll_to_round_begin(8); + // pay 20% issuance for all collators + assert_events_eq!( + Event::CollatorChosen { + round: 8, + collator_account: 1, + total_exposed_amount: 100, + }, + Event::CollatorChosen { + round: 8, + collator_account: 2, + total_exposed_amount: 90, + }, + Event::CollatorChosen { + round: 8, + collator_account: 3, + total_exposed_amount: 80, + }, + Event::CollatorChosen { + round: 8, + collator_account: 4, + total_exposed_amount: 70, + }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 340, + }, + ); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 3, + rewards: 56, + }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 4, + rewards: 56, + }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 56, + }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 2, + rewards: 56, + }); + // check that distributing rewards clears awarded pts + assert!(ParachainStaking::awarded_pts(1, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(4, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(4, 2).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 2).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 3).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 4).is_zero()); + }); +} + +#[test] +fn multiple_delegations() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![ + (6, 1, 10), + (7, 1, 10), + (8, 2, 10), + (9, 2, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 2, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(6), + 2, + 10, + 10, + 10 + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(6), + 3, + 10, + 10, + 10 + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(6), + 4, + 10, + 10, + 10 + )); + assert_events_eq!( + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 2, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 3, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + ); + roll_to_round_begin(6); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(7), + 2, + 80, + 10, + 10 + )); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(10), + 2, + 10, + 10, + 10 + )); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(2), + 5 + )); + assert_events_eq!( + Event::Delegation { + delegator: 7, + locked_amount: 80, + candidate: 2, + delegator_position: DelegatorAdded::AddedToTop { new_total: 130 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 10, + locked_amount: 10, + candidate: 2, + delegator_position: DelegatorAdded::AddedToBottom, + auto_compound: Percent::zero(), + }, + Event::CandidateScheduledExit { + exit_allowed_round: 6, + candidate: 2, + scheduled_exit: 8 + }, + ); + roll_to_round_begin(7); + assert_events_eq!( + Event::CollatorChosen { + round: 7, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 7, + collator_account: 3, + total_exposed_amount: 30, + }, + Event::CollatorChosen { + round: 7, + collator_account: 4, + total_exposed_amount: 30, + }, + Event::CollatorChosen { + round: 7, + collator_account: 5, + total_exposed_amount: 10, + }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, + ); + // verify that delegations are removed after collator leaves, not before + assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); + assert_eq!( + ParachainStaking::delegator_state(7) + .unwrap() + .delegations + .0 + .len(), + 2usize + ); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 40); + assert_eq!( + ParachainStaking::delegator_state(6) + .unwrap() + .delegations + .0 + .len(), + 4usize + ); + assert_eq!(Balances::locks(&6)[0].amount, 40); + assert_eq!(Balances::locks(&7)[0].amount, 90); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&6), + 60 + ); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&7), + 10 + ); + roll_to_round_begin(8); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(2), + 2, + 5 + )); + assert_events_eq!(Event::CandidateLeft { + ex_candidate: 2, + unlocked_amount: 140, + new_total_amt_locked: 120, + }); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 10); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 30); + assert_eq!( + ParachainStaking::delegator_state(7) + .unwrap() + .delegations + .0 + .len(), + 1usize + ); + assert_eq!( + ParachainStaking::delegator_state(6) + .unwrap() + .delegations + .0 + .len(), + 3usize + ); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&6), + 70 + ); + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&7), + 90 + ); + }); +} + +#[test] +// The test verifies that the pending revoke request is removed by 2's exit so there is no dangling +// revoke request after 2 exits +fn execute_leave_candidate_removes_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (3, 2, 10), (4, 1, 10), (4, 2, 10)]) + .build() + .execute_with(|| { + // Verifies the revocation request is initially empty + assert!(!ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); + + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(2), + 2 + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(3), + 2 + )); + // Verifies the revocation request is present + assert!(ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); + + roll_to(16); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(2), + 2, + 2 + )); + // Verifies the revocation request is again empty + assert!(!ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); + }); +} + +#[test] +fn payouts_follow_delegation_changes() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) + .with_delegations(vec![ + (6, 1, 10), + (7, 1, 10), + (8, 2, 10), + (9, 2, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 2, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 130, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + // distribute total issuance to collator 1 and its delegators 6, 7, 19 + assert_events_eq!( + Event::CollatorChosen { + round: 4, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 4, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 4, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 4, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 23, + }, + Event::Rewarded { + account: 6, + rewards: 7, + }, + Event::Rewarded { + account: 7, + rewards: 7, + }, + Event::Rewarded { + account: 10, + rewards: 7, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(3, 1, 100); + set_author(4, 1, 100); + set_author(5, 1, 100); + set_author(6, 1, 100); + + roll_blocks(1); + // 1. ensure delegators are paid for 2 rounds after they leave + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), + Error::::DelegatorDNE + ); + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(6) + )); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 4, + delegator: 6, + scheduled_exit: 6, + }); + // fast forward to block in which delegator 6 exit executes + roll_to_round_begin(5); + assert_events_eq!( + Event::CollatorChosen { + round: 5, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 5, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 5, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 5, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 24, + }, + Event::Rewarded { + account: 6, + rewards: 8, + }, + Event::Rewarded { + account: 7, + rewards: 8, + }, + Event::Rewarded { + account: 10, + rewards: 8, + }, + ); + // keep paying 6 (note: inflation is in terms of total issuance so that's why 1 is 21) + roll_to_round_begin(6); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(6), + 6, + 10 + )); + assert_events_eq!( + Event::CollatorChosen { + round: 6, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 6, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 6, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 6, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 130, + }, + Event::DelegatorLeftCandidate { + delegator: 6, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 40, + }, + Event::DelegatorLeft { + delegator: 6, + unstaked_amount: 10, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 26, + }, + Event::Rewarded { + account: 6, + rewards: 8, + }, + Event::Rewarded { + account: 7, + rewards: 8, + }, + Event::Rewarded { + account: 10, + rewards: 8, + }, + ); + // 6 won't be paid for this round because they left already + set_author(7, 1, 100); + roll_to_round_begin(7); + // keep paying 6 + assert_events_eq!( + Event::CollatorChosen { + round: 7, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 7, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 7, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 7, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 31, + }, + Event::Rewarded { + account: 7, + rewards: 10, + }, + Event::Rewarded { + account: 10, + rewards: 10, + }, + ); + roll_to_round_begin(8); + assert_events_eq!( + Event::CollatorChosen { + round: 8, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 8, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 8, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 8, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 33, + }, + Event::Rewarded { + account: 7, + rewards: 11, + }, + Event::Rewarded { + account: 10, + rewards: 11, + }, + ); + set_author(8, 1, 100); + roll_to_round_begin(9); + // no more paying 6 + assert_events_eq!( + Event::CollatorChosen { + round: 9, + collator_account: 1, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 9, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 9, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 9, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 34, + }, + Event::Rewarded { + account: 7, + rewards: 11, + }, + Event::Rewarded { + account: 10, + rewards: 11, + }, + ); + roll_blocks(1); + set_author(9, 1, 100); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(8), + 1, + 10, + 10, + 10 + )); + assert_events_eq!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + + roll_to_round_begin(10); + // new delegation is not rewarded yet + assert_events_eq!( + Event::CollatorChosen { + round: 10, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 10, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 10, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 10, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 36, + }, + Event::Rewarded { + account: 7, + rewards: 12, + }, + Event::Rewarded { + account: 10, + rewards: 12, + }, + ); + set_author(10, 1, 100); + roll_to_round_begin(11); + // new delegation not rewarded yet + assert_events_eq!( + Event::CollatorChosen { + round: 11, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 11, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 11, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 11, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 38, + }, + Event::Rewarded { + account: 7, + rewards: 12, + }, + Event::Rewarded { + account: 10, + rewards: 12, + }, + ); + roll_to_round_begin(12); + // new delegation is rewarded for first time + // 2 rounds after joining (`RewardPaymentDelay` = 2) + assert_events_eq!( + Event::CollatorChosen { + round: 12, + collator_account: 1, + total_exposed_amount: 50, + }, + Event::CollatorChosen { + round: 12, + collator_account: 2, + total_exposed_amount: 40, + }, + Event::CollatorChosen { + round: 12, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 12, + collator_account: 4, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 34, + }, + Event::Rewarded { + account: 7, + rewards: 11, + }, + Event::Rewarded { + account: 10, + rewards: 11, + }, + Event::Rewarded { + account: 8, + rewards: 11, + }, + ); + }); +} + +#[test] +fn bottom_delegations_are_empty_when_top_delegations_not_full() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 10), (4, 10), (5, 10)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // no top delegators => no bottom delegators + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert!(top_delegations.delegations.is_empty()); + assert!(bottom_delegations.delegations.is_empty()); + // 1 delegator => 1 top delegator, 0 bottom delegators + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 10, + 10, + 10 + )); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 1usize); + assert!(bottom_delegations.delegations.is_empty()); + // 2 delegators => 2 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(3), + 1, + 10, + 10, + 10 + )); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 2usize); + assert!(bottom_delegations.delegations.is_empty()); + // 3 delegators => 3 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(4), + 1, + 10, + 10, + 10 + )); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 3usize); + assert!(bottom_delegations.delegations.is_empty()); + // 4 delegators => 4 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(5), + 1, + 10, + 10, + 10 + )); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 4usize); + assert!(bottom_delegations.delegations.is_empty()); + }); +} + +#[test] +fn candidate_pool_updates_when_total_counted_changes() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (3, 1, 11), + (4, 1, 12), + (5, 1, 13), + (6, 1, 14), + (7, 1, 15), + (8, 1, 16), + (9, 1, 17), + (10, 1, 18), + ]) + .build() + .execute_with(|| { + fn is_candidate_pool_bond(account: u64, bond: u128) { + let pool = ParachainStaking::candidate_pool(); + for candidate in pool.0 { + if candidate.owner == account { + assert_eq!( + candidate.amount, bond, + "Candidate Bond {:?} is Not Equal to Expected: {:?}", + candidate.amount, bond + ); + } + } + } + // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) + is_candidate_pool_bond(1, 86); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(3), + 1, + 8 + )); + // 3: 11 -> 19 => 3 is in top, bumps out 7 + // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) + is_candidate_pool_bond(1, 90); + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(4), + 1, + 8 + )); + // 4: 12 -> 20 => 4 is in top, bumps out 8 + // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) + is_candidate_pool_bond(1, 94); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(10), + 1, + 3 + )); + roll_to(30); + // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(10), + 10, + 1 + )); + // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) + is_candidate_pool_bond(1, 92); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(9), + 1, + 4 + )); + roll_to(40); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(9), + 9, + 1 + )); + // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) + is_candidate_pool_bond(1, 90); + }); +} + +#[test] +fn only_top_collators_are_counted() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (3, 1, 11), + (4, 1, 12), + (5, 1, 13), + (6, 1, 14), + (7, 1, 15), + (8, 1, 16), + (9, 1, 17), + (10, 1, 18), + ]) + .build() + .execute_with(|| { + // sanity check that 3-10 are delegators immediately + for i in 3..11 { + assert!(ParachainStaking::is_delegator(&i)); + } + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 86); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(3), + 1, + 8 + )); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 90); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(4), + 1, + 8 + )); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 4, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 94); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(5), + 1, + 8 + )); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 5, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 98); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(6), + 1, + 8 + )); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 6, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 102); + }); +} + +#[test] +fn delegation_events_convey_correct_position() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 11), (4, 1, 12), (5, 1, 13), (6, 1, 14)]) + .build() + .execute_with(|| { + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 11 + 12 + 13 + 14 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 70); + // Top delegations are full, new highest delegation is made + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(7), + 1, + 15, + 10, + 10 + )); + assert_events_emitted!(Event::Delegation { + delegator: 7, + locked_amount: 15, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 74 }, + auto_compound: Percent::zero(), + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 74); + // New delegation is added to the bottom + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(8), + 1, + 10, + 10, + 10 + )); + assert_events_emitted!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToBottom, + auto_compound: Percent::zero(), + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 74); + // 8 increases delegation to the top + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(8), + 1, + 3 + )); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 8, + candidate: 1, + amount: 3, + in_top: true, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 75); + // 3 increases delegation but stays in bottom + assert_ok!(ParachainStaking::delegator_bond_more( + RuntimeOrigin::signed(3), + 1, + 1 + )); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 1, + in_top: false, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 75); + // 6 decreases delegation but stays in top + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 2 + )); + assert_events_emitted!(Event::DelegationDecreaseScheduled { + delegator: 6, + candidate: 1, + amount_to_decrease: 2, + execute_round: 3, + }); + roll_to(30); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 2, + in_top: true, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ + assert_eq!(collator1_state.total_counted, 73); + // 6 decreases delegation and is bumped to bottom + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 1 + )); + assert_events_emitted!(Event::DelegationDecreaseScheduled { + delegator: 6, + candidate: 1, + amount_to_decrease: 1, + execute_round: 9, + }); + roll_to(40); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 1, + in_top: false, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 73); + }); +} + +#[test] +fn no_rewards_paid_until_after_reward_payment_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // payouts for round 1 + set_author(1, 1, 1); + set_author(1, 2, 1); + set_author(1, 2, 1); + set_author(1, 3, 1); + set_author(1, 3, 1); + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 3, + total_balance: 60, + }, + ); + + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { + round: 3, + collator_account: 1, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 3, + collator_account: 2, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 3, + collator_account: 3, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 3, + total_balance: 60, + }, + ); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 3, + rewards: 1, + }); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 1, + }); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 2, + rewards: 1, + }); + + // there should be no more payments in this round... + let num_blocks_rolled = roll_to_round_end(3); + assert_no_events!(); + assert_eq!(num_blocks_rolled, 1); + }); +} + +#[test] +fn deferred_payment_storage_items_are_cleaned_up() { + use crate::*; + + // this test sets up two collators, gives them points in round one, and focuses on the + // storage over the next several blocks to show that it is properly cleaned up + + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + set_author(1, 1, 1); + set_author(1, 2, 1); + + // reflects genesis? + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + roll_to_round_begin(2); + assert_events_eq!( + Event::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 2, + collator_account: 2, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + // we should have AtStake snapshots as soon as we start a round... + assert!(>::contains_key(2, 1)); + assert!(>::contains_key(2, 2)); + // ...and it should persist until the round is fully paid out + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + assert!( + !>::contains_key(1), + "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" + ); + assert!( + >::contains_key(1), + "Points should be populated during current round" + ); + assert!( + >::contains_key(1), + "Staked should be populated when round changes" + ); + + assert!( + !>::contains_key(2), + "Points should not be populated until author noted" + ); + assert!( + >::contains_key(2), + "Staked should be populated when round changes" + ); + + // first payout occurs in round 3 + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { + round: 3, + collator_account: 1, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 3, + collator_account: 2, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 1, + },); + + // payouts should exist for past rounds that haven't been paid out yet.. + assert!(>::contains_key(3, 1)); + assert!(>::contains_key(3, 2)); + assert!(>::contains_key(2, 1)); + assert!(>::contains_key(2, 2)); + + assert!( + >::contains_key(1), + "DelayedPayouts should be populated after RewardPaymentDelay" + ); + assert!(>::contains_key(1)); + assert!( + !>::contains_key(1), + "Staked should be cleaned up after round change" + ); + + assert!(!>::contains_key(2)); + assert!( + !>::contains_key(2), + "We never rewarded points for round 2" + ); + assert!(>::contains_key(2)); + + assert!(!>::contains_key(3)); + assert!( + !>::contains_key(3), + "We never awarded points for round 3" + ); + assert!(>::contains_key(3)); + + // collator 1 has been paid in this last block and associated storage cleaned up + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 1)); + + // but collator 2 hasn't been paid + assert!(>::contains_key(1, 2)); + assert!(>::contains_key(1, 2)); + + // second payout occurs in next block + roll_blocks(1); + assert_events_eq!(Event::Rewarded { + account: 2, + rewards: 1, + },); + + roll_to_round_begin(4); + assert_events_eq!( + Event::CollatorChosen { + round: 4, + collator_account: 1, + total_exposed_amount: 20, + }, + Event::CollatorChosen { + round: 4, + collator_account: 2, + total_exposed_amount: 20, + }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + // collators have both been paid and storage fully cleaned up for round 1 + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); // points should be cleaned up + assert!(!>::contains_key(1)); + + roll_to_round_end(4); + + // no more events expected + assert_no_events!(); + }); +} + +#[test] +fn deferred_payment_and_at_stake_storage_items_cleaned_up_for_candidates_not_producing_blocks() { + use crate::*; + + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) + .build() + .execute_with(|| { + // candidate 3 will not produce blocks + set_author(1, 1, 1); + set_author(1, 2, 1); + + // reflects genesis? + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + roll_to_round_begin(2); + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + assert!(>::contains_key(1, 3)); + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(>::contains_key(1)); + assert!(>::contains_key(1)); + roll_to_round_begin(3); + assert!(>::contains_key(1)); + + // all storage items must be cleaned up + roll_to_round_begin(4); + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); + }); +} + +#[test] +fn deferred_payment_steady_state_event_flow() { + use frame_support::traits::{Currency, ExistenceRequirement, WithdrawReasons}; + + // this test "flows" through a number of rounds, asserting that certain things do/don't happen + // once the staking pallet is in a "steady state" (specifically, once we are past the first few + // rounds to clear RewardPaymentDelay) + + ExtBuilder::default() + .with_balances(vec![ + // collators + (1, 200), + (2, 200), + (3, 200), + (4, 200), + // delegators + (11, 200), + (22, 200), + (33, 200), + (44, 200), + // burn account, see `reset_issuance()` + (111, 1000), + ]) + .with_candidates(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) + .with_delegations(vec![ + // delegator 11 delegates 100 to 1 and 2 + (11, 1, 100), + (11, 2, 100), + // delegator 22 delegates 100 to 2 and 3 + (22, 2, 100), + (22, 3, 100), + // delegator 33 delegates 100 to 3 and 4 + (33, 3, 100), + (33, 4, 100), + // delegator 44 delegates 100 to 4 and 1 + (44, 4, 100), + (44, 1, 100), + ]) + .build() + .execute_with(|| { + // convenience to set the round points consistently + let set_round_points = |round: BlockNumber| { + set_author(round as BlockNumber, 1, 1); + set_author(round as BlockNumber, 2, 1); + set_author(round as BlockNumber, 3, 1); + set_author(round as BlockNumber, 4, 1); + }; + + // grab initial issuance -- we will reset it before round issuance is calculated so that + // it is consistent every round + let initial_issuance = Balances::total_issuance(); + let reset_issuance = || { + let new_issuance = Balances::total_issuance(); + let diff = new_issuance - initial_issuance; + let burned = Balances::burn(diff); + Balances::settle( + &111, + burned, + WithdrawReasons::FEE, + ExistenceRequirement::AllowDeath, + ) + .expect("Account can absorb burn"); + }; + + // fn to roll through the first RewardPaymentDelay rounds. returns new round index + let roll_through_initial_rounds = |mut round: BlockNumber| -> BlockNumber { + while round < crate::mock::RewardPaymentDelay::get() + 1 { + set_round_points(round); + + roll_to_round_end(round); + round += 1; + } + + reset_issuance(); + + round + }; + + // roll through a "steady state" round and make all of our assertions + // returns new round index + let roll_through_steady_state_round = |round: BlockNumber| -> BlockNumber { + let num_rounds_rolled = roll_to_round_begin(round); + assert!( + num_rounds_rolled <= 1, + "expected to be at round begin already" + ); + + assert_events_eq!( + Event::CollatorChosen { + round: round as u32, + collator_account: 1, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 2, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 3, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 4, + total_exposed_amount: 400, + }, + Event::NewRound { + starting_block: (round - 1) * 5, + round: round as u32, + selected_collators_number: 4, + total_balance: 1600, + }, + ); + + set_round_points(round); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 3, + rewards: 19, + }, + Event::Rewarded { + account: 22, + rewards: 6, + }, + Event::Rewarded { + account: 33, + rewards: 6, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 4, + rewards: 19, + }, + Event::Rewarded { + account: 33, + rewards: 6, + }, + Event::Rewarded { + account: 44, + rewards: 6, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 19, + }, + Event::Rewarded { + account: 11, + rewards: 6, + }, + Event::Rewarded { + account: 44, + rewards: 6, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 2, + rewards: 19, + }, + Event::Rewarded { + account: 11, + rewards: 6, + }, + Event::Rewarded { + account: 22, + rewards: 6, + }, + ); + + roll_blocks(1); + // Since we defer first deferred staking payout, this test have the maximum amout of + // supported collators. This eman that the next round is trigerred one block after + // the last reward. + //assert_no_events!(); + + let num_rounds_rolled = roll_to_round_end(round); + assert_eq!(num_rounds_rolled, 0, "expected to be at round end already"); + + reset_issuance(); + + round + 1 + }; + + let mut round = 1; + round = roll_through_initial_rounds(round); // we should be at RewardPaymentDelay + for _ in 1..2 { + round = roll_through_steady_state_round(round); + } + }); +} + +#[test] +fn delegation_kicked_from_bottom_removes_pending_request() { + ExtBuilder::default() + .with_balances(vec![ + (1, 30), + (2, 29), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 30), + ]) + .with_candidates(vec![(1, 30), (11, 30)]) + .with_delegations(vec![ + (2, 1, 19), + (2, 11, 10), // second delegation so not left after first is kicked + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + (7, 1, 20), + (8, 1, 20), + (9, 1, 20), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + // 10 delegates to full 1 => kicks lowest delegation (2, 19) + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(10), + 1, + 20, + 8, + 0 + )); + // check the event + assert_events_emitted!(Event::DelegationKicked { + delegator: 2, + candidate: 1, + unstaked_amount: 19, + }); + // ensure request DNE + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + }); +} + +#[test] +fn no_selected_candidates_defaults_to_last_round_collators() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) + .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) + .build() + .execute_with(|| { + roll_to_round_begin(1); + // schedule to leave + for i in 1..6 { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + 5 + )); + } + let old_round = ParachainStaking::round().current; + let old_selected_candidates = ParachainStaking::selected_candidates(); + let mut old_at_stake_snapshots = Vec::new(); + for account in old_selected_candidates.clone() { + old_at_stake_snapshots.push(>::get(old_round, account)); + } + roll_to_round_begin(3); + // execute leave + for i in 1..6 { + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(i), + i, + 0, + )); + } + // next round + roll_to_round_begin(4); + let new_round = ParachainStaking::round().current; + // check AtStake matches previous + let new_selected_candidates = ParachainStaking::selected_candidates(); + assert_eq!(old_selected_candidates, new_selected_candidates); + let mut index = 0usize; + for account in new_selected_candidates { + assert_eq!( + old_at_stake_snapshots[index], + >::get(new_round, account) + ); + index += 1usize; + } + }); +} + +#[test] +fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_for_future() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator.total_counted, + "collator's total was reduced unexpectedly" + ); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 4, + }, + Event::Rewarded { + account: 2, + rewards: 1, + }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 5, + },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator.total_counted, + "collator's total was reduced unexpectedly" + ); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 5, + },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 4, + }, + Event::Rewarded { + account: 2, + rewards: 1, + }, + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() +{ + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + execute_round: 3, + delegator: 2, + candidate: 1, + amount_to_decrease: 10, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!( + 40, collator.total_counted, + "collator's total was reduced unexpectedly" + ); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 3, + }, + Event::Rewarded { + account: 2, + rewards: 2, + }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 4, + }, + Event::Rewarded { + account: 2, + rewards: 1, + }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + execute_round: 3, + delegator: 2, + candidate: 1, + amount_to_decrease: 10, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!( + 40, collator.total_counted, + "collator's total was reduced unexpectedly" + ); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_delegation_request( + RuntimeOrigin::signed(2), + 1 + )); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 4, + }, + Event::Rewarded { + account: 2, + rewards: 1, + }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 40, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 3, + }, + Event::Rewarded { + account: 2, + rewards: 2, + }, + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_for_future() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2), + )); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator.total_counted, + "collator's total was reduced unexpectedly" + ); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 4, + }, + Event::Rewarded { + account: 2, + rewards: 1, + }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 5, + },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator.total_counted, + "collator's total was reduced unexpectedly" + ); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_leave_delegators( + RuntimeOrigin::signed(2) + )); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { + account: 1, + rewards: 5, + },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 4, + }, + Event::Rewarded { + account: 2, + rewards: 1, + }, + ); + }); +} + +#[test] +fn test_delegation_request_exists_returns_false_when_nothing_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_request_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_exists_returns_true_when_decrease_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert!(ParachainStaking::delegation_request_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_exists_returns_true_when_revoke_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], + ); + assert!(ParachainStaking::delegation_request_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_revoke_exists_returns_false_when_nothing_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], + ); + assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3, 4] // 4 does not exist, but is OK for idempotency + ) + ); + + assert!(!>::contains_key(2)); + assert!(!>::contains_key(3)); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2] + ) + ); + + assert!(!>::contains_key(2)); + assert!(>::contains_key(3)); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + vec![ScheduledRequest { + delegator: 10, + when_executable: 1, + action: DelegationAction::Revoke(10), + }], + ); + + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3] + ), + >::CandidateNotLeaving, + ); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 1, + Vec::>::new(), + ); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![1] + ), + >::CandidateNotLeaving, + ); + }); +} + +#[test] +fn locking_zero_amount_is_ignored() { + use frame_support::traits::{LockableCurrency, WithdrawReasons}; + + // this test demonstrates the behavior of pallet Balance's `LockableCurrency` implementation of + // `set_locks()` when an amount of 0 is provided: it is a no-op + + ExtBuilder::default() + .with_balances(vec![(1, 100)]) + .build() + .execute_with(|| { + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), None); + + Balances::set_lock(DELEGATOR_LOCK_ID, &1, 1, WithdrawReasons::all()); + assert_eq!( + crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), + Some(1) + ); + + Balances::set_lock(DELEGATOR_LOCK_ID, &1, 0, WithdrawReasons::all()); + // Note that we tried to call `set_lock(0)` and it ignored it, we still have our lock + assert_eq!( + crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), + Some(1) + ); + }); +} + +#[test] +fn revoke_last_removes_lock() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100)]) + .with_candidates(vec![(1, 25), (2, 25)]) + .with_delegations(vec![(3, 1, 30), (3, 2, 25)]) + .build() + .execute_with(|| { + assert_eq!( + crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), + Some(55) + ); + + // schedule and remove one... + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(3), + 1 + )); + roll_to_round_begin(3); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 1 + )); + assert_eq!( + crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), + Some(25) + ); + + // schedule and remove the other... + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(3), + 2 + )); + roll_to_round_begin(5); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 2 + )); + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_as_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert!(>::get(1) + .iter() + .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_)))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); + + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_can_cancel_leave_delegators_as_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_ok!(ParachainStaking::cancel_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_events_eq!(Event::DelegatorExitCancelled { delegator: 2 }); + + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_can_execute_leave_delegators_as_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeft { + delegator: 2, + unstaked_amount: 10 + }); + + let state = >::get(2); + assert!(state.is_none()); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_cannot_execute_leave_delegators_early_no_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorCannotLeaveYet + ); + }); +} + +#[test] +fn test_set_auto_compound_fails_if_invalid_delegation_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; // is however, 1 + + assert_noop!( + ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowDelegationCountToAutoCompound, + ); + }); +} + +#[test] +fn test_set_auto_compound_fails_if_invalid_candidate_auto_compounding_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new(vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(10), + }]) + .set_storage(&1); + let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 + let delegation_hint = 1; + + assert_noop!( + ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + ); + }); +} + +#[test] +fn test_set_auto_compound_inserts_if_not_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(50), + }], + ParachainStaking::auto_compounding_delegations(&1), + ); + }); +} + +#[test] +fn test_set_auto_compound_updates_if_existing() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new(vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(10), + }]) + .set_storage(&1); + + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(50), + }], + ParachainStaking::auto_compounding_delegations(&1), + ); + }); +} + +#[test] +fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new(vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(10), + }]) + .set_storage(&1); + + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::zero(), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::zero(), + }); + assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); + }); +} + +#[test] +fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delegation_revoke() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was erroneously removed" + ); + }); +} + +#[test] +fn test_execute_leave_delegators_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 2, + )); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); +} + +#[allow(deprecated)] +#[test] +fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(2), + 2, + 2, + )); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); +} + +#[test] +fn test_execute_leave_candidates_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(1), + 2 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(1), + 1, + 1, + )); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was erroneously removed" + ); + }); +} + +#[test] +fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![ + (1, 30), + (2, 29), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 30), + ]) + .with_candidates(vec![(1, 30), (11, 30)]) + .with_delegations(vec![ + (2, 11, 10), // extra delegation to avoid leaving the delegator set + (2, 1, 19), + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + (7, 1, 20), + (8, 1, 20), + (9, 1, 20), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + + // kicks lowest delegation (2, 19) + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(10), + 1, + 20, + 8, + 0 + )); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); +} + +#[test] +fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 200), (3, 200)]) + .with_candidates(vec![(1, 100)]) + .with_delegations(vec![(2, 1, 200), (3, 1, 200)]) + .build() + .execute_with(|| { + (2..=5).for_each(|round| set_author(round, 1, 1)); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(3), + 1, + Percent::from_percent(50), + 1, + 1, + )); + roll_to_round_begin(3); + + // schedule revoke for delegator 2; no rewards should be compounded + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + roll_to_round_begin(4); + + assert_events_eq!( + Event::CollatorChosen { + round: 4, + collator_account: 1, + total_exposed_amount: 500, + }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 500, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 9, + }, + // no compound since revoke request exists + Event::Rewarded { + account: 2, + rewards: 8, + }, + // 50% + Event::Rewarded { + account: 3, + rewards: 8, + }, + Event::Compounded { + candidate: 1, + delegator: 3, + amount: 4, + }, + ); + }); +} + +#[test] +fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 200), (3, 200), (4, 200), (5, 200)]) + .with_candidates(vec![(1, 100)]) + .with_delegations(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) + .build() + .execute_with(|| { + (2..=6).for_each(|round| set_author(round, 1, 1)); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(0), + 0, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(3), + 1, + Percent::from_percent(50), + 1, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(4), + 1, + Percent::from_percent(100), + 2, + 1, + )); + roll_to_round_begin(4); + + assert_events_eq!( + Event::CollatorChosen { + round: 4, + collator_account: 1, + total_exposed_amount: 900, + }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 900, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { + account: 1, + rewards: 13, + }, + // 0% + Event::Rewarded { + account: 2, + rewards: 8, + }, + // 50% + Event::Rewarded { + account: 3, + rewards: 8, + }, + Event::Compounded { + candidate: 1, + delegator: 3, + amount: 4, + }, + // 100% + Event::Rewarded { + account: 4, + rewards: 8, + }, + Event::Compounded { + candidate: 1, + delegator: 4, + amount: 8, + }, + // no-config + Event::Rewarded { + account: 5, + rewards: 8, + }, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_fails_if_invalid_delegation_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 3, 10)]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 0; + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; // is however, 1 + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowDelegationCountToDelegate, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_fails_if_invalid_candidate_delegation_count_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(3, 1, 10)]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 0; // is however, 1 + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateDelegationCountToDelegate, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_delegations_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(10))]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 1; + let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 + let delegation_hint = 0; + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_sets_auto_compound_config() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0, + )); + assert_events_emitted!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(50), + }], + ParachainStaking::auto_compounding_delegations(&1), + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::zero(), + 0, + 0, + 0, + )); + assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }); + }); +} + +#[test] +fn test_delegate_with_auto_compound_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::get_delegator_stakable_free_balance(&2), + 10 + ); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0, + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); +} + +#[test] +fn test_delegate_with_auto_compound_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_none()); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + )); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); + assert_eq!(delegator_state.total(), 10); + assert_eq!(delegator_state.delegations.0[0].owner, 1); + assert_eq!(delegator_state.delegations.0[0].amount, 10); + }); +} + +#[test] +fn test_delegate_with_auto_compound_updates_collator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); + assert!(top_delegations.delegations.is_empty()); + assert!(top_delegations.total.is_zero()); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + )); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); + assert_eq!(candidate_state.total_counted, 40); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); + assert_eq!(top_delegations.delegations[0].owner, 2); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates( + RuntimeOrigin::signed(1), + 20, + 0 + )); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 20, + Percent::from_percent(50), + 0, + 0, + 0 + )); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_delegate_to_other_if_revoking() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation( + RuntimeOrigin::signed(2), + 1 + )); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 4, + 10, + Percent::from_percent(50), + 0, + 0, + 2 + )); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_if_less_than_or_equal_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(11), + 1, + 10, + Percent::from_percent(50), + 8, + 0, + 0 + ), + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 11), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(11), + 1, + 11, + Percent::from_percent(50), + 8, + 0, + 0 + )); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); + assert_events_emitted!(Event::DelegatorLeft { + delegator: 10, + unstaked_amount: 10 + }); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_still_delegate_to_other_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators( + RuntimeOrigin::signed(2) + )); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 3, + 10, + Percent::from_percent(50), + 0, + 0, + 1 + ),); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_if_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + ), + Error::::CandidateExists + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_if_already_delegated() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 1, + 1 + ), + Error::::AlreadyDelegatedCandidate + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_more_than_max_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 6, + 10, + Percent::from_percent(50), + 0, + 0, + 4 + ), + Error::::ExceedMaxDelegationsPerDelegator, + ); + }); +} + +#[test] +fn test_delegate_skips_auto_compound_storage_but_emits_event_for_zero_auto_compound() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(50))]) + .build() + .execute_with(|| { + // We already have an auto-compounding delegation from 3 -> 1, so the hint validation + // would cause a failure if the auto-compounding isn't skipped properly. + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(2), + 1, + 10, + 1, + 0, + )); + assert_eq!(1, ParachainStaking::auto_compounding_delegations(&1).len(),); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + }); +} + +#[test] +fn test_on_initialize_weights() { + use crate::mock::System; + use crate::weights::{SubstrateWeight as PalletWeights, WeightInfo}; + use crate::*; + use frame_support::{pallet_prelude::*, weights::constants::RocksDbWeight}; + + // generate balance, candidate, and delegation vecs to "fill" out delegations + let mut balances = Vec::new(); + let mut candidates = Vec::new(); + let mut delegations = Vec::new(); + + for collator in 1..30 { + balances.push((collator, 100)); + candidates.push((collator, 10)); + let starting_delegator = collator * 1000; + for delegator in starting_delegator..starting_delegator + 300 { + balances.push((delegator, 100)); + delegations.push((delegator, collator, 10)); + } + } + + ExtBuilder::default() + .with_balances(balances) + .with_candidates(candidates) + .with_delegations(delegations) + .build() + .execute_with(|| { + let weight = ParachainStaking::on_initialize(1); + + // TODO: build this with proper db reads/writes + assert_eq!(Weight::from_ref_time(285_890_000), weight); + + // roll to the end of the round, then run on_init again, we should see round change... + roll_to_round_end(3); + set_author(2, 1, 100); // must set some points for prepare_staking_payouts + let block = System::block_number() + 1; + let weight = ParachainStaking::on_initialize(block); + + // the total on_init weight during our round change. this number is taken from running + // the fn with a given weights.rs benchmark, so will need to be updated as benchmarks + // change. + // + // following this assertion, we add individual weights together to show that we can + // derive this number independently. + let expected_on_init = 2_537_230_483; + assert_eq!(Weight::from_ref_time(expected_on_init), weight); + + // assemble weight manually to ensure it is well understood + let mut expected_weight = 0u64; + expected_weight += PalletWeights::::base_on_initialize().ref_time(); + expected_weight += PalletWeights::::prepare_staking_payouts().ref_time(); + + // TODO: this should be the same as >. I believe this relates to + // genesis building + let num_avg_delegations = 8; + expected_weight += PalletWeights::::select_top_candidates( + >::get(), + num_avg_delegations, + ) + .ref_time(); + // Round and Staked writes, done in on-round-change code block inside on_initialize() + expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); + // more reads/writes manually accounted for for on_finalize + expected_weight += RocksDbWeight::get().reads_writes(3, 2).ref_time(); + + assert_eq!(Weight::from_ref_time(expected_weight), weight); + assert_eq!(expected_on_init, expected_weight); // magic number == independent accounting + }); +} diff --git a/external/pallets/parachain-staking/src/traits.rs b/external/pallets/parachain-staking/src/traits.rs new file mode 100644 index 000000000..2b30b04cc --- /dev/null +++ b/external/pallets/parachain-staking/src/traits.rs @@ -0,0 +1,66 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! traits for parachain-staking + +use frame_support::pallet_prelude::Weight; + +pub trait OnCollatorPayout { + fn on_collator_payout( + for_round: crate::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight; +} +impl OnCollatorPayout for () { + fn on_collator_payout( + _for_round: crate::RoundIndex, + _collator_id: AccountId, + _amount: Balance, + ) -> Weight { + Weight::zero() + } +} + +pub trait OnNewRound { + fn on_new_round(round_index: crate::RoundIndex) -> Weight; +} +impl OnNewRound for () { + fn on_new_round(_round_index: crate::RoundIndex) -> Weight { + Weight::zero() + } +} + +/// Defines the behavior to payout the collator's reward. +pub trait PayoutCollatorReward { + fn payout_collator_reward( + round_index: crate::RoundIndex, + collator_id: Runtime::AccountId, + amount: crate::BalanceOf, + ) -> Weight; +} + +/// Defines the default behavior for paying out the collator's reward. The amount is directly +/// deposited into the collator's account. +impl PayoutCollatorReward for () { + fn payout_collator_reward( + for_round: crate::RoundIndex, + collator_id: Runtime::AccountId, + amount: crate::BalanceOf, + ) -> Weight { + crate::Pallet::::mint_collator_reward(for_round, collator_id, amount) + } +} diff --git a/external/pallets/parachain-staking/src/types.rs b/external/pallets/parachain-staking/src/types.rs new file mode 100644 index 000000000..dbb673e70 --- /dev/null +++ b/external/pallets/parachain-staking/src/types.rs @@ -0,0 +1,1757 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Types for parachain-staking + +use crate::{ + auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, + CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, + Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, +}; +use frame_support::{ + pallet_prelude::*, + traits::{tokens::WithdrawReasons, LockableCurrency}, +}; +use parity_scale_codec::{Decode, Encode}; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Saturating, Zero}, + Perbill, Percent, RuntimeDebug, +}; +use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; + +pub struct CountedDelegations { + pub uncounted_stake: BalanceOf, + pub rewardable_delegations: Vec>>, +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Bond { + pub owner: AccountId, + pub amount: Balance, +} + +impl Default for Bond { + fn default() -> Bond { + Bond { + owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + amount: B::default(), + } + } +} + +impl Bond { + pub fn from_owner(owner: A) -> Self { + Bond { + owner, + amount: B::default(), + } + } +} + +impl Eq for Bond {} + +impl Ord for Bond { + fn cmp(&self, other: &Self) -> Ordering { + self.owner.cmp(&other.owner) + } +} + +impl PartialOrd for Bond { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for Bond { + fn eq(&self, other: &Self) -> bool { + self.owner == other.owner + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// The activity status of the collator +pub enum CollatorStatus { + /// Committed to be online and producing valid blocks (not equivocating) + Active, + /// Temporarily inactive and excused for inactivity + Idle, + /// Bonded until the inner round + Leaving(RoundIndex), +} + +impl Default for CollatorStatus { + fn default() -> CollatorStatus { + CollatorStatus::Active + } +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct BondWithAutoCompound { + pub owner: AccountId, + pub amount: Balance, + pub auto_compound: Percent, +} + +impl Default for BondWithAutoCompound { + fn default() -> BondWithAutoCompound { + BondWithAutoCompound { + owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + amount: B::default(), + auto_compound: Percent::zero(), + } + } +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// Snapshot of collator state at the start of the round for which they are selected +pub struct CollatorSnapshot { + /// The total value locked by the collator. + pub bond: Balance, + + /// The rewardable delegations. This list is a subset of total delegators, where certain + /// delegators are adjusted based on their scheduled + /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. + pub delegations: Vec>, + + /// The total counted value locked for the collator, including the self bond + total staked by + /// top delegators. + pub total: Balance, +} + +impl PartialEq for CollatorSnapshot { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.bond == other.bond && self.total == other.total; + if !must_be_true { + return false; + } + for ( + BondWithAutoCompound { + owner: o1, + amount: a1, + auto_compound: c1, + }, + BondWithAutoCompound { + owner: o2, + amount: a2, + auto_compound: c2, + }, + ) in self.delegations.iter().zip(other.delegations.iter()) + { + if o1 != o2 || a1 != a2 || c1 != c2 { + return false; + } + } + true + } +} + +impl Default for CollatorSnapshot { + fn default() -> CollatorSnapshot { + CollatorSnapshot { + bond: B::default(), + delegations: Vec::new(), + total: B::default(), + } + } +} + +#[derive(Default, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Info needed to make delayed payments to stakers after round end +pub struct DelayedPayout { + /// Total round reward (result of compute_issuance() at round end) + pub round_issuance: Balance, + /// The total inflation paid this round to stakers (e.g. less parachain bond fund) + pub total_staking_reward: Balance, + /// Snapshot of collator commission rate at the end of the round + pub collator_commission: Perbill, +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// DEPRECATED +/// Collator state with commission fee, bonded stake, and delegations +pub struct Collator2 { + /// The account of this collator + pub id: AccountId, + /// This collator's self stake. + pub bond: Balance, + /// Set of all nominator AccountIds (to prevent >1 nomination per AccountId) + pub nominators: OrderedSet, + /// Top T::MaxDelegatorsPerCollator::get() nominators, ordered greatest to least + pub top_nominators: Vec>, + /// Bottom nominators (unbounded), ordered least to greatest + pub bottom_nominators: Vec>, + /// Sum of top delegations + self.bond + pub total_counted: Balance, + /// Sum of all delegations + self.bond = (total_counted + uncounted) + pub total_backing: Balance, + /// Current status of the collator + pub state: CollatorStatus, +} + +impl From> for CollatorCandidate { + fn from(other: Collator2) -> CollatorCandidate { + CollatorCandidate { + id: other.id, + bond: other.bond, + delegators: other.nominators, + top_delegations: other.top_nominators, + bottom_delegations: other.bottom_nominators, + total_counted: other.total_counted, + total_backing: other.total_backing, + request: None, + state: other.state, + } + } +} + +#[derive(PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Request scheduled to change the collator candidate self-bond +pub struct CandidateBondLessRequest { + pub amount: Balance, + pub when_executable: RoundIndex, +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// DEPRECATED, replaced by `CandidateMetadata` and two storage instances of `Delegations` +/// Collator candidate state with self bond + delegations +pub struct CollatorCandidate { + /// The account of this collator + pub id: AccountId, + /// This collator's self stake. + pub bond: Balance, + /// Set of all delegator AccountIds (to prevent >1 delegation per AccountId) + pub delegators: OrderedSet, + /// Top T::MaxDelegatorsPerCollator::get() delegations, ordered greatest to least + pub top_delegations: Vec>, + /// Bottom delegations (unbounded), ordered least to greatest + pub bottom_delegations: Vec>, + /// Sum of top delegations + self.bond + pub total_counted: Balance, + /// Sum of all delegations + self.bond = (total_counted + uncounted) + pub total_backing: Balance, + /// Maximum 1 pending request to decrease candidate self bond at any given time + pub request: Option>, + /// Current status of the collator + pub state: CollatorStatus, +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Type for top and bottom delegation storage item +pub struct Delegations { + pub delegations: Vec>, + pub total: Balance, +} + +impl Default for Delegations { + fn default() -> Delegations { + Delegations { + delegations: Vec::new(), + total: B::default(), + } + } +} + +impl + Delegations +{ + pub fn sort_greatest_to_least(&mut self) { + self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); + } + /// Insert sorted greatest to least and increase .total accordingly + /// Insertion respects first come first serve so new delegations are pushed after existing + /// delegations if the amount is the same + pub fn insert_sorted_greatest_to_least(&mut self, delegation: Bond) { + self.total = self.total.saturating_add(delegation.amount); + // if delegations nonempty && last_element == delegation.amount => push input and return + if !self.delegations.is_empty() { + // if last_element == delegation.amount => push the delegation and return early + if self.delegations[self.delegations.len() - 1].amount == delegation.amount { + self.delegations.push(delegation); + // early return + return; + } + } + // else binary search insertion + match self + .delegations + .binary_search_by(|x| delegation.amount.cmp(&x.amount)) + { + // sorted insertion on sorted vec + // enforces first come first serve for equal bond amounts + Ok(i) => { + let mut new_index = i + 1; + while new_index <= (self.delegations.len() - 1) { + if self.delegations[new_index].amount == delegation.amount { + new_index = new_index.saturating_add(1); + } else { + self.delegations.insert(new_index, delegation); + return; + } + } + self.delegations.push(delegation) + } + Err(i) => self.delegations.insert(i, delegation), + } + } + /// Return the capacity status for top delegations + pub fn top_capacity(&self) -> CapacityStatus { + match &self.delegations { + x if x.len() as u32 >= T::MaxTopDelegationsPerCandidate::get() => CapacityStatus::Full, + x if x.is_empty() => CapacityStatus::Empty, + _ => CapacityStatus::Partial, + } + } + /// Return the capacity status for bottom delegations + pub fn bottom_capacity(&self) -> CapacityStatus { + match &self.delegations { + x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => { + CapacityStatus::Full + } + x if x.is_empty() => CapacityStatus::Empty, + _ => CapacityStatus::Partial, + } + } + /// Return last delegation amount without popping the delegation + pub fn lowest_delegation_amount(&self) -> Balance { + self.delegations + .last() + .map(|x| x.amount) + .unwrap_or(Balance::zero()) + } + /// Return highest delegation amount + pub fn highest_delegation_amount(&self) -> Balance { + self.delegations + .first() + .map(|x| x.amount) + .unwrap_or(Balance::zero()) + } +} + +#[derive(PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Capacity status for top or bottom delegations +pub enum CapacityStatus { + /// Reached capacity + Full, + /// Empty aka contains no delegations + Empty, + /// Partially full (nonempty and not full) + Partial, +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// All candidate info except the top and bottom delegations +pub struct CandidateMetadata { + /// This candidate's self bond amount + pub bond: Balance, + /// Total number of delegations to this candidate + pub delegation_count: u32, + /// Self bond + sum of top delegations + pub total_counted: Balance, + /// The smallest top delegation amount + pub lowest_top_delegation_amount: Balance, + /// The highest bottom delegation amount + pub highest_bottom_delegation_amount: Balance, + /// The smallest bottom delegation amount + pub lowest_bottom_delegation_amount: Balance, + /// Capacity status for top delegations + pub top_capacity: CapacityStatus, + /// Capacity status for bottom delegations + pub bottom_capacity: CapacityStatus, + /// Maximum 1 pending request to decrease candidate self bond at any given time + pub request: Option>, + /// Current status of the collator + pub status: CollatorStatus, +} + +impl< + Balance: Copy + + Zero + + PartialOrd + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + sp_std::fmt::Debug + + Saturating, + > CandidateMetadata +{ + pub fn new(bond: Balance) -> Self { + CandidateMetadata { + bond, + delegation_count: 0u32, + total_counted: bond, + lowest_top_delegation_amount: Zero::zero(), + highest_bottom_delegation_amount: Zero::zero(), + lowest_bottom_delegation_amount: Zero::zero(), + top_capacity: CapacityStatus::Empty, + bottom_capacity: CapacityStatus::Empty, + request: None, + status: CollatorStatus::Active, + } + } + pub fn is_active(&self) -> bool { + matches!(self.status, CollatorStatus::Active) + } + pub fn is_leaving(&self) -> bool { + matches!(self.status, CollatorStatus::Leaving(_)) + } + pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { + ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); + let now = >::get().current; + let when = now + T::LeaveCandidatesDelay::get(); + self.status = CollatorStatus::Leaving(when); + Ok((now, when)) + } + pub fn can_leave(&self) -> DispatchResult { + if let CollatorStatus::Leaving(when) = self.status { + ensure!( + >::get().current >= when, + Error::::CandidateCannotLeaveYet + ); + Ok(()) + } else { + Err(Error::::CandidateNotLeaving.into()) + } + } + pub fn go_offline(&mut self) { + self.status = CollatorStatus::Idle; + } + pub fn go_online(&mut self) { + self.status = CollatorStatus::Active; + } + pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult + where + BalanceOf: From, + { + ensure!( + >::get_collator_stakable_free_balance(&who) >= more.into(), + Error::::InsufficientBalance + ); + let new_total = >::get().saturating_add(more.into()); + >::put(new_total); + self.bond = self.bond.saturating_add(more); + T::Currency::set_lock( + COLLATOR_LOCK_ID, + &who.clone(), + self.bond.into(), + WithdrawReasons::all(), + ); + self.total_counted = self.total_counted.saturating_add(more); + >::deposit_event(Event::CandidateBondedMore { + candidate: who.clone(), + amount: more.into(), + new_total_bond: self.bond.into(), + }); + Ok(()) + } + /// Schedule executable decrease of collator candidate self bond + /// Returns the round at which the collator can execute the pending request + pub fn schedule_bond_less( + &mut self, + less: Balance, + ) -> Result + where + BalanceOf: Into, + { + // ensure no pending request + ensure!( + self.request.is_none(), + Error::::PendingCandidateRequestAlreadyExists + ); + // ensure bond above min after decrease + ensure!(self.bond > less, Error::::CandidateBondBelowMin); + ensure!( + self.bond - less >= T::MinCandidateStk::get().into(), + Error::::CandidateBondBelowMin + ); + let when_executable = >::get().current + T::CandidateBondLessDelay::get(); + self.request = Some(CandidateBondLessRequest { + amount: less, + when_executable, + }); + Ok(when_executable) + } + /// Execute pending request to decrease the collator self bond + /// Returns the event to be emitted + pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult + where + BalanceOf: From, + { + let request = self + .request + .ok_or(Error::::PendingCandidateRequestsDNE)?; + ensure!( + request.when_executable <= >::get().current, + Error::::PendingCandidateRequestNotDueYet + ); + let new_total_staked = >::get().saturating_sub(request.amount.into()); + >::put(new_total_staked); + // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond + // (assumptions enforced by `schedule_bond_less`; if storage corrupts, must re-verify) + self.bond = self.bond.saturating_sub(request.amount); + T::Currency::set_lock( + COLLATOR_LOCK_ID, + &who.clone(), + self.bond.into(), + WithdrawReasons::all(), + ); + self.total_counted = self.total_counted.saturating_sub(request.amount); + let event = Event::CandidateBondedLess { + candidate: who.clone().into(), + amount: request.amount.into(), + new_bond: self.bond.into(), + }; + // reset s.t. no pending request + self.request = None; + // update candidate pool value because it must change if self bond changes + if self.is_active() { + Pallet::::update_active(who.into(), self.total_counted.into()); + } + Pallet::::deposit_event(event); + Ok(()) + } + /// Cancel candidate bond less request + pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult + where + BalanceOf: From, + { + let request = self + .request + .ok_or(Error::::PendingCandidateRequestsDNE)?; + let event = Event::CancelledCandidateBondLess { + candidate: who.clone().into(), + amount: request.amount.into(), + execute_round: request.when_executable, + }; + self.request = None; + Pallet::::deposit_event(event); + Ok(()) + } + /// Reset top delegations metadata + pub fn reset_top_data( + &mut self, + candidate: T::AccountId, + top_delegations: &Delegations>, + ) where + BalanceOf: Into + From, + { + self.lowest_top_delegation_amount = top_delegations.lowest_delegation_amount().into(); + self.top_capacity = top_delegations.top_capacity::(); + let old_total_counted = self.total_counted; + self.total_counted = self.bond.saturating_add(top_delegations.total.into()); + // CandidatePool value for candidate always changes if top delegations total changes + // so we moved the update into this function to deduplicate code and patch a bug that + // forgot to apply the update when increasing top delegation + if old_total_counted != self.total_counted && self.is_active() { + Pallet::::update_active(candidate, self.total_counted.into()); + } + } + /// Reset bottom delegations metadata + pub fn reset_bottom_data( + &mut self, + bottom_delegations: &Delegations>, + ) where + BalanceOf: Into, + { + self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); + self.highest_bottom_delegation_amount = + bottom_delegations.highest_delegation_amount().into(); + self.bottom_capacity = bottom_delegations.bottom_capacity::(); + } + /// Add delegation + /// Returns whether delegator was added and an optional negative total counted remainder + /// for if a bottom delegation was kicked + /// MUST ensure no delegation exists for this candidate in the `DelegatorState` before call + pub fn add_delegation( + &mut self, + candidate: &T::AccountId, + delegation: Bond>, + ) -> Result<(DelegatorAdded, Option), DispatchError> + where + BalanceOf: Into + From, + { + let mut less_total_staked = None; + let delegator_added = match self.top_capacity { + CapacityStatus::Full => { + // top is full, insert into top iff the lowest_top < amount + if self.lowest_top_delegation_amount < delegation.amount.into() { + // bumps lowest top to the bottom inside this function call + less_total_staked = self.add_top_delegation::(candidate, delegation); + DelegatorAdded::AddedToTop { + new_total: self.total_counted, + } + } else { + // if bottom is full, only insert if greater than lowest bottom (which will + // be bumped out) + if matches!(self.bottom_capacity, CapacityStatus::Full) { + ensure!( + delegation.amount.into() > self.lowest_bottom_delegation_amount, + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + // need to subtract from total staked + less_total_staked = Some(self.lowest_bottom_delegation_amount); + } + // insert into bottom + self.add_bottom_delegation::(false, candidate, delegation); + DelegatorAdded::AddedToBottom + } + } + // top is either empty or partially full + _ => { + self.add_top_delegation::(candidate, delegation); + DelegatorAdded::AddedToTop { + new_total: self.total_counted, + } + } + }; + Ok((delegator_added, less_total_staked)) + } + /// Add delegation to top delegation + /// Returns Option + /// Only call if lowest top delegation is less than delegation.amount || !top_full + pub fn add_top_delegation( + &mut self, + candidate: &T::AccountId, + delegation: Bond>, + ) -> Option + where + BalanceOf: Into + From, + { + let mut less_total_staked = None; + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); + let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); + if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { + // pop lowest top delegation + let new_bottom_delegation = top_delegations.delegations.pop().expect(""); + top_delegations.total = top_delegations + .total + .saturating_sub(new_bottom_delegation.amount); + if matches!(self.bottom_capacity, CapacityStatus::Full) { + less_total_staked = Some(self.lowest_bottom_delegation_amount); + } + self.add_bottom_delegation::(true, candidate, new_bottom_delegation); + } + // insert into top + top_delegations.insert_sorted_greatest_to_least(delegation); + // update candidate info + self.reset_top_data::(candidate.clone(), &top_delegations); + if less_total_staked.is_none() { + // only increment delegation count if we are not kicking a bottom delegation + self.delegation_count = self.delegation_count.saturating_add(1u32); + } + >::insert(&candidate, top_delegations); + less_total_staked + } + /// Add delegation to bottom delegations + /// Check before call that if capacity is full, inserted delegation is higher than lowest + /// bottom delegation (and if so, need to adjust the total storage item) + /// CALLER MUST ensure(lowest_bottom_to_be_kicked.amount < delegation.amount) + pub fn add_bottom_delegation( + &mut self, + bumped_from_top: bool, + candidate: &T::AccountId, + delegation: Bond>, + ) where + BalanceOf: Into + From, + { + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); + // if bottom is full, kick the lowest bottom (which is expected to be lower than input + // as per check) + let increase_delegation_count = if bottom_delegations.delegations.len() as u32 + == T::MaxBottomDelegationsPerCandidate::get() + { + let lowest_bottom_to_be_kicked = bottom_delegations + .delegations + .pop() + .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); + // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller + // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick + // the lowest bottom to enforce first come first served + bottom_delegations.total = bottom_delegations + .total + .saturating_sub(lowest_bottom_to_be_kicked.amount); + // update delegator state + // total staked is updated via propagation of lowest bottom delegation amount prior + // to call + let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) + .expect("Delegation existence => DelegatorState existence"); + let leaving = delegator_state.delegations.0.len() == 1usize; + delegator_state.rm_delegation::(candidate); + >::delegation_remove_request_with_state( + &candidate, + &lowest_bottom_to_be_kicked.owner, + &mut delegator_state, + ); + >::remove_auto_compound( + &candidate, + &lowest_bottom_to_be_kicked.owner, + ); + + Pallet::::deposit_event(Event::DelegationKicked { + delegator: lowest_bottom_to_be_kicked.owner.clone(), + candidate: candidate.clone(), + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + if leaving { + >::remove(&lowest_bottom_to_be_kicked.owner); + Pallet::::deposit_event(Event::DelegatorLeft { + delegator: lowest_bottom_to_be_kicked.owner, + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + } else { + >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); + } + false + } else { + !bumped_from_top + }; + // only increase delegation count if new bottom delegation (1) doesn't come from top && + // (2) doesn't pop the lowest delegation from the bottom + if increase_delegation_count { + self.delegation_count = self.delegation_count.saturating_add(1u32); + } + bottom_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + } + /// Remove delegation + /// Removes from top if amount is above lowest top or top is not full + /// Return Ok(if_total_counted_changed) + pub fn rm_delegation_if_exists( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + amount: Balance, + ) -> Result + where + BalanceOf: Into + From, + { + let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; + let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { + self.rm_top_delegation::(candidate, delegator) + } else if amount_geq_lowest_top && lowest_top_eq_highest_bottom { + let result = self.rm_top_delegation::(candidate, delegator.clone()); + if result == Err(delegation_dne_err) { + // worst case removal + self.rm_bottom_delegation::(candidate, delegator) + } else { + result + } + } else { + self.rm_bottom_delegation::(candidate, delegator) + } + } + /// Remove top delegation, bumps top bottom delegation if exists + pub fn rm_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + ) -> Result + where + BalanceOf: Into + From, + { + let old_total_counted = self.total_counted; + // remove top delegation + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); + let mut actual_amount_option: Option> = None; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + actual_amount_option = Some(d.amount); + false + } + }) + .collect(); + let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; + top_delegations.total = top_delegations.total.saturating_sub(actual_amount); + // if bottom nonempty => bump top bottom to top + if !matches!(self.bottom_capacity, CapacityStatus::Empty) { + let mut bottom_delegations = + >::get(candidate).expect("bottom is nonempty as just checked"); + // expect already stored greatest to least by bond amount + let highest_bottom_delegation = bottom_delegations.delegations.remove(0); + bottom_delegations.total = bottom_delegations + .total + .saturating_sub(highest_bottom_delegation.amount); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + // insert highest bottom into top delegations + top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); + } + // update candidate info + self.reset_top_data::(candidate.clone(), &top_delegations); + self.delegation_count = self.delegation_count.saturating_sub(1u32); + >::insert(candidate, top_delegations); + // return whether total counted changed + Ok(old_total_counted == self.total_counted) + } + /// Remove bottom delegation + /// Returns if_total_counted_changed: bool + pub fn rm_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + ) -> Result + where + BalanceOf: Into, + { + // remove bottom delegation + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); + let mut actual_amount_option: Option> = None; + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + actual_amount_option = Some(d.amount); + false + } + }) + .collect(); + let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; + bottom_delegations.total = bottom_delegations.total.saturating_sub(actual_amount); + // update candidate info + self.reset_bottom_data::(&bottom_delegations); + self.delegation_count = self.delegation_count.saturating_sub(1u32); + >::insert(candidate, bottom_delegations); + Ok(false) + } + /// Increase delegation amount + pub fn increase_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { + // definitely in top + self.increase_top_delegation::(candidate, delegator.clone(), more) + } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { + // update top but if error then update bottom (because could be in bottom because + // lowest_top_eq_highest_bottom) + let result = self.increase_top_delegation::(candidate, delegator.clone(), more); + if result == Err(delegation_dne_err) { + self.increase_bottom_delegation::(candidate, delegator, bond, more) + } else { + result + } + } else { + self.increase_bottom_delegation::(candidate, delegator, bond, more) + } + } + /// Increase top delegation + pub fn increase_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); + let mut in_top = false; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_top = true; + let new_amount = d.amount.saturating_add(more); + Bond { + owner: d.owner, + amount: new_amount, + } + } + }) + .collect(); + ensure!(in_top, Error::::DelegationDNE); + top_delegations.total = top_delegations.total.saturating_add(more); + top_delegations.sort_greatest_to_least(); + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + Ok(true) + } + /// Increase bottom delegation + pub fn increase_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let mut bottom_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; + let mut delegation_option: Option>> = None; + let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount + { + // bump it from bottom + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_add(more), + }); + false + } + }) + .collect(); + let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; + bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); + // add it to top + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); + // if top is full, pop lowest top + if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { + // pop lowest top delegation + let new_bottom_delegation = top_delegations + .delegations + .pop() + .expect("Top capacity full => Exists at least 1 top delegation"); + top_delegations.total = top_delegations + .total + .saturating_sub(new_bottom_delegation.amount); + bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); + } + // insert into top + top_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + true + } else { + let mut in_bottom = false; + // just increase the delegation + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_bottom = true; + Bond { + owner: d.owner, + amount: d.amount.saturating_add(more), + } + } + }) + .collect(); + ensure!(in_bottom, Error::::DelegationDNE); + bottom_delegations.total = bottom_delegations.total.saturating_add(more); + bottom_delegations.sort_greatest_to_least(); + false + }; + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + Ok(in_top_after) + } + /// Decrease delegation + pub fn decrease_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: Balance, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { + // definitely in top + self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less) + } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { + // update top but if error then update bottom (because could be in bottom because + // lowest_top_eq_highest_bottom) + let result = + self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); + if result == Err(delegation_dne_err) { + self.decrease_bottom_delegation::(candidate, delegator, less) + } else { + result + } + } else { + self.decrease_bottom_delegation::(candidate, delegator, less) + } + } + /// Decrease top delegation + pub fn decrease_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + // The delegation after the `decrease-delegation` will be strictly less than the + // highest bottom delegation + let bond_after_less_than_highest_bottom = + bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; + // The top delegations is full and the bottom delegations has at least one delegation + let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) + && !matches!(self.bottom_capacity, CapacityStatus::Empty); + let mut top_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; + let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { + let mut delegation_option: Option>> = None; + // take delegation from top + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + top_delegations.total = top_delegations.total.saturating_sub(d.amount); + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_sub(less), + }); + false + } + }) + .collect(); + let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; + // pop highest bottom by reverse and popping + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); + let highest_bottom_delegation = bottom_delegations.delegations.remove(0); + bottom_delegations.total = bottom_delegations + .total + .saturating_sub(highest_bottom_delegation.amount); + // insert highest bottom into top + top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); + // insert previous top into bottom + bottom_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + false + } else { + // keep it in the top + let mut is_in_top = false; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + is_in_top = true; + Bond { + owner: d.owner, + amount: d.amount.saturating_sub(less), + } + } + }) + .collect(); + ensure!(is_in_top, Error::::DelegationDNE); + top_delegations.total = top_delegations.total.saturating_sub(less); + top_delegations.sort_greatest_to_least(); + true + }; + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + Ok(in_top_after) + } + /// Decrease bottom delegation + pub fn decrease_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into, + { + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); + let mut in_bottom = false; + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_bottom = true; + Bond { + owner: d.owner, + amount: d.amount.saturating_sub(less), + } + } + }) + .collect(); + ensure!(in_bottom, Error::::DelegationDNE); + bottom_delegations.sort_greatest_to_least(); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + Ok(false) + } +} + +// Temporary manual implementation for migration testing purposes +impl PartialEq for CollatorCandidate { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.id == other.id + && self.bond == other.bond + && self.total_counted == other.total_counted + && self.total_backing == other.total_backing + && self.request == other.request + && self.state == other.state; + if !must_be_true { + return false; + } + for (x, y) in self.delegators.0.iter().zip(other.delegators.0.iter()) { + if x != y { + return false; + } + } + for ( + Bond { + owner: o1, + amount: a1, + }, + Bond { + owner: o2, + amount: a2, + }, + ) in self + .top_delegations + .iter() + .zip(other.top_delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + for ( + Bond { + owner: o1, + amount: a1, + }, + Bond { + owner: o2, + amount: a2, + }, + ) in self + .bottom_delegations + .iter() + .zip(other.bottom_delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + true + } +} + +/// Convey relevant information describing if a delegator was added to the top or bottom +/// Delegations added to the top yield a new total +#[derive(Clone, Copy, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum DelegatorAdded { + AddedToTop { new_total: B }, + AddedToBottom, +} + +impl< + A: Ord + Clone + sp_std::fmt::Debug, + B: AtLeast32BitUnsigned + + Ord + + Copy + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::fmt::Debug, + > CollatorCandidate +{ + pub fn is_active(&self) -> bool { + self.state == CollatorStatus::Active + } +} + +impl From> for CollatorSnapshot { + fn from(other: CollatorCandidate) -> CollatorSnapshot { + CollatorSnapshot { + bond: other.bond, + delegations: other + .top_delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner, + amount: d.amount, + auto_compound: Percent::zero(), + }) + .collect(), + total: other.total_counted, + } + } +} + +#[allow(deprecated)] +#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum DelegatorStatus { + /// Active with no scheduled exit + Active, + /// Schedule exit to revoke all ongoing delegations + #[deprecated(note = "must only be used for backwards compatibility reasons")] + Leaving(RoundIndex), +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Delegator state +pub struct Delegator { + /// Delegator account + pub id: AccountId, + /// All current delegations + pub delegations: OrderedSet>, + /// Total balance locked for this delegator + pub total: Balance, + /// Sum of pending revocation amounts + bond less amounts + pub less_total: Balance, + /// Status for this delegator + pub status: DelegatorStatus, +} + +// Temporary manual implementation for migration testing purposes +impl PartialEq for Delegator { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.id == other.id + && self.total == other.total + && self.less_total == other.less_total + && self.status == other.status; + if !must_be_true { + return false; + } + for ( + Bond { + owner: o1, + amount: a1, + }, + Bond { + owner: o2, + amount: a2, + }, + ) in self.delegations.0.iter().zip(other.delegations.0.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + true + } +} + +impl< + AccountId: Ord + Clone, + Balance: Copy + + sp_std::ops::AddAssign + + sp_std::ops::Add + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + Ord + + Zero + + Default + + Saturating, + > Delegator +{ + pub fn new(id: AccountId, collator: AccountId, amount: Balance) -> Self { + Delegator { + id, + delegations: OrderedSet::from(vec![Bond { + owner: collator, + amount, + }]), + total: amount, + less_total: Balance::zero(), + status: DelegatorStatus::Active, + } + } + + pub fn default_with_total(id: AccountId, amount: Balance) -> Self { + Delegator { + id, + total: amount, + delegations: OrderedSet::from(vec![]), + less_total: Balance::zero(), + status: DelegatorStatus::Active, + } + } + + pub fn total(&self) -> Balance { + self.total + } + + pub fn total_sub_if(&mut self, amount: Balance, check: F) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + F: Fn(Balance) -> DispatchResult, + { + let total = self.total.saturating_sub(amount); + check(total)?; + self.total = total; + self.adjust_bond_lock::(BondAdjust::Decrease)?; + Ok(()) + } + + pub fn total_add(&mut self, amount: Balance) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + { + self.total = self.total.saturating_add(amount); + self.adjust_bond_lock::(BondAdjust::Increase(amount))?; + Ok(()) + } + + pub fn total_sub(&mut self, amount: Balance) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + { + self.total = self.total.saturating_sub(amount); + self.adjust_bond_lock::(BondAdjust::Decrease)?; + Ok(()) + } + + pub fn is_active(&self) -> bool { + matches!(self.status, DelegatorStatus::Active) + } + + pub fn add_delegation(&mut self, bond: Bond) -> bool { + let amt = bond.amount; + if self.delegations.insert(bond) { + self.total = self.total.saturating_add(amt); + true + } else { + false + } + } + // Return Some(remaining balance), must be more than MinDelegatorStk + // Return None if delegation not found + pub fn rm_delegation(&mut self, collator: &AccountId) -> Option + where + BalanceOf: From, + T::AccountId: From, + { + let mut amt: Option = None; + let delegations = self + .delegations + .0 + .iter() + .filter_map(|x| { + if &x.owner == collator { + amt = Some(x.amount); + None + } else { + Some(x.clone()) + } + }) + .collect(); + if let Some(balance) = amt { + self.delegations = OrderedSet::from(delegations); + self.total_sub::(balance) + .expect("Decreasing lock cannot fail, qed"); + Some(self.total) + } else { + None + } + } + + /// Increases the delegation amount and returns `true` if the delegation is part of the + /// TopDelegations set, `false` otherwise. + pub fn increase_delegation( + &mut self, + candidate: AccountId, + amount: Balance, + ) -> Result + where + BalanceOf: From, + T::AccountId: From, + Delegator>: From>, + { + let delegator_id: T::AccountId = self.id.clone().into(); + let candidate_id: T::AccountId = candidate.clone().into(); + let balance_amt: BalanceOf = amount.into(); + // increase delegation + for x in &mut self.delegations.0 { + if x.owner == candidate { + let before_amount: BalanceOf = x.amount.into(); + x.amount = x.amount.saturating_add(amount); + self.total = self.total.saturating_add(amount); + self.adjust_bond_lock::(BondAdjust::Increase(amount))?; + + // update collator state delegation + let mut collator_state = + >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; + let before = collator_state.total_counted; + let in_top = collator_state.increase_delegation::( + &candidate_id, + delegator_id.clone(), + before_amount, + balance_amt, + )?; + let after = collator_state.total_counted; + if collator_state.is_active() && (before != after) { + Pallet::::update_active(candidate_id.clone(), after); + } + >::insert(&candidate_id, collator_state); + let new_total_staked = >::get().saturating_add(balance_amt); + >::put(new_total_staked); + let nom_st: Delegator> = self.clone().into(); + >::insert(&delegator_id, nom_st); + return Ok(in_top); + } + } + Err(Error::::DelegationDNE.into()) + } + + /// Updates the bond locks for this delegator. + /// + /// This will take the current self.total and ensure that a lock of the same amount is applied + /// and when increasing the bond lock will also ensure that the account has enough free balance. + /// + /// `additional_required_balance` should reflect the change to the amount that should be locked if + /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is + /// not possible to query the amount that is locked for a given lock id. + pub fn adjust_bond_lock( + &mut self, + additional_required_balance: BondAdjust, + ) -> DispatchResult + where + BalanceOf: From, + T::AccountId: From, + { + match additional_required_balance { + BondAdjust::Increase(amount) => { + ensure!( + >::get_delegator_stakable_free_balance(&self.id.clone().into()) + >= amount.into(), + Error::::InsufficientBalance, + ); + + // additional sanity check: shouldn't ever want to lock more than total + if amount > self.total { + log::warn!("LOGIC ERROR: request to reserve more than bond total"); + return Err(DispatchError::Other("Invalid additional_required_balance")); + } + } + BondAdjust::Decrease => (), // do nothing on decrease + }; + + if self.total.is_zero() { + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &self.id.clone().into()); + } else { + T::Currency::set_lock( + DELEGATOR_LOCK_ID, + &self.id.clone().into(), + self.total.into(), + WithdrawReasons::all(), + ); + } + Ok(()) + } + + /// Retrieves the bond amount that a delegator has provided towards a collator. + /// Returns `None` if missing. + pub fn get_bond_amount(&self, collator: &AccountId) -> Option { + self.delegations + .0 + .iter() + .find(|b| &b.owner == collator) + .map(|b| b.amount) + } +} + +pub mod deprecated { + #![allow(deprecated)] + + use super::*; + + #[deprecated(note = "use DelegationAction")] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] + /// Changes requested by the delegator + /// - limit of 1 ongoing change per delegation + pub enum DelegationChange { + Revoke, + Decrease, + } + + #[deprecated(note = "use ScheduledRequest")] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] + pub struct DelegationRequest { + pub collator: AccountId, + pub amount: Balance, + pub when_executable: RoundIndex, + pub action: DelegationChange, + } + + #[deprecated(note = "use DelegationScheduledRequests storage item")] + #[derive(Clone, Encode, PartialEq, Decode, RuntimeDebug, TypeInfo)] + /// Pending requests to mutate delegations for each delegator + pub struct PendingDelegationRequests { + /// Number of pending revocations (necessary for determining whether revoke is exit) + pub revocations_count: u32, + /// Map from collator -> Request (enforces at most 1 pending request per delegation) + pub requests: BTreeMap>, + /// Sum of pending revocation amounts + bond less amounts + pub less_total: Balance, + } + + impl Default for PendingDelegationRequests { + fn default() -> PendingDelegationRequests { + PendingDelegationRequests { + revocations_count: 0u32, + requests: BTreeMap::new(), + less_total: B::zero(), + } + } + } + + impl< + A: Ord + Clone, + B: Zero + + Ord + + Copy + + Clone + + sp_std::ops::AddAssign + + sp_std::ops::Add + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + Saturating, + > PendingDelegationRequests + { + /// New default (empty) pending requests + pub fn new() -> Self { + Self::default() + } + } + + #[deprecated(note = "use new crate::types::Delegator struct")] + #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] + /// Delegator state + pub struct Delegator { + /// Delegator account + pub id: AccountId, + /// All current delegations + pub delegations: OrderedSet>, + /// Total balance locked for this delegator + pub total: Balance, + /// Requests to change delegations, relevant iff active + pub requests: PendingDelegationRequests, + /// Status for this delegator + pub status: DelegatorStatus, + } + + // CollatorSnapshot + + #[deprecated(note = "use CollatorSnapshot with BondWithAutoCompound delegations")] + #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] + /// Snapshot of collator state at the start of the round for which they are selected + pub struct CollatorSnapshot { + /// The total value locked by the collator. + pub bond: Balance, + + /// The rewardable delegations. This list is a subset of total delegators, where certain + /// delegators are adjusted based on their scheduled + /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. + pub delegations: Vec>, + + /// The total counted value locked for the collator, including the self bond + total staked by + /// top delegators. + pub total: Balance, + } + + impl PartialEq for CollatorSnapshot { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.bond == other.bond && self.total == other.total; + if !must_be_true { + return false; + } + for ( + Bond { + owner: o1, + amount: a1, + }, + Bond { + owner: o2, + amount: a2, + }, + ) in self.delegations.iter().zip(other.delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + true + } + } + + impl Default for CollatorSnapshot { + fn default() -> CollatorSnapshot { + CollatorSnapshot { + bond: B::default(), + delegations: Vec::new(), + total: B::default(), + } + } + } +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +/// DEPRECATED in favor of Delegator +/// Nominator state +pub struct Nominator2 { + /// All current delegations + pub delegations: OrderedSet>, + /// Delegations scheduled to be revoked + pub revocations: OrderedSet, + /// Total balance locked for this nominator + pub total: Balance, + /// Total number of revocations scheduled to be executed + pub scheduled_revocations_count: u32, + /// Total amount to be unbonded once revocations are executed + pub scheduled_revocations_total: Balance, + /// Status for this nominator + pub status: DelegatorStatus, +} + +// /// Temporary function to migrate state +// pub(crate) fn migrate_nominator_to_delegator_state( +// id: T::AccountId, +// nominator: Nominator2>, +// ) -> Delegator> { +// Delegator { +// id, +// delegations: nominator.delegations, +// total: nominator.total, +// requests: PendingDelegationRequests::new(), +// status: nominator.status, +// } +// } + +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// The current round index and transition information +pub struct RoundInfo { + /// Current round index + pub current: RoundIndex, + /// The first block of the current round + pub first: BlockNumber, + /// The length of the current round in number of blocks + pub length: u32, +} +impl< + B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, + > RoundInfo +{ + pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { + RoundInfo { + current, + first, + length, + } + } + /// Check if the round should be updated + pub fn should_update(&self, now: B) -> bool { + now - self.first >= self.length.into() + } + /// New round + pub fn update(&mut self, now: B) { + self.current = self.current.saturating_add(1u32); + self.first = now; + } +} +impl< + B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, + > Default for RoundInfo +{ + fn default() -> RoundInfo { + RoundInfo::new(1u32, 1u32.into(), 20u32) + } +} + +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Reserve information { account, percent_of_inflation } +pub struct ParachainBondConfig { + /// Account which receives funds intended for parachain bond + pub account: AccountId, + /// Percent of inflation set aside for parachain bond account + pub percent: Percent, +} +impl Default for ParachainBondConfig { + fn default() -> ParachainBondConfig { + ParachainBondConfig { + account: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + percent: Percent::zero(), + } + } +} + +pub enum BondAdjust { + Increase(Balance), + Decrease, +} diff --git a/external/pallets/parachain-staking/src/weights.rs b/external/pallets/parachain-staking/src/weights.rs new file mode 100644 index 000000000..01c070a18 --- /dev/null +++ b/external/pallets/parachain-staking/src/weights.rs @@ -0,0 +1,903 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Autogenerated weights for parachain_staking +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// parachain_staking +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --template=./benchmarking/frame-weight-template.hbs +// --json-file +// raw.json +// --output +// weights.rs + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for parachain_staking. +pub trait WeightInfo { + #[rustfmt::skip] + fn set_staking_expectations() -> Weight; + #[rustfmt::skip] + fn set_inflation() -> Weight; + #[rustfmt::skip] + fn set_parachain_bond_account() -> Weight; + #[rustfmt::skip] + fn set_parachain_bond_reserve_percent() -> Weight; + #[rustfmt::skip] + fn set_total_selected() -> Weight; + #[rustfmt::skip] + fn set_collator_commission() -> Weight; + #[rustfmt::skip] + fn set_blocks_per_round() -> Weight; + #[rustfmt::skip] + fn join_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn schedule_leave_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn execute_leave_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn cancel_leave_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn go_offline() -> Weight; + #[rustfmt::skip] + fn go_online() -> Weight; + #[rustfmt::skip] + fn candidate_bond_more() -> Weight; + #[rustfmt::skip] + fn schedule_candidate_bond_less() -> Weight; + #[rustfmt::skip] + fn execute_candidate_bond_less() -> Weight; + #[rustfmt::skip] + fn cancel_candidate_bond_less() -> Weight; + #[rustfmt::skip] + fn delegate(x: u32, y: u32, ) -> Weight; + #[rustfmt::skip] + fn schedule_leave_delegators() -> Weight; + #[rustfmt::skip] + fn execute_leave_delegators(x: u32, ) -> Weight; + #[rustfmt::skip] + fn cancel_leave_delegators() -> Weight; + #[rustfmt::skip] + fn schedule_revoke_delegation() -> Weight; + #[rustfmt::skip] + fn delegator_bond_more() -> Weight; + #[rustfmt::skip] + fn schedule_delegator_bond_less() -> Weight; + #[rustfmt::skip] + fn execute_revoke_delegation() -> Weight; + #[rustfmt::skip] + fn execute_delegator_bond_less() -> Weight; + #[rustfmt::skip] + fn cancel_revoke_delegation() -> Weight; + #[rustfmt::skip] + fn cancel_delegator_bond_less() -> Weight; + #[rustfmt::skip] + fn prepare_staking_payouts() -> Weight; + #[rustfmt::skip] + fn get_rewardable_delegators(y: u32, ) -> Weight; + #[rustfmt::skip] + fn select_top_candidates(x: u32, y: u32, ) -> Weight; + #[rustfmt::skip] + fn pay_one_collator_reward(y: u32, ) -> Weight; + #[rustfmt::skip] + fn base_on_initialize() -> Weight; + #[rustfmt::skip] + fn set_auto_compound(x: u32, y: u32, ) -> Weight; + #[rustfmt::skip] + fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight; + #[rustfmt::skip] + fn mint_collator_reward() -> Weight; +} + +/// Weights for parachain_staking using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_staking_expectations() -> Weight { + Weight::from_ref_time(48_225_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_inflation() -> Weight { + Weight::from_ref_time(61_063_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_account() -> Weight { + Weight::from_ref_time(27_645_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_reserve_percent() -> Weight { + Weight::from_ref_time(26_922_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:1) + #[rustfmt::skip] + fn set_total_selected() -> Weight { + Weight::from_ref_time(29_263_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CollatorCommission (r:1 w:1) + #[rustfmt::skip] + fn set_collator_commission() -> Weight { + Weight::from_ref_time(25_867_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_blocks_per_round() -> Weight { + Weight::from_ref_time(66_047_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:0 w:1) + // Storage: ParachainStaking BottomDelegations (r:0 w:1) + #[rustfmt::skip] + fn join_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(93_609_702 as u64) + // Standard Error: 1_049 + .saturating_add(Weight::from_ref_time(156_227 as u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(74_938_974 as u64) + // Standard Error: 1_813 + .saturating_add(Weight::from_ref_time(136_560 as u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: Balances Locks (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(120_885_000 as u64) + // Standard Error: 73_687 + .saturating_add(Weight::from_ref_time(31_457_020 as u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(x as u64))) + .saturating_add(T::DbWeight::get().writes(5 as u64)) + .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(70_048_572 as u64) + // Standard Error: 1_524 + .saturating_add(Weight::from_ref_time(145_661 as u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_offline() -> Weight { + Weight::from_ref_time(42_412_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_online() -> Weight { + Weight::from_ref_time(41_744_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn candidate_bond_more() -> Weight { + Weight::from_ref_time(68_900_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(5 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn schedule_candidate_bond_less() -> Weight { + Weight::from_ref_time(38_239_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn execute_candidate_bond_less() -> Weight { + Weight::from_ref_time(76_166_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(5 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn cancel_candidate_bond_less() -> Weight { + Weight::from_ref_time(35_581_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegate(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(131_245_351 as u64) + // Standard Error: 19_323 + .saturating_add(Weight::from_ref_time(239_400 as u64).saturating_mul(x as u64)) + // Standard Error: 6_339 + .saturating_add(Weight::from_ref_time(261_836 as u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_delegators() -> Weight { + Weight::from_ref_time(44_609_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_delegators(x: u32, ) -> Weight { + Weight::from_ref_time(14_022_061 as u64) + // Standard Error: 30_972 + .saturating_add(Weight::from_ref_time(29_549_278 as u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(x as u64))) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_delegators() -> Weight { + Weight::from_ref_time(44_825_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_revoke_delegation() -> Weight { + Weight::from_ref_time(43_131_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegator_bond_more() -> Weight { + Weight::from_ref_time(90_452_000 as u64) + .saturating_add(T::DbWeight::get().reads(8 as u64)) + .saturating_add(T::DbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_delegator_bond_less() -> Weight { + Weight::from_ref_time(43_388_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_revoke_delegation() -> Weight { + Weight::from_ref_time(112_401_000 as u64) + .saturating_add(T::DbWeight::get().reads(9 as u64)) + .saturating_add(T::DbWeight::get().writes(8 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_delegator_bond_less() -> Weight { + Weight::from_ref_time(97_377_000 as u64) + .saturating_add(T::DbWeight::get().reads(8 as u64)) + .saturating_add(T::DbWeight::get().writes(8 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_revoke_delegation() -> Weight { + Weight::from_ref_time(43_406_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_delegator_bond_less() -> Weight { + Weight::from_ref_time(49_020_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking Staked (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CollatorCommission (r:1 w:0) + // Storage: ParachainStaking DelayedPayouts (r:0 w:1) + #[rustfmt::skip] + fn prepare_staking_payouts() -> Weight { + Weight::from_ref_time(59_628_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + #[rustfmt::skip] + fn get_rewardable_delegators(y: u32, ) -> Weight { + Weight::from_ref_time(16_322_694 as u64) + // Standard Error: 1_133 + .saturating_add(Weight::from_ref_time(233_812 as u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:0) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:0 w:1) + // Storage: ParachainStaking AtStake (r:0 w:1) + #[rustfmt::skip] + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(44_110_000 as u64) + // Standard Error: 237_049 + .saturating_add(Weight::from_ref_time(24_788_127 as u64).saturating_mul(x as u64)) + // Standard Error: 118_210 + .saturating_add(Weight::from_ref_time(2_957_731 as u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(x as u64))) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelayedPayouts (r:1 w:0) + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking AtStake (r:2 w:1) + // Storage: ParachainStaking AwardedPts (r:1 w:1) + // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn pay_one_collator_reward(y: u32, ) -> Weight { + Weight::from_ref_time(65_307_432 as u64) + // Standard Error: 9_596 + .saturating_add(Weight::from_ref_time(17_073_916 as u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(y as u64))) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(y as u64))) + } + #[rustfmt::skip] + fn base_on_initialize() -> Weight { + Weight::from_ref_time(10_890_000 as u64) + } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + #[rustfmt::skip] + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(64_797_700 as u64) + // Standard Error: 5_810 + .saturating_add(Weight::from_ref_time(292_809 as u64).saturating_mul(x as u64)) + // Standard Error: 17_394 + .saturating_add(Weight::from_ref_time(258_382 as u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + #[rustfmt::skip] + fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { + Weight::from_ref_time(181_911_542 as u64) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(120_473 as u64).saturating_mul(x as u64)) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(80_638 as u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(8 as u64)) + .saturating_add(T::DbWeight::get().writes(8 as u64)) + } + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn mint_collator_reward() -> Weight { + Weight::from_ref_time(40_146_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_staking_expectations() -> Weight { + Weight::from_ref_time(48_225_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_inflation() -> Weight { + Weight::from_ref_time(61_063_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_account() -> Weight { + Weight::from_ref_time(27_645_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_reserve_percent() -> Weight { + Weight::from_ref_time(26_922_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:1) + #[rustfmt::skip] + fn set_total_selected() -> Weight { + Weight::from_ref_time(29_263_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CollatorCommission (r:1 w:1) + #[rustfmt::skip] + fn set_collator_commission() -> Weight { + Weight::from_ref_time(25_867_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_blocks_per_round() -> Weight { + Weight::from_ref_time(66_047_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:0 w:1) + // Storage: ParachainStaking BottomDelegations (r:0 w:1) + #[rustfmt::skip] + fn join_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(93_609_702 as u64) + // Standard Error: 1_049 + .saturating_add(Weight::from_ref_time(156_227 as u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(74_938_974 as u64) + // Standard Error: 1_813 + .saturating_add(Weight::from_ref_time(136_560 as u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: Balances Locks (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(120_885_000 as u64) + // Standard Error: 73_687 + .saturating_add(Weight::from_ref_time(31_457_020 as u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().reads((3 as u64).saturating_mul(x as u64))) + .saturating_add(RocksDbWeight::get().writes(5 as u64)) + .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(70_048_572 as u64) + // Standard Error: 1_524 + .saturating_add(Weight::from_ref_time(145_661 as u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_offline() -> Weight { + Weight::from_ref_time(42_412_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_online() -> Weight { + Weight::from_ref_time(41_744_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn candidate_bond_more() -> Weight { + Weight::from_ref_time(68_900_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(5 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn schedule_candidate_bond_less() -> Weight { + Weight::from_ref_time(38_239_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn execute_candidate_bond_less() -> Weight { + Weight::from_ref_time(76_166_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(5 as u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn cancel_candidate_bond_less() -> Weight { + Weight::from_ref_time(35_581_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegate(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(131_245_351 as u64) + // Standard Error: 19_323 + .saturating_add(Weight::from_ref_time(239_400 as u64).saturating_mul(x as u64)) + // Standard Error: 6_339 + .saturating_add(Weight::from_ref_time(261_836 as u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(7 as u64)) + .saturating_add(RocksDbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_delegators() -> Weight { + Weight::from_ref_time(44_609_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_delegators(x: u32, ) -> Weight { + Weight::from_ref_time(14_022_061 as u64) + // Standard Error: 30_972 + .saturating_add(Weight::from_ref_time(29_549_278 as u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(x as u64))) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_delegators() -> Weight { + Weight::from_ref_time(44_825_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_revoke_delegation() -> Weight { + Weight::from_ref_time(43_131_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegator_bond_more() -> Weight { + Weight::from_ref_time(90_452_000 as u64) + .saturating_add(RocksDbWeight::get().reads(8 as u64)) + .saturating_add(RocksDbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_delegator_bond_less() -> Weight { + Weight::from_ref_time(43_388_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_revoke_delegation() -> Weight { + Weight::from_ref_time(112_401_000 as u64) + .saturating_add(RocksDbWeight::get().reads(9 as u64)) + .saturating_add(RocksDbWeight::get().writes(8 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_delegator_bond_less() -> Weight { + Weight::from_ref_time(97_377_000 as u64) + .saturating_add(RocksDbWeight::get().reads(8 as u64)) + .saturating_add(RocksDbWeight::get().writes(8 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_revoke_delegation() -> Weight { + Weight::from_ref_time(43_406_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_delegator_bond_less() -> Weight { + Weight::from_ref_time(49_020_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking Staked (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CollatorCommission (r:1 w:0) + // Storage: ParachainStaking DelayedPayouts (r:0 w:1) + #[rustfmt::skip] + fn prepare_staking_payouts() -> Weight { + Weight::from_ref_time(59_628_000 as u64) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + #[rustfmt::skip] + fn get_rewardable_delegators(y: u32, ) -> Weight { + Weight::from_ref_time(16_322_694 as u64) + // Standard Error: 1_133 + .saturating_add(Weight::from_ref_time(233_812 as u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:0) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:0 w:1) + // Storage: ParachainStaking AtStake (r:0 w:1) + #[rustfmt::skip] + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(44_110_000 as u64) + // Standard Error: 237_049 + .saturating_add(Weight::from_ref_time(24_788_127 as u64).saturating_mul(x as u64)) + // Standard Error: 118_210 + .saturating_add(Weight::from_ref_time(2_957_731 as u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(x as u64))) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelayedPayouts (r:1 w:0) + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking AtStake (r:2 w:1) + // Storage: ParachainStaking AwardedPts (r:1 w:1) + // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn pay_one_collator_reward(y: u32, ) -> Weight { + Weight::from_ref_time(65_307_432 as u64) + // Standard Error: 9_596 + .saturating_add(Weight::from_ref_time(17_073_916 as u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(7 as u64)) + .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(y as u64))) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(y as u64))) + } + #[rustfmt::skip] + fn base_on_initialize() -> Weight { + Weight::from_ref_time(10_890_000 as u64) + } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + #[rustfmt::skip] + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(64_797_700 as u64) + // Standard Error: 5_810 + .saturating_add(Weight::from_ref_time(292_809 as u64).saturating_mul(x as u64)) + // Standard Error: 17_394 + .saturating_add(Weight::from_ref_time(258_382 as u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + #[rustfmt::skip] + fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { + Weight::from_ref_time(181_911_542 as u64) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(120_473 as u64).saturating_mul(x as u64)) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(80_638 as u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(8 as u64)) + .saturating_add(RocksDbWeight::get().writes(8 as u64)) + } + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn mint_collator_reward() -> Weight { + Weight::from_ref_time(40_146_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } +} diff --git a/external/session-keys/Cargo.toml b/external/session-keys/Cargo.toml new file mode 100644 index 000000000..e84385752 --- /dev/null +++ b/external/session-keys/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "session-keys-primitives" +authors = [ "PureStake" ] +description = "Primitives for session keys" +edition = "2021" +version = "0.1.0" + +[dependencies] +async-trait = { version = "0.1", optional = true } +frame-support = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +nimbus-primitives = { path = "../nimbus-primitives", default-features = false } +parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } +scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } +sp-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-consensus-babe = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-consensus-vrf = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-keystore = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", optional = true, default-features = false } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-std = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } + +[features] +default = [ "std" ] +std = [ + "async-trait", + "frame-support/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-api/std", + "sp-application-crypto/std", + "sp-consensus-babe/std", + "sp-consensus-vrf/std", + "sp-core/std", + "sp-inherents/std", + "sp-keystore", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [] diff --git a/external/session-keys/src/digest.rs b/external/session-keys/src/digest.rs new file mode 100644 index 000000000..c82cf7f92 --- /dev/null +++ b/external/session-keys/src/digest.rs @@ -0,0 +1,63 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! VRF pre digest object and conversion to DigestItem +use crate::vrf::{VrfSignature, VRF_ENGINE_ID}; +use parity_scale_codec::{Decode, Encode}; +use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; +use sp_runtime::{generic::DigestItem, RuntimeDebug}; + +/// Raw VRF pre-digest. +#[derive(Clone, RuntimeDebug, Encode, Decode)] +pub struct PreDigest { + /// VRF output + pub vrf_output: VRFOutput, + /// VRF proof + pub vrf_proof: VRFProof, +} + +/// A digest item which is usable with moonbeam VRF. +pub trait CompatibleDigestItem: Sized { + /// Construct a digest item which contains a VRF pre-digest. + fn vrf_pre_digest(seal: PreDigest) -> Self; + + /// If this item is an VRF pre-digest, return it. + fn as_vrf_pre_digest(&self) -> Option; + + /// Construct a digest item which contains a VRF seal. + fn vrf_seal(signature: VrfSignature) -> Self; + + /// If this item is a VRF signature, return the signature. + fn as_vrf_seal(&self) -> Option; +} + +impl CompatibleDigestItem for DigestItem { + fn vrf_pre_digest(digest: PreDigest) -> Self { + DigestItem::PreRuntime(VRF_ENGINE_ID, digest.encode()) + } + + fn as_vrf_pre_digest(&self) -> Option { + self.pre_runtime_try_to(&VRF_ENGINE_ID) + } + + fn vrf_seal(signature: VrfSignature) -> Self { + DigestItem::Seal(VRF_ENGINE_ID, signature.encode()) + } + + fn as_vrf_seal(&self) -> Option { + self.seal_try_to(&VRF_ENGINE_ID) + } +} diff --git a/external/session-keys/src/inherent.rs b/external/session-keys/src/inherent.rs new file mode 100644 index 000000000..7e645ee1a --- /dev/null +++ b/external/session-keys/src/inherent.rs @@ -0,0 +1,76 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . +use parity_scale_codec::{Decode, Encode}; +use sp_inherents::{Error, InherentData, InherentIdentifier, IsFatalError}; +use sp_runtime::RuntimeString; + +#[derive(Encode)] +#[cfg_attr(feature = "std", derive(Debug, Decode))] +pub enum InherentError { + Other(RuntimeString), +} + +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + match *self { + InherentError::Other(_) => true, + } + } +} + +impl InherentError { + /// Try to create an instance ouf of the given identifier and data. + #[cfg(feature = "std")] + pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { + if id == &INHERENT_IDENTIFIER { + ::decode(&mut &*data).ok() + } else { + None + } + } +} + +/// The InherentIdentifier to set the babe randomness results +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"baberand"; + +/// A bare minimum inherent data provider that provides no real data. +/// The inherent is simply used as a way to kick off some computation +/// until https://github.com/zeitgeistpm/substrate/pull/10128 lands. +pub struct InherentDataProvider; + +#[cfg(feature = "std")] +#[async_trait::async_trait] +impl sp_inherents::InherentDataProvider for InherentDataProvider { + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> { + inherent_data.put_data(INHERENT_IDENTIFIER, &()) + } + + async fn try_handle_error( + &self, + identifier: &InherentIdentifier, + _error: &[u8], + ) -> Option> { + // Don't process modules from other inherents + if *identifier != INHERENT_IDENTIFIER { + return None; + } + + // All errors with the randomness inherent are fatal + Some(Err(Error::Application(Box::from(String::from( + "Error processing dummy randomness inherent", + ))))) + } +} diff --git a/external/session-keys/src/lib.rs b/external/session-keys/src/lib.rs new file mode 100644 index 000000000..4fb8eeb56 --- /dev/null +++ b/external/session-keys/src/lib.rs @@ -0,0 +1,45 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Primitives for session keys +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod digest; +pub mod inherent; +pub mod vrf; +pub use digest::*; +pub use inherent::*; +pub use vrf::*; + +/// A Trait to lookup keys from AuthorIds +pub trait KeysLookup { + #[cfg(feature = "runtime-benchmarks")] + type Account; + fn lookup_keys(author: &AuthorId) -> Option; + #[cfg(feature = "runtime-benchmarks")] + fn set_keys(id: AuthorId, account: Self::Account, keys: Keys); +} + +// A dummy impl used in simple tests +impl KeysLookup for () { + #[cfg(feature = "runtime-benchmarks")] + type Account = (); + fn lookup_keys(_: &AuthorId) -> Option { + None + } + #[cfg(feature = "runtime-benchmarks")] + fn set_keys(_id: AuthorId, _account: Self::Account, _keys: Keys) {} +} diff --git a/external/session-keys/src/vrf.rs b/external/session-keys/src/vrf.rs new file mode 100644 index 000000000..b8a1a8ddb --- /dev/null +++ b/external/session-keys/src/vrf.rs @@ -0,0 +1,100 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! VRF Key type +use nimbus_primitives::NimbusId; +use sp_application_crypto::{sr25519, KeyTypeId, UncheckedFrom}; +use sp_consensus_babe::Transcript; +#[cfg(feature = "std")] +use sp_keystore::vrf::{VRFTranscriptData, VRFTranscriptValue}; +use sp_runtime::{BoundToRuntimeAppPublic, ConsensusEngineId}; + +/// Make VRF transcript from the VrfInput +pub fn make_transcript>(last_vrf_output: Hash) -> Transcript { + let mut transcript = Transcript::new(&VRF_ENGINE_ID); + transcript.append_message(b"last vrf output", last_vrf_output.as_ref()); + transcript +} + +/// Make a VRF transcript data container +#[cfg(feature = "std")] +pub fn make_transcript_data>(last_vrf_output: Hash) -> VRFTranscriptData { + VRFTranscriptData { + label: &VRF_ENGINE_ID, + items: vec![( + "last vrf output", + VRFTranscriptValue::Bytes(last_vrf_output.as_ref().to_vec()), + )], + } +} + +/// Struct to implement `BoundToRuntimeAppPublic` by assigning Public = VrfId +pub struct VrfSessionKey; + +impl BoundToRuntimeAppPublic for VrfSessionKey { + type Public = VrfId; +} + +impl From for VrfId { + fn from(nimbus_id: NimbusId) -> VrfId { + let nimbus_as_sr25519: sr25519::Public = nimbus_id.into(); + let sr25519_as_bytes: [u8; 32] = nimbus_as_sr25519.into(); + sr25519::Public::unchecked_from(sr25519_as_bytes).into() + } +} + +/// The ConsensusEngineId for VRF keys +pub const VRF_ENGINE_ID: ConsensusEngineId = *b"rand"; + +/// The KeyTypeId used for VRF keys +pub const VRF_KEY_ID: KeyTypeId = KeyTypeId(VRF_ENGINE_ID); + +/// VRFInOut context. +pub static VRF_INOUT_CONTEXT: &[u8] = b"VRFInOutContext"; + +// The strongly-typed crypto wrappers to be used by VRF in the keystore +mod vrf_crypto { + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, crate::VRF_KEY_ID); +} + +/// A vrf public key. +pub type VrfId = vrf_crypto::Public; + +/// A vrf signature. +pub type VrfSignature = vrf_crypto::Signature; + +sp_application_crypto::with_pair! { + /// A vrf key pair + pub type VrfPair = vrf_crypto::Pair; +} + +sp_api::decl_runtime_apis! { + pub trait VrfApi { + fn get_last_vrf_output() -> Option; + fn vrf_key_lookup(nimbus_id: nimbus_primitives::NimbusId) -> Option; + } +} + +#[test] +fn nimbus_to_vrf_id() { + for x in 0u8..10u8 { + let nimbus_id: NimbusId = sr25519::Public::unchecked_from([x; 32]).into(); + let expected_vrf_id: VrfId = sr25519::Public::unchecked_from([x; 32]).into(); + let nimbus_to_vrf_id: VrfId = nimbus_id.into(); + assert_eq!(expected_vrf_id, nimbus_to_vrf_id); + } +} diff --git a/external/vrf/Cargo.toml b/external/vrf/Cargo.toml new file mode 100644 index 000000000..5b4e1df6b --- /dev/null +++ b/external/vrf/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "moonbeam-vrf" +authors = [ "PureStake" ] +edition = "2018" +homepage = "https://moonbeam.network" +license = "GPL-3.0-only" +repository = "https://github.com/PureStake/moonbeam/" +version = "0.1.0" + +[dependencies] +# Substrate +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } +sp-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-consensus-vrf = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-keystore = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } + +# Moonbeam +session-keys-primitives = { path = "../session-keys" } + +# Nimbus +nimbus-primitives = { path = "../nimbus-primitives" } + +# Polkadot +polkadot-primitives = { git = "https://github.com/zeitgeistpm/polkadot", branch = "moonbeam-polkadot-v0.9.29" } diff --git a/external/vrf/src/lib.rs b/external/vrf/src/lib.rs new file mode 100644 index 000000000..169e13660 --- /dev/null +++ b/external/vrf/src/lib.rs @@ -0,0 +1,75 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! VRF client primitives for client-side verification + +use nimbus_primitives::NimbusId; +use session_keys_primitives::{make_transcript, make_transcript_data, PreDigest, VrfApi, VrfId}; +use sp_application_crypto::{AppKey, ByteArray}; +use sp_consensus_vrf::schnorrkel::{PublicKey, VRFOutput, VRFProof}; +use sp_core::H256; +use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; + +/// Uses the runtime API to get the VRF inputs and sign them with the VRF key that +/// corresponds to the authoring NimbusId. +pub fn vrf_pre_digest( + client: &C, + keystore: &SyncCryptoStorePtr, + nimbus_id: NimbusId, + parent: H256, +) -> Option +where + B: sp_runtime::traits::Block, + C: sp_api::ProvideRuntimeApi, + C::Api: VrfApi, +{ + let at = sp_api::BlockId::Hash(parent); + let runtime_api = client.runtime_api(); + + // first ? for runtime API, second ? for if last vrf output is not available + let last_vrf_output = runtime_api.get_last_vrf_output(&at).ok()??; + // first ? for runtime API, second ? for not VRF key associated with NimbusId + let key: VrfId = runtime_api.vrf_key_lookup(&at, nimbus_id).ok()??; + let vrf_pre_digest = sign_vrf(last_vrf_output, key, &keystore)?; + Some(session_keys_primitives::digest::CompatibleDigestItem::vrf_pre_digest(vrf_pre_digest)) +} + +/// Signs the VrfInput using the private key corresponding to the input `key` public key +/// to be found in the input keystore +fn sign_vrf(last_vrf_output: H256, key: VrfId, keystore: &SyncCryptoStorePtr) -> Option { + let transcript = make_transcript(last_vrf_output.clone()); + let transcript_data = make_transcript_data(last_vrf_output); + let try_sign = + SyncCryptoStore::sr25519_vrf_sign(&**keystore, VrfId::ID, key.as_ref(), transcript_data); + if let Ok(Some(signature)) = try_sign { + let public = PublicKey::from_bytes(&key.to_raw_vec()).ok()?; + if signature + .output + .attach_input_hash(&public, transcript) + .is_err() + { + // VRF signature cannot be validated using key and transcript + return None; + } + Some(PreDigest { + vrf_output: VRFOutput(signature.output), + vrf_proof: VRFProof(signature.proof), + }) + } else { + // VRF key not found in keystore or VRF signing failed + None + } +} diff --git a/node/Cargo.toml b/node/Cargo.toml index a66b5e24b..6b4a288b8 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -63,18 +63,18 @@ cumulus-relay-chain-rpc-interface = { branch = "moonbeam-polkadot-v0.9.29", git # Parachain -moonbeam-vrf = { tag = "v0.27.2-a", git = "https://github.com/zeitgeistpm/moonbeam", optional = true } -nimbus-consensus = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -nimbus-primitives = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-author-inherent = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-parachain-staking = { tag = "v0.27.2-a", git = "https://github.com/zeitgeistpm/moonbeam", optional = true } +moonbeam-vrf = { path = "../external/vrf", optional = true } +nimbus-primitives = { default-features = false, path = "../external/nimbus-primitives", optional = true } +nimbus-consensus = { default-features = false, path = "../external/nimbus-consensus", optional = true } +pallet-author-inherent = { default-features = false, path = "../external/pallets/author-inherent", optional = true } +pallet-parachain-staking = { default-features = false, path = "../external/pallets/parachain-staking", optional = true } parity-scale-codec = { optional = true, version = "3.0.0" } sc-chain-spec = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } sc-network = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } sc-network-common = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } sc-tracing = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } serde = { features = ["derive"], optional = true, version = "1.0.144" } -session-keys-primitives = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } +session-keys-primitives = { default-features = false, path = "../external/session-keys", optional = true } sp-keystore = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } substrate-prometheus-endpoint = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } diff --git a/runtime/battery-station/Cargo.toml b/runtime/battery-station/Cargo.toml index 5748d0ff0..7576c8f15 100644 --- a/runtime/battery-station/Cargo.toml +++ b/runtime/battery-station/Cargo.toml @@ -63,13 +63,13 @@ cumulus-primitives-utility = { branch = "moonbeam-polkadot-v0.9.29", default-fea parachain-info = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } # Parachain +nimbus-primitives = { default-features = false, path = "../../external/nimbus-primitives", optional = true } +pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } +pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } +pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } +pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } +session-keys-primitives = { default-features = false, path = "../../external/session-keys", optional = true } -nimbus-primitives = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-author-inherent = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-author-mapping = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } -pallet-author-slot-filter = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-parachain-staking = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } -session-keys-primitives = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } # Polkadot diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index fae491e83..25402a32c 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -5,9 +5,9 @@ frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -pallet-author-inherent = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-author-mapping = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } -pallet-author-slot-filter = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } +pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } +pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } +pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } pallet-bounties = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } pallet-collective = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } @@ -15,7 +15,7 @@ pallet-democracy = { branch = "moonbeam-polkadot-v0.9.29", default-features = fa pallet-identity = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } pallet-membership = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } pallet-multisig = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-parachain-staking = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } +pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } pallet-preimage = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } pallet-proxy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } pallet-randomness-collective-flip = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 58707f793..78f0d557d 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -438,7 +438,7 @@ macro_rules! impl_config_traits { type AccountLookup = AuthorMapping; type CanAuthor = AuthorFilter; type SlotBeacon = cumulus_pallet_parachain_system::RelaychainBlockNumberProvider; - type WeightInfo = weights::pallet_author_inherent::WeightInfo; + type WeightInfo = pallet_author_inherent::weights::SubstrateWeight; } #[cfg(feature = "parachain")] @@ -447,7 +447,7 @@ macro_rules! impl_config_traits { type DepositCurrency = Balances; type Event = Event; type Keys = session_keys_primitives::VrfId; - type WeightInfo = weights::pallet_author_mapping::WeightInfo; + type WeightInfo = pallet_author_mapping::weights::SubstrateWeight; } #[cfg(feature = "parachain")] @@ -455,7 +455,7 @@ macro_rules! impl_config_traits { type Event = Event; type RandomnessSource = RandomnessCollectiveFlip; type PotentialAuthors = ParachainStaking; - type WeightInfo = weights::pallet_author_slot_filter::WeightInfo; + type WeightInfo = pallet_author_slot_filter::weights::SubstrateWeight; } #[cfg(not(feature = "parachain"))] @@ -522,10 +522,11 @@ macro_rules! impl_config_traits { type MinSelectedCandidates = MinSelectedCandidates; type MonetaryGovernanceOrigin = EnsureRoot; type OnCollatorPayout = (); + type PayoutCollatorReward = (); type OnNewRound = (); type RevokeDelegationDelay = RevokeDelegationDelay; type RewardPaymentDelay = RewardPaymentDelay; - type WeightInfo = weights::pallet_parachain_staking::WeightInfo; + type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } #[cfg(feature = "parachain")] diff --git a/runtime/common/src/weights/mod.rs b/runtime/common/src/weights/mod.rs index 2a7825912..a7f1dec2c 100644 --- a/runtime/common/src/weights/mod.rs +++ b/runtime/common/src/weights/mod.rs @@ -18,10 +18,6 @@ cfg_if::cfg_if! { if #[cfg(feature = "parachain")] { pub mod cumulus_pallet_xcmp_queue; - pub mod pallet_author_inherent; - pub mod pallet_author_mapping; - pub mod pallet_author_slot_filter; - pub mod pallet_parachain_staking; } else { // Currently the benchmark does yield an invalid weight implementation // pub mod pallet_grandpa; diff --git a/runtime/zeitgeist/Cargo.toml b/runtime/zeitgeist/Cargo.toml index fd63175bf..ceac1d737 100644 --- a/runtime/zeitgeist/Cargo.toml +++ b/runtime/zeitgeist/Cargo.toml @@ -62,12 +62,12 @@ parachain-info = { branch = "moonbeam-polkadot-v0.9.29", default-features = fals # Parachain -nimbus-primitives = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-author-inherent = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-author-mapping = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } -pallet-author-slot-filter = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/nimbus", optional = true } -pallet-parachain-staking = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } -session-keys-primitives = { tag = "v0.27.2-a", default-features = false, git = "https://github.com/zeitgeistpm/moonbeam", optional = true } +nimbus-primitives = { default-features = false, path = "../../external/nimbus-primitives", optional = true } +pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } +pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } +pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } +pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } +session-keys-primitives = { default-features = false, path = "../../external/session-keys", optional = true } # Polkadot From 04afbe6330879cd03973ee2781d3cf5c96a2c7f6 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Tue, 7 Feb 2023 14:16:04 +0530 Subject: [PATCH 02/22] Use all polkadot related dependencies from paritytech github. Make things compile with polkadot v0.9.32. Please note that certain things are just commneted out and will be fixed/improved in upcoming commits. --- Cargo.lock | 1981 +++++++++-------- external/nimbus-consensus/Cargo.toml | 34 +- external/nimbus-primitives/Cargo.toml | 16 +- external/nimbus-primitives/src/inherents.rs | 2 +- external/pallets/author-inherent/Cargo.toml | 24 +- external/pallets/author-inherent/src/lib.rs | 2 +- external/pallets/author-mapping/Cargo.toml | 16 +- external/pallets/author-mapping/src/lib.rs | 2 +- .../pallets/author-slot-filter/Cargo.toml | 16 +- .../author-slot-filter/src/benchmarks.rs | 4 +- .../pallets/author-slot-filter/src/lib.rs | 2 +- external/pallets/parachain-staking/Cargo.toml | 16 +- external/pallets/parachain-staking/src/lib.rs | 8 +- external/session-keys/Cargo.toml | 20 +- external/session-keys/src/inherent.rs | 2 +- external/vrf/Cargo.toml | 14 +- node/Cargo.toml | 125 +- node/src/benchmarking.rs | 4 +- node/src/cli.rs | 36 +- node/src/command.rs | 6 + node/src/service/service_parachain.rs | 5 +- node/src/service/service_standalone.rs | 20 +- primitives/Cargo.toml | 14 +- runtime/battery-station/Cargo.toml | 133 +- .../src/integration_tests/xcm/setup.rs | 8 +- .../src/integration_tests/xcm/test_net.rs | 6 +- .../integration_tests/xcm/tests/transfers.rs | 10 +- runtime/battery-station/src/lib.rs | 14 +- .../battery-station/src/parachain_params.rs | 4 +- runtime/battery-station/src/parameters.rs | 3 + .../battery-station/src/xcm_config/config.rs | 22 +- runtime/common/Cargo.toml | 44 +- runtime/common/src/lib.rs | 187 +- runtime/common/src/weights/mod.rs | 8 +- runtime/zeitgeist/Cargo.toml | 131 +- .../src/integration_tests/xcm/setup.rs | 8 +- .../src/integration_tests/xcm/test_net.rs | 6 +- .../integration_tests/xcm/tests/transfers.rs | 10 +- runtime/zeitgeist/src/lib.rs | 26 +- runtime/zeitgeist/src/parachain_params.rs | 4 +- runtime/zeitgeist/src/parameters.rs | 3 + runtime/zeitgeist/src/xcm_config/config.rs | 22 +- zrml/authorized/Cargo.toml | 14 +- zrml/authorized/src/lib.rs | 6 +- zrml/authorized/src/mock.rs | 10 +- zrml/authorized/src/tests.rs | 30 +- zrml/court/Cargo.toml | 16 +- zrml/court/src/lib.rs | 4 +- zrml/court/src/mock.rs | 10 +- zrml/court/src/tests.rs | 90 +- zrml/global-disputes/Cargo.toml | 16 +- zrml/global-disputes/src/benchmarks.rs | 2 +- zrml/global-disputes/src/lib.rs | 2 +- zrml/global-disputes/src/mock.rs | 10 +- zrml/global-disputes/src/tests.rs | 152 +- zrml/liquidity-mining/Cargo.toml | 14 +- zrml/liquidity-mining/src/lib.rs | 2 +- zrml/liquidity-mining/src/mock.rs | 10 +- zrml/liquidity-mining/src/tests.rs | 4 +- zrml/market-commons/Cargo.toml | 14 +- zrml/market-commons/src/mock.rs | 8 +- zrml/orderbook-v1/Cargo.toml | 16 +- zrml/orderbook-v1/fuzz/Cargo.toml | 2 +- .../fuzz/orderbook_v1_full_workflow.rs | 12 +- zrml/orderbook-v1/src/lib.rs | 2 +- zrml/orderbook-v1/src/mock.rs | 16 +- zrml/orderbook-v1/src/tests.rs | 14 +- zrml/prediction-markets/Cargo.toml | 32 +- zrml/prediction-markets/fuzz/Cargo.toml | 2 +- .../fuzz/pm_full_workflow.rs | 12 +- .../prediction-markets/runtime-api/Cargo.toml | 2 +- zrml/prediction-markets/src/benchmarks.rs | 2 +- zrml/prediction-markets/src/lib.rs | 23 +- zrml/prediction-markets/src/migrations.rs | 38 +- zrml/prediction-markets/src/mock.rs | 34 +- zrml/prediction-markets/src/tests.rs | 532 ++--- zrml/rikiddo/Cargo.toml | 14 +- zrml/rikiddo/fuzz/Cargo.toml | 4 +- zrml/rikiddo/src/mock.rs | 10 +- zrml/simple-disputes/Cargo.toml | 14 +- zrml/simple-disputes/src/lib.rs | 4 +- zrml/simple-disputes/src/mock.rs | 10 +- zrml/styx/Cargo.toml | 14 +- zrml/styx/src/lib.rs | 4 +- zrml/styx/src/mock.rs | 10 +- zrml/styx/src/tests.rs | 16 +- zrml/swaps/Cargo.toml | 22 +- zrml/swaps/fuzz/Cargo.toml | 6 +- zrml/swaps/fuzz/pool_exit.rs | 4 +- .../fuzz/pool_exit_with_exact_asset_amount.rs | 4 +- .../fuzz/pool_exit_with_exact_pool_amount.rs | 4 +- zrml/swaps/fuzz/pool_join.rs | 4 +- .../fuzz/pool_join_with_exact_asset_amount.rs | 4 +- .../fuzz/pool_join_with_exact_pool_amount.rs | 4 +- zrml/swaps/fuzz/swap_exact_amount_in.rs | 4 +- zrml/swaps/fuzz/swap_exact_amount_out.rs | 4 +- zrml/swaps/rpc/Cargo.toml | 6 +- zrml/swaps/runtime-api/Cargo.toml | 4 +- zrml/swaps/src/benchmarks.rs | 2 +- zrml/swaps/src/lib.rs | 4 +- zrml/swaps/src/mock.rs | 18 +- zrml/swaps/src/tests.rs | 74 +- 102 files changed, 2291 insertions(+), 2148 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9ec0ff78..e911c2518 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if 1.0.0", - "cipher 0.3.0", + "cipher", "cpufeatures", "opaque-debug 0.3.0", ] @@ -65,7 +65,7 @@ checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" dependencies = [ "aead", "aes", - "cipher 0.3.0", + "cipher", "ctr", "ghash", "subtle", @@ -139,6 +139,12 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "array-bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" + [[package]] name = "arrayref" version = "0.3.6" @@ -306,9 +312,9 @@ dependencies = [ [[package]] name = "async-std-resolver" -version = "0.21.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2f8a4a203be3325981310ab243a28e6e4ea55b6519bffce05d41ab60e09ad8" +checksum = "6ba50e24d9ee0a8950d3d03fc6d0dd10aa14b5de3b101949b4e160f7fee7c723" dependencies = [ "async-std", "async-trait", @@ -431,6 +437,12 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + [[package]] name = "basic-toml" version = "0.1.1" @@ -514,6 +526,7 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", + "sp-std", "sp-transaction-pool", "sp-version", "substrate-fixed", @@ -549,14 +562,14 @@ dependencies = [ [[package]] name = "beefy-gadget" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "async-trait", "beefy-primitives", "fnv", "futures 0.3.25", "futures-timer", - "hex", "log", "parity-scale-codec", "parking_lot 0.12.1", @@ -566,6 +579,7 @@ dependencies = [ "sc-finality-grandpa", "sc-keystore", "sc-network", + "sc-network-common", "sc-network-gossip", "sc-utils", "sp-api", @@ -585,7 +599,7 @@ dependencies = [ [[package]] name = "beefy-gadget-rpc" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "beefy-gadget", "beefy-primitives", @@ -605,32 +619,30 @@ dependencies = [ [[package]] name = "beefy-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "beefy-primitives", "sp-api", + "sp-runtime", ] [[package]] name = "beefy-primitives" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", + "serde", "sp-api", "sp-application-crypto", "sp-core", + "sp-io", + "sp-mmr-primitives", "sp-runtime", "sp-std", ] -[[package]] -name = "bimap" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0455254eb5c6964c4545d8bac815e1a1be4f3afe0ae695ea539c12d728d44b" - [[package]] name = "bincode" version = "1.3.3" @@ -642,9 +654,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.59.2" +version = "0.60.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" dependencies = [ "bitflags", "cexpr", @@ -960,7 +972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" dependencies = [ "cfg-if 1.0.0", - "cipher 0.3.0", + "cipher", "cpufeatures", "zeroize", ] @@ -973,7 +985,7 @@ checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" dependencies = [ "aead", "chacha20", - "cipher 0.3.0", + "cipher", "poly1305", "zeroize", ] @@ -1015,16 +1027,6 @@ dependencies = [ "generic-array 0.14.6", ] -[[package]] -name = "cipher" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "ckb-merkle-mountain-range" version = "0.3.2" @@ -1042,31 +1044,29 @@ checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", - "libloading 0.7.4", + "libloading", ] [[package]] name = "clap" -version = "3.2.23" +version = "4.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" dependencies = [ - "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap", + "is-terminal", "once_cell", "strsim", "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.18" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" dependencies = [ "heck", "proc-macro-error", @@ -1077,22 +1077,13 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" dependencies = [ "os_str_bytes", ] -[[package]] -name = "cmake" -version = "0.1.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" -dependencies = [ - "cc", -] - [[package]] name = "coarsetime" version = "0.1.22" @@ -1186,7 +1177,7 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1258,19 +1249,21 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749d0d6022c9038dccf480bdde2a38d435937335bf2bb0f14e815d94517cdce8" +checksum = "52056f6d0584484b57fa6c1a65c1fcb15f3780d8b6a758426d9e3084169b2ddd" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94370cc7b37bf652ccd8bb8f09bd900997f7ccf97520edfc75554bb5c4abbea" +checksum = "18fed94c8770dc25d01154c3ffa64ed0b3ba9d583736f305fed7beebe5d9cf74" dependencies = [ + "arrayvec 0.7.2", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", @@ -1285,33 +1278,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a3cea8fdab90e44018c5b9a1dfd460d8ee265ac354337150222a354628bdb6" +checksum = "1c451b81faf237d11c7e4f3165eeb6bac61112762c5cfe7b4c0fb7241474358f" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac72f76f2698598951ab26d8c96eaa854810e693e7dd52523958b5909fde6b2" +checksum = "e7c940133198426d26128f08be2b40b0bd117b84771fd36798969c4d712d81fc" [[package]] name = "cranelift-entity" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09eaeacfcd2356fe0e66b295e8f9d59fdd1ac3ace53ba50de14d628ec902f72d" +checksum = "87a0f1b2fdc18776956370cf8d9b009ded3f855350c480c1c52142510961f352" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba69c9980d5ffd62c18a2bde927855fcd7c8dc92f29feaf8636052662cbd99c" +checksum = "34897538b36b216cc8dd324e73263596d51b8cf610da6498322838b2546baf8a" dependencies = [ "cranelift-codegen", "log", @@ -1321,15 +1314,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2920dc1e05cac40304456ed3301fde2c09bd6a9b0210bcfa2f101398d628d5b" +checksum = "1b2629a569fae540f16a76b70afcc87ad7decb38dc28fa6c648ac73b51e78470" [[package]] name = "cranelift-native" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04dfa45f9b2a6f587c564d6b63388e00cd6589d2df6ea2758cf79e1a13285e6" +checksum = "20937dab4e14d3e225c5adfc9c7106bafd4ac669bdb43027b911ff794c6fb318" dependencies = [ "cranelift-codegen", "libc", @@ -1338,9 +1331,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.85.3" +version = "0.88.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31a46513ae6f26f3f267d8d75b5373d555fbbd1e68681f348d99df43f747ec54" +checksum = "80fc2288957a94fd342a015811479de1837850924166d1f1856d8406e6f3609b" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1478,24 +1471,13 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "cuckoofilter" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" -dependencies = [ - "byteorder", - "fnv", - "rand 0.7.3", + "cipher", ] [[package]] name = "cumulus-client-cli" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "clap", "parity-scale-codec", @@ -1510,12 +1492,11 @@ dependencies = [ [[package]] name = "cumulus-client-collator" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", "cumulus-primitives-core", - "cumulus-relay-chain-interface", "futures 0.3.25", "parity-scale-codec", "parking_lot 0.12.1", @@ -1534,7 +1515,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -1544,7 +1525,6 @@ dependencies = [ "polkadot-primitives", "sc-client-api", "sc-consensus", - "sp-api", "sp-blockchain", "sp-consensus", "sp-runtime", @@ -1555,7 +1535,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-relay-chain" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -1563,7 +1543,6 @@ dependencies = [ "cumulus-relay-chain-interface", "futures 0.3.25", "parking_lot 0.12.1", - "sc-client-api", "sc-consensus", "sp-api", "sp-block-builder", @@ -1579,11 +1558,10 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "cumulus-relay-chain-interface", - "derive_more", "futures 0.3.25", "futures-timer", "parity-scale-codec", @@ -1592,7 +1570,6 @@ dependencies = [ "polkadot-parachain", "polkadot-primitives", "sc-client-api", - "sp-api", "sp-blockchain", "sp-consensus", "sp-core", @@ -1604,7 +1581,7 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", @@ -1618,7 +1595,6 @@ dependencies = [ "rand 0.8.5", "sc-client-api", "sc-consensus", - "sp-api", "sp-consensus", "sp-maybe-compressed-blob", "sp-runtime", @@ -1628,7 +1604,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-client-cli", "cumulus-client-collator", @@ -1637,26 +1613,21 @@ dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", "parking_lot 0.12.1", - "polkadot-overseer", "polkadot-primitives", "sc-client-api", "sc-consensus", - "sc-consensus-babe", "sc-service", - "sc-telemetry", - "sc-tracing", "sp-api", "sp-blockchain", "sp-consensus", "sp-core", "sp-runtime", - "tracing", ] [[package]] name = "cumulus-pallet-dmp-queue" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1668,13 +1639,12 @@ dependencies = [ "sp-runtime", "sp-std", "xcm", - "xcm-executor", ] [[package]] name = "cumulus-pallet-parachain-system" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -1685,11 +1655,9 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log", - "pallet-balances", "parity-scale-codec", "polkadot-parachain", "scale-info", - "serde", "sp-core", "sp-externalities", "sp-inherents", @@ -1699,13 +1667,12 @@ dependencies = [ "sp-std", "sp-trie", "sp-version", - "xcm", ] [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1716,14 +1683,13 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "frame-support", "frame-system", "parity-scale-codec", "scale-info", - "serde", "sp-io", "sp-runtime", "sp-std", @@ -1733,7 +1699,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -1752,9 +1718,8 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ - "frame-support", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", @@ -1768,7 +1733,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1791,7 +1756,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-timestamp" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "futures 0.3.25", @@ -1804,18 +1769,14 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "frame-support", "log", "parity-scale-codec", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-primitives", "sp-runtime", "sp-std", - "sp-trie", "xcm", "xcm-builder", "xcm-executor", @@ -1824,7 +1785,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1836,39 +1797,31 @@ dependencies = [ "polkadot-service", "sc-cli", "sc-client-api", - "sc-consensus-babe", - "sc-network", "sc-sysinfo", "sc-telemetry", "sc-tracing", "sp-api", - "sp-blockchain", "sp-consensus", "sp-core", "sp-runtime", "sp-state-machine", - "tracing", ] [[package]] name = "cumulus-relay-chain-interface" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "cumulus-primitives-core", - "derive_more", "futures 0.3.25", "jsonrpsee-core", "parity-scale-codec", - "parking_lot 0.12.1", "polkadot-overseer", "polkadot-service", "sc-client-api", "sp-api", "sp-blockchain", - "sp-core", - "sp-runtime", "sp-state-machine", "thiserror", ] @@ -1876,7 +1829,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-rpc-interface" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "async-trait", "backoff", @@ -1886,11 +1839,12 @@ dependencies = [ "futures-timer", "jsonrpsee", "parity-scale-codec", - "parking_lot 0.12.1", "polkadot-service", "sc-client-api", "sc-rpc-api", "sp-api", + "sp-authority-discovery", + "sp-consensus-babe", "sp-core", "sp-runtime", "sp-state-machine", @@ -1903,7 +1857,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -2073,6 +2027,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.8.1" @@ -2159,6 +2119,12 @@ dependencies = [ "quick-error", ] +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + [[package]] name = "downcast-rs" version = "1.2.0" @@ -2279,9 +2245,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "enum-as-inner" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ "heck", "proc-macro2", @@ -2503,7 +2469,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2524,9 +2490,9 @@ dependencies = [ [[package]] name = "fixed-hash" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", "rand 0.8.5", @@ -2551,6 +2517,15 @@ dependencies = [ "miniz_oxide 0.5.4", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2560,7 +2535,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", ] @@ -2574,10 +2549,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -2600,9 +2581,10 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "Inflector", + "array-bytes", "chrono", "clap", "comfy-table", @@ -2612,7 +2594,6 @@ dependencies = [ "gethostname", "handlebars", "hash-db", - "hex", "itertools", "kvdb", "lazy_static", @@ -2651,7 +2632,7 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2662,7 +2643,7 @@ dependencies = [ [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -2678,7 +2659,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -2707,7 +2688,7 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "bitflags", "frame-metadata", @@ -2732,13 +2713,14 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-tracing", + "sp-weights", "tt-call", ] [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "Inflector", "cfg-expr", @@ -2752,7 +2734,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -2764,7 +2746,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro2", "quote", @@ -2774,7 +2756,7 @@ dependencies = [ [[package]] name = "frame-support-test" version = "3.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-support-test-pallet", @@ -2797,7 +2779,7 @@ dependencies = [ [[package]] name = "frame-support-test-pallet" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -2808,7 +2790,7 @@ dependencies = [ [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "log", @@ -2820,12 +2802,13 @@ dependencies = [ "sp-runtime", "sp-std", "sp-version", + "sp-weights", ] [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -2840,7 +2823,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "sp-api", @@ -2849,7 +2832,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "parity-scale-codec", @@ -2864,18 +2847,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" -[[package]] -name = "fs-swap" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d47dad3685eceed8488986cad3d5027165ea5edb164331770e2059555f10a5" -dependencies = [ - "lazy_static", - "libc", - "libloading 0.5.2", - "winapi", -] - [[package]] name = "fs2" version = "0.4.3" @@ -3260,12 +3231,6 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" -[[package]] -name = "hex_fmt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" - [[package]] name = "hmac" version = "0.8.1" @@ -3444,9 +3409,9 @@ dependencies = [ [[package]] name = "if-watch" -version = "1.1.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015a7df1eb6dda30df37f34b63ada9b7b352984b0e84de2a20ed526345000791" +checksum = "065c008e570a43c00de6aed9714035e5ea6a498c255323db9091722af6ee67dd" dependencies = [ "async-io", "core-foundation", @@ -3471,9 +3436,9 @@ dependencies = [ [[package]] name = "impl-serde" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" dependencies = [ "serde", ] @@ -3500,15 +3465,6 @@ dependencies = [ "serde", ] -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array 0.14.6", -] - [[package]] name = "instant" version = "0.1.12" @@ -3533,12 +3489,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "io-lifetimes" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec58677acfea8a15352d42fc87d11d63596ade9239e0a7c9352914417515dbe6" - [[package]] name = "io-lifetimes" version = "0.7.5" @@ -3552,7 +3502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3588,7 +3538,7 @@ dependencies = [ "hermit-abi 0.2.6", "io-lifetimes 1.0.4", "rustix 0.36.7", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3791,8 +3741,8 @@ dependencies = [ [[package]] name = "kusama-runtime" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-primitives", "bitvec", @@ -3815,10 +3765,12 @@ dependencies = [ "pallet-bounties", "pallet-child-bounties", "pallet-collective", + "pallet-conviction-voting", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", + "pallet-fast-unstake", "pallet-gilt", "pallet-grandpa", "pallet-identity", @@ -3833,7 +3785,9 @@ dependencies = [ "pallet-offences-benchmarking", "pallet-preimage", "pallet-proxy", + "pallet-ranked-collective", "pallet-recovery", + "pallet-referenda", "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", @@ -3847,6 +3801,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", + "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "parity-scale-codec", @@ -3884,14 +3839,16 @@ dependencies = [ [[package]] name = "kusama-runtime-constants" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "polkadot-primitives", "polkadot-runtime-common", "smallvec", + "sp-core", "sp-runtime", + "sp-weights", ] [[package]] @@ -3905,9 +3862,9 @@ dependencies = [ [[package]] name = "kvdb" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a301d8ecb7989d4a6e2c57a49baca77d353bdbf879909debe3f375fe25d61f86" +checksum = "585089ceadba0197ffe9af6740ab350b325e3c1f5fccfbc3522e0250c750409b" dependencies = [ "parity-util-mem", "smallvec", @@ -3915,9 +3872,9 @@ dependencies = [ [[package]] name = "kvdb-memorydb" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece7e668abd21387aeb6628130a6f4c802787f014fa46bc83221448322250357" +checksum = "40d109c87bfb7759edd2a49b2649c1afe25af785d930ad6a38479b4dc70dd873" dependencies = [ "kvdb", "parity-util-mem", @@ -3926,15 +3883,13 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca7fbdfd71cd663dceb0faf3367a99f8cf724514933e9867cec4995b6027cbc1" +checksum = "c076cc2cdbac89b9910c853a36c957d3862a779f31c2661174222cefb49ee597" dependencies = [ - "fs-swap", "kvdb", "log", "num_cpus", - "owning_ref", "parity-util-mem", "parking_lot 0.12.1", "regex", @@ -3971,16 +3926,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "libloading" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" -dependencies = [ - "cc", - "winapi", -] - [[package]] name = "libloading" version = "0.7.4" @@ -4005,9 +3950,9 @@ checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libp2p" -version = "0.46.1" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81327106887e42d004fbdab1fef93675be2e2e07c1b95fce45e2cc813485611d" +checksum = "ec878fda12ebec479186b3914ebc48ff180fa4c51847e11a1a68bf65249e02c1" dependencies = [ "bytes", "futures 0.3.25", @@ -4015,12 +3960,8 @@ dependencies = [ "getrandom 0.2.8", "instant", "lazy_static", - "libp2p-autonat", "libp2p-core", - "libp2p-deflate", "libp2p-dns", - "libp2p-floodsub", - "libp2p-gossipsub", "libp2p-identify", "libp2p-kad", "libp2p-mdns", @@ -4028,49 +3969,24 @@ dependencies = [ "libp2p-mplex", "libp2p-noise", "libp2p-ping", - "libp2p-plaintext", - "libp2p-pnet", - "libp2p-relay", - "libp2p-rendezvous", "libp2p-request-response", "libp2p-swarm", "libp2p-swarm-derive", "libp2p-tcp", - "libp2p-uds", "libp2p-wasm-ext", "libp2p-websocket", "libp2p-yamux", "multiaddr", "parking_lot 0.12.1", "pin-project", - "rand 0.7.3", "smallvec", ] -[[package]] -name = "libp2p-autonat" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4decc51f3573653a9f4ecacb31b1b922dd20c25a6322bb15318ec04287ec46f9" -dependencies = [ - "async-trait", - "futures 0.3.25", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-request-response", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.8.5", -] - [[package]] name = "libp2p-core" -version = "0.34.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf9b94cefab7599b2d3dff2f93bee218c6621d68590b23ede4485813cbcece6" +checksum = "799676bb0807c788065e57551c6527d461ad572162b0519d1958946ff9e0539d" dependencies = [ "asn1_der", "bs58", @@ -4081,7 +3997,6 @@ dependencies = [ "futures-timer", "instant", "lazy_static", - "libsecp256k1", "log", "multiaddr", "multihash", @@ -4091,7 +4006,6 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "ring", "rw-stream-sink", "sha2 0.10.6", "smallvec", @@ -4101,22 +4015,11 @@ dependencies = [ "zeroize", ] -[[package]] -name = "libp2p-deflate" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0183dc2a3da1fbbf85e5b6cf51217f55b14f5daea0c455a9536eef646bfec71" -dependencies = [ - "flate2", - "futures 0.3.25", - "libp2p-core", -] - [[package]] name = "libp2p-dns" -version = "0.34.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbf54723250fa5d521383be789bf60efdabe6bacfb443f87da261019a49b4b5" +checksum = "2322c9fb40d99101def6a01612ee30500c89abbbecb6297b3cd252903a4c1720" dependencies = [ "async-std-resolver", "futures 0.3.25", @@ -4127,57 +4030,11 @@ dependencies = [ "trust-dns-resolver", ] -[[package]] -name = "libp2p-floodsub" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a4b6ffd53e355775d24b76f583fdda54b3284806f678499b57913adb94f231" -dependencies = [ - "cuckoofilter", - "fnv", - "futures 0.3.25", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.7.3", - "smallvec", -] - -[[package]] -name = "libp2p-gossipsub" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b4b888cfbeb1f5551acd3aa1366e01bf88ede26cc3c4645d0d2d004d5ca7b0" -dependencies = [ - "asynchronous-codec", - "base64 0.13.1", - "byteorder", - "bytes", - "fnv", - "futures 0.3.25", - "hex_fmt", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prometheus-client", - "prost", - "prost-build", - "rand 0.7.3", - "regex", - "sha2 0.10.6", - "smallvec", - "unsigned-varint", - "wasm-timer", -] - [[package]] name = "libp2p-identify" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50b585518f8efd06f93ac2f976bd672e17cdac794644b3117edd078e96bda06" +checksum = "dcf9a121f699e8719bda2e6e9e9b6ddafc6cff4602471d6481c1067930ccb29b" dependencies = [ "asynchronous-codec", "futures 0.3.25", @@ -4185,7 +4042,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "lru 0.7.8", + "lru 0.8.1", "prost", "prost-build", "prost-codec", @@ -4196,9 +4053,9 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.38.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740862893bb5f06ac24acc9d49bdeadc3a5e52e51818a30a25c1f3519da2c851" +checksum = "6721c200e2021f6c3fab8b6cf0272ead8912d871610ee194ebd628cecf428f22" dependencies = [ "arrayvec 0.7.2", "asynchronous-codec", @@ -4213,7 +4070,7 @@ dependencies = [ "log", "prost", "prost-build", - "rand 0.7.3", + "rand 0.8.5", "sha2 0.10.6", "smallvec", "thiserror", @@ -4224,16 +4081,15 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.38.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66e5e5919509603281033fd16306c61df7a4428ce274b67af5e14b07de5cdcb2" +checksum = "761704e727f7d68d58d7bc2231eafae5fc1b9814de24290f126df09d4bd37a15" dependencies = [ "async-io", "data-encoding", "dns-parser", "futures 0.3.25", "if-watch", - "lazy_static", "libp2p-core", "libp2p-swarm", "log", @@ -4245,25 +4101,23 @@ dependencies = [ [[package]] name = "libp2p-metrics" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8aff4a1abef42328fbb30b17c853fff9be986dc39af17ee39f9c5f755c5e0c" +checksum = "9ee31b08e78b7b8bfd1c4204a9dd8a87b4fcdf6dafc57eb51701c1c264a81cb9" dependencies = [ "libp2p-core", - "libp2p-gossipsub", "libp2p-identify", "libp2p-kad", "libp2p-ping", - "libp2p-relay", "libp2p-swarm", "prometheus-client", ] [[package]] name = "libp2p-mplex" -version = "0.34.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61fd1b20638ec209c5075dfb2e8ce6a7ea4ec3cd3ad7b77f7a477c06d53322e2" +checksum = "692664acfd98652de739a8acbb0a0d670f1d67190a49be6b4395e22c37337d89" dependencies = [ "asynchronous-codec", "bytes", @@ -4272,16 +4126,16 @@ dependencies = [ "log", "nohash-hasher", "parking_lot 0.12.1", - "rand 0.7.3", + "rand 0.8.5", "smallvec", "unsigned-varint", ] [[package]] name = "libp2p-noise" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762408cb5d84b49a600422d7f9a42c18012d8da6ebcd570f9a4a4290ba41fb6f" +checksum = "048155686bd81fe6cb5efdef0c6290f25ad32a0a42e8f4f72625cf6a505a206f" dependencies = [ "bytes", "curve25519-dalek 3.2.0", @@ -4301,105 +4155,25 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "100a6934ae1dbf8a693a4e7dd1d730fd60b774dafc45688ed63b554497c6c925" -dependencies = [ - "futures 0.3.25", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.7.3", - "void", -] - -[[package]] -name = "libp2p-plaintext" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be27bf0820a6238a4e06365b096d428271cce85a129cf16f2fe9eb1610c4df86" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures 0.3.25", - "libp2p-core", - "log", - "prost", - "prost-build", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-pnet" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5a702574223aa55d8878bdc8bf55c84a6086f87ddaddc28ce730b4caa81538" -dependencies = [ - "futures 0.3.25", - "log", - "pin-project", - "rand 0.8.5", - "salsa20", - "sha3", -] - -[[package]] -name = "libp2p-relay" -version = "0.10.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4931547ee0cce03971ccc1733ff05bb0c4349fd89120a39e9861e2bbe18843c3" +checksum = "7228b9318d34689521349a86eb39a3c3a802c9efc99a0568062ffb80913e3f91" dependencies = [ - "asynchronous-codec", - "bytes", - "either", "futures 0.3.25", "futures-timer", "instant", "libp2p-core", "libp2p-swarm", "log", - "pin-project", - "prost", - "prost-build", - "prost-codec", "rand 0.8.5", - "smallvec", - "static_assertions", - "thiserror", - "void", -] - -[[package]] -name = "libp2p-rendezvous" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9511c9672ba33284838e349623319c8cad2d18cfad243ae46c6b7e8a2982ea4e" -dependencies = [ - "asynchronous-codec", - "bimap", - "futures 0.3.25", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.8.5", - "sha2 0.10.6", - "thiserror", - "unsigned-varint", "void", ] [[package]] name = "libp2p-request-response" -version = "0.19.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508a189e2795d892c8f5c1fa1e9e0b1845d32d7b0b249dbf7b05b18811361843" +checksum = "8827af16a017b65311a410bb626205a9ad92ec0473967618425039fa5231adc1" dependencies = [ "async-trait", "bytes", @@ -4408,16 +4182,16 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "rand 0.7.3", + "rand 0.8.5", "smallvec", "unsigned-varint", ] [[package]] name = "libp2p-swarm" -version = "0.37.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ac5be6c2de2d1ff3f7693fda6faf8a827b1f3e808202277783fea9f527d114" +checksum = "46d13df7c37807965d82930c0e4b04a659efcb6cca237373b206043db5398ecf" dependencies = [ "either", "fnv", @@ -4427,7 +4201,7 @@ dependencies = [ "libp2p-core", "log", "pin-project", - "rand 0.7.3", + "rand 0.8.5", "smallvec", "thiserror", "void", @@ -4435,48 +4209,36 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.28.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f54a64b6957249e0ce782f8abf41d97f69330d02bf229f0672d864f0650cc76" +checksum = "a0eddc4497a8b5a506013c40e8189864f9c3a00db2b25671f428ae9007f3ba32" dependencies = [ + "heck", "quote", "syn", ] [[package]] name = "libp2p-tcp" -version = "0.34.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6771dc19aa3c65d6af9a8c65222bfc8fcd446630ddca487acd161fa6096f3b" +checksum = "9839d96761491c6d3e238e70554b856956fca0ab60feb9de2cd08eed4473fa92" dependencies = [ "async-io", "futures 0.3.25", "futures-timer", "if-watch", - "ipnet", "libc", "libp2p-core", "log", "socket2", ] -[[package]] -name = "libp2p-uds" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d125e3e5f0d58f3c6ac21815b20cf4b6a88b8db9dc26368ea821838f4161fd4d" -dependencies = [ - "async-std", - "futures 0.3.25", - "libp2p-core", - "log", -] - [[package]] name = "libp2p-wasm-ext" -version = "0.34.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec894790eec3c1608f8d1a8a0bdf0dbeb79ed4de2dce964222011c2896dfa05a" +checksum = "a17b5b8e7a73e379e47b1b77f8a82c4721e97eca01abcd18e9cd91a23ca6ce97" dependencies = [ "futures 0.3.25", "js-sys", @@ -4488,9 +4250,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.36.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9808e57e81be76ff841c106b4c5974fb4d41a233a7bdd2afbf1687ac6def3818" +checksum = "3758ae6f89b2531a24b6d9f5776bda6a626b60a57600d7185d43dfa75ca5ecc4" dependencies = [ "either", "futures 0.3.25", @@ -4507,12 +4269,13 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.38.0" +version = "0.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6dea686217a06072033dc025631932810e2f6ad784e4fafa42e27d311c7a81c" +checksum = "0d6874d66543c4f7e26e3b8ca9a6bead351563a13ab4fafd43c7927f7c0d6c12" dependencies = [ "futures 0.3.25", "libp2p-core", + "log", "parking_lot 0.12.1", "thiserror", "yamux", @@ -4520,9 +4283,9 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "0.6.1+6.28.2" +version = "0.8.0+7.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc587013734dadb7cf23468e531aa120788b87243648be42e2d3a072186291" +checksum = "611804e4666a25136fcc5f8cf425ab4d26c7f74ea245ffe92ea23b85b6420b5d" dependencies = [ "bindgen", "bzip2-sys", @@ -4626,12 +4389,6 @@ dependencies = [ "statrs", ] -[[package]] -name = "linux-raw-sys" -version = "0.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" - [[package]] name = "linux-raw-sys" version = "0.0.46" @@ -4758,11 +4515,11 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memfd" -version = "0.4.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6627dc657574b49d6ad27105ed671822be56e0d2547d413bfbf3e8d8fa92e7a" +checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb" dependencies = [ - "libc", + "rustix 0.36.7", ] [[package]] @@ -4794,9 +4551,9 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" +checksum = "34ac11bb793c28fa095b7554466f53b3a60a2cd002afdac01bcf135cbd73a269" dependencies = [ "hash-db", "hashbrown 0.12.3", @@ -4814,9 +4571,9 @@ dependencies = [ [[package]] name = "memory_units" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] name = "merlin" @@ -4874,7 +4631,34 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.42.0", +] + +[[package]] +name = "mockall" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e4a1c770583dac7ab5e2f6c139153b783a53a1bbee9729613f193e59828326" +dependencies = [ + "cfg-if 1.0.0", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "832663583d5fa284ca8810bf7015e46c9fff9622d3cf34bd1eea5003fec06dd0" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -4967,9 +4751,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "multistream-select" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363a84be6453a70e63513660f4894ef815daf88e3356bffcda9ca27d810ce83b" +checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" dependencies = [ "bytes", "futures 0.3.25", @@ -5178,6 +4962,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "num-bigint" version = "0.2.6" @@ -5189,6 +4979,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.4.3" @@ -5225,7 +5026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ "autocfg", - "num-bigint", + "num-bigint 0.2.6", "num-integer", "num-traits", ] @@ -5237,6 +5038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", + "num-bigint 0.4.3", "num-integer", "num-traits", ] @@ -5263,12 +5065,12 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", - "hashbrown 0.11.2", + "hashbrown 0.12.3", "indexmap", "memchr", ] @@ -5308,8 +5110,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "orchestra" -version = "0.0.1" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aab54694ddaa8a9b703724c6ef04272b2d27bc32d2c855aae5cdd1857216b43" dependencies = [ "async-trait", "dyn-clonable", @@ -5324,8 +5127,9 @@ dependencies = [ [[package]] name = "orchestra-proc-macro" -version = "0.0.1" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a702b2f6bf592b3eb06c00d80d05afaf7a8eff6b41bb361e397d799acc21b45a" dependencies = [ "expander 0.0.6", "itertools", @@ -5348,7 +5152,7 @@ dependencies = [ [[package]] name = "orml-asset-registry" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "frame-system", @@ -5367,7 +5171,7 @@ dependencies = [ [[package]] name = "orml-benchmarking" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-benchmarking", "frame-support", @@ -5387,7 +5191,7 @@ dependencies = [ [[package]] name = "orml-currencies" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "frame-system", @@ -5404,7 +5208,7 @@ dependencies = [ [[package]] name = "orml-tokens" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "frame-system", @@ -5419,7 +5223,7 @@ dependencies = [ [[package]] name = "orml-traits" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -5437,7 +5241,7 @@ dependencies = [ [[package]] name = "orml-unknown-tokens" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "frame-system", @@ -5452,7 +5256,7 @@ dependencies = [ [[package]] name = "orml-utilities" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "parity-scale-codec", @@ -5466,7 +5270,7 @@ dependencies = [ [[package]] name = "orml-xcm-support" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "frame-support", "orml-traits", @@ -5480,7 +5284,7 @@ dependencies = [ [[package]] name = "orml-xtokens" version = "0.4.1-dev" -source = "git+https://github.com/zeitgeistpm/open-runtime-module-library?branch=moonbeam-polkadot-v0.9.29#d231a39d4583445d1af7326a9e6e78ba744ce6e9" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.32#f336875e48599b5e9500b301385259354821f01f" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -5513,15 +5317,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "owning_ref" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" -dependencies = [ - "stable_deref_trait", -] - [[package]] name = "packed_simd_2" version = "0.3.8" @@ -5535,7 +5330,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -5612,7 +5407,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -5628,7 +5423,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -5643,7 +5438,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5667,7 +5462,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5687,7 +5482,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5702,7 +5497,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "beefy-primitives", "frame-support", @@ -5718,13 +5513,13 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "beefy-merkle-tree", "beefy-primitives", "frame-support", "frame-system", - "hex", "log", "pallet-beefy", "pallet-mmr", @@ -5741,7 +5536,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5759,7 +5554,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5778,7 +5573,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5792,17 +5587,36 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-conviction-voting" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "assert_matches", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", "serde", + "sp-core", "sp-io", "sp-runtime", "sp-std", @@ -5811,13 +5625,14 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", "log", + "pallet-election-provider-support-benchmarking", "parity-scale-codec", "rand 0.7.3", "scale-info", @@ -5834,7 +5649,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5847,7 +5662,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5862,10 +5677,31 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-fast-unstake" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "pallet-staking", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-gilt" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5880,7 +5716,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5903,7 +5739,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "enumflags2", "frame-benchmarking", @@ -5919,7 +5755,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5939,7 +5775,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5956,7 +5792,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -5973,7 +5809,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ckb-merkle-mountain-range", "frame-benchmarking", @@ -5991,7 +5827,7 @@ dependencies = [ [[package]] name = "pallet-mmr-rpc" version = "3.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -6006,11 +5842,12 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", "sp-io", @@ -6021,7 +5858,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "1.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6038,7 +5875,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "1.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6050,6 +5887,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", + "sp-runtime-interface", "sp-staking", "sp-std", ] @@ -6057,7 +5895,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "1.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "sp-api", @@ -6067,7 +5905,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6084,7 +5922,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6128,11 +5966,12 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", "sp-core", @@ -6144,7 +5983,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6159,7 +5998,7 @@ dependencies = [ [[package]] name = "pallet-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6170,16 +6009,52 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-ranked-collective" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-recovery" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-referenda" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "assert_matches", "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", "scale-info", + "serde", + "sp-arithmetic", "sp-io", "sp-runtime", "sp-std", @@ -6188,7 +6063,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6204,7 +6079,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6225,7 +6100,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6241,7 +6116,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6255,7 +6130,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6278,7 +6153,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -6289,7 +6164,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "sp-arithmetic", @@ -6298,7 +6173,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6312,7 +6187,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6330,7 +6205,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6349,7 +6224,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-support", "frame-system", @@ -6365,7 +6240,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -6375,23 +6250,25 @@ dependencies = [ "sp-core", "sp-rpc", "sp-runtime", + "sp-weights", ] [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "sp-api", "sp-runtime", + "sp-weights", ] [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6408,7 +6285,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6424,7 +6301,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6436,10 +6313,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-whitelist" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-xcm" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "frame-system", @@ -6456,8 +6348,8 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-benchmarking", "frame-support", @@ -6474,14 +6366,13 @@ dependencies = [ [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/cumulus?branch=moonbeam-polkadot-v0.9.29#e4f9bb8949e12e174ec6350cef81e556a5c94b5f" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.32#6abd385ce49f7feb882218646410feb063404b77" dependencies = [ "cumulus-primitives-core", "frame-support", "frame-system", "parity-scale-codec", "scale-info", - "serde", ] [[package]] @@ -6538,9 +6429,9 @@ checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" [[package]] name = "parity-util-mem" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" +checksum = "0d32c34f4f5ca7f9196001c0aba5a1f9a5a12382c8944b8b0f90233282d1e8f8" dependencies = [ "cfg-if 1.0.0", "hashbrown 0.12.3", @@ -6574,9 +6465,9 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.42.2" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking" @@ -6629,7 +6520,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -6760,6 +6651,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.26" @@ -6780,8 +6682,8 @@ checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" [[package]] name = "polkadot-approval-distribution" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "polkadot-node-network-protocol", @@ -6795,8 +6697,8 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "polkadot-node-network-protocol", @@ -6809,13 +6711,13 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "derive_more", "fatality", "futures 0.3.25", - "lru 0.7.8", + "lru 0.8.1", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6832,12 +6734,12 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "fatality", "futures 0.3.25", - "lru 0.7.8", + "lru 0.8.1", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6853,8 +6755,8 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "clap", "frame-benchmarking-cli", @@ -6879,8 +6781,8 @@ dependencies = [ [[package]] name = "polkadot-client" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-primitives", "frame-benchmarking", @@ -6919,10 +6821,11 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "always-assert", + "bitvec", "fatality", "futures 0.3.25", "futures-timer", @@ -6940,8 +6843,8 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "parity-scale-codec", "parity-util-mem", @@ -6953,13 +6856,15 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "derive_more", "fatality", "futures 0.3.25", - "lru 0.7.8", + "futures-timer", + "indexmap", + "lru 0.8.1", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6976,8 +6881,8 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -6990,8 +6895,8 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "futures-timer", @@ -7010,8 +6915,8 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "always-assert", "async-trait", @@ -7034,8 +6939,8 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "parity-scale-codec", @@ -7052,15 +6957,15 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bitvec", "derive_more", "futures 0.3.25", "futures-timer", "kvdb", - "lru 0.7.8", + "lru 0.8.1", "merlin", "parity-scale-codec", "polkadot-node-jaeger", @@ -7081,8 +6986,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bitvec", "futures 0.3.25", @@ -7101,8 +7006,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bitvec", "fatality", @@ -7120,8 +7025,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "polkadot-node-subsystem", @@ -7135,8 +7040,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "futures 0.3.25", @@ -7153,8 +7058,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "polkadot-node-subsystem", @@ -7168,8 +7073,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "futures-timer", @@ -7185,13 +7090,13 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "fatality", "futures 0.3.25", "kvdb", - "lru 0.7.8", + "lru 0.8.1", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -7204,8 +7109,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "futures 0.3.25", @@ -7221,8 +7126,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bitvec", "fatality", @@ -7239,8 +7144,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "always-assert", "assert_matches", @@ -7251,7 +7156,7 @@ dependencies = [ "parity-scale-codec", "pin-project", "polkadot-core-primitives", - "polkadot-node-subsystem-util", + "polkadot-node-metrics", "polkadot-parachain", "rand 0.8.5", "rayon", @@ -7271,8 +7176,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "polkadot-node-primitives", @@ -7287,8 +7192,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "futures 0.3.25", "memory-lru", @@ -7303,8 +7208,8 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-std", "lazy_static", @@ -7321,8 +7226,8 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bs58", "futures 0.3.25", @@ -7340,8 +7245,8 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "derive_more", @@ -7355,6 +7260,7 @@ dependencies = [ "rand 0.8.5", "sc-authority-discovery", "sc-network", + "sc-network-common", "strum", "thiserror", "tracing-gum", @@ -7362,8 +7268,8 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bounded-vec", "futures 0.3.25", @@ -7384,8 +7290,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -7394,8 +7300,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "derive_more", @@ -7417,8 +7323,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "derive_more", @@ -7426,7 +7332,7 @@ dependencies = [ "futures 0.3.25", "itertools", "kvdb", - "lru 0.7.8", + "lru 0.8.1", "parity-db", "parity-scale-codec", "parity-util-mem", @@ -7450,13 +7356,13 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "futures 0.3.25", "futures-timer", - "lru 0.7.8", + "lru 0.8.1", "orchestra", "parity-util-mem", "parking_lot 0.12.1", @@ -7473,8 +7379,8 @@ dependencies = [ [[package]] name = "polkadot-parachain" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "derive_more", "frame-support", @@ -7490,8 +7396,8 @@ dependencies = [ [[package]] name = "polkadot-performance-test" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "env_logger 0.9.3", "kusama-runtime", @@ -7505,8 +7411,8 @@ dependencies = [ [[package]] name = "polkadot-primitives" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bitvec", "frame-system", @@ -7535,8 +7441,8 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-gadget", "beefy-gadget-rpc", @@ -7567,8 +7473,8 @@ dependencies = [ [[package]] name = "polkadot-runtime" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-primitives", "bitvec", @@ -7594,6 +7500,7 @@ dependencies = [ "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", + "pallet-fast-unstake", "pallet-grandpa", "pallet-identity", "pallet-im-online", @@ -7655,8 +7562,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-primitives", "bitvec", @@ -7702,20 +7609,22 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "polkadot-primitives", "polkadot-runtime-common", "smallvec", + "sp-core", "sp-runtime", + "sp-weights", ] [[package]] name = "polkadot-runtime-metrics" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bs58", "parity-scale-codec", @@ -7726,8 +7635,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "bitflags", "bitvec", @@ -7769,8 +7678,8 @@ dependencies = [ [[package]] name = "polkadot-service" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "async-trait", "beefy-gadget", @@ -7782,7 +7691,7 @@ dependencies = [ "kusama-runtime", "kvdb", "kvdb-rocksdb", - "lru 0.7.8", + "lru 0.8.1", "pallet-babe", "pallet-im-online", "pallet-staking", @@ -7873,8 +7782,8 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "arrayvec 0.5.2", "fatality", @@ -7894,8 +7803,8 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -7904,8 +7813,8 @@ dependencies = [ [[package]] name = "polkadot-test-runtime" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-primitives", "bitvec", @@ -7965,8 +7874,8 @@ dependencies = [ [[package]] name = "polkadot-test-service" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-benchmarking", "frame-system", @@ -8028,7 +7937,7 @@ dependencies = [ "libc", "log", "wepoll-ffi", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -8060,6 +7969,36 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "predicates" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +dependencies = [ + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2" + +[[package]] +name = "predicates-tree" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "pretty_assertions" version = "1.3.0" @@ -8072,11 +8011,21 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "primitive-types" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" dependencies = [ "fixed-hash", "impl-codec", @@ -8088,7 +8037,8 @@ dependencies = [ [[package]] name = "prioritized-metered-channel" version = "0.2.0" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382698e48a268c832d0b181ed438374a6bb708a82a8ca273bb0f61c74cf209c4" dependencies = [ "coarsetime", "crossbeam-queue", @@ -8159,21 +8109,21 @@ dependencies = [ [[package]] name = "prometheus-client" -version = "0.16.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1abe0255c04d15f571427a2d1e00099016506cf3297b53853acd2b7eb87825" +checksum = "83cd1b99916654a69008fd66b4f9397fbe08e6e51dfe23d4417acf5d3b8cb87c" dependencies = [ "dtoa", "itoa", - "owning_ref", + "parking_lot 0.12.1", "prometheus-client-derive-text-encode", ] [[package]] name = "prometheus-client-derive-text-encode" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e12d01b9d66ad9eb4529c57666b6263fc1993cb30261d83ead658fdd932652" +checksum = "66a455fbcb954c1a7decf3c586e860fd7889cddf4b8e164be736dbac95a953cd" dependencies = [ "proc-macro2", "quote", @@ -8182,9 +8132,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.10.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ "bytes", "prost-derive", @@ -8192,31 +8142,31 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.10.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ "bytes", - "cfg-if 1.0.0", - "cmake", "heck", "itertools", "lazy_static", "log", "multimap", "petgraph", + "prettyplease", "prost", "prost-types", "regex", + "syn", "tempfile", "which", ] [[package]] name = "prost-codec" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00af1e92c33b4813cc79fda3f2dbf56af5169709be0202df730e9ebc3e4cd007" +checksum = "011ae9ff8359df7915f97302d591cdd9e0e27fbd5a4ddc5bd13b71079bb20987" dependencies = [ "asynchronous-codec", "bytes", @@ -8227,9 +8177,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.10.1" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -8240,9 +8190,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.10.1" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ "bytes", "prost", @@ -8446,7 +8396,7 @@ dependencies = [ "derive_more", "fs-err", "itertools", - "static_init", + "static_init 0.5.2", "thiserror", ] @@ -8472,9 +8422,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.2.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8d23b35d7177df3b9d31ed8a9ab4bf625c668be77a319d4f5efd4a5257701c" +checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" dependencies = [ "fxhash", "log", @@ -8508,25 +8458,12 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "region" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" -dependencies = [ - "bitflags", - "libc", - "mach", - "winapi", -] - [[package]] name = "remote-externalities" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "env_logger 0.9.3", - "jsonrpsee", "log", "parity-scale-codec", "serde", @@ -8535,6 +8472,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-version", + "substrate-rpc-client", ] [[package]] @@ -8584,9 +8522,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "620f4129485ff1a7128d184bc687470c21c7951b64779ebc9cfdad3dcd920290" +checksum = "7e9562ea1d70c0cc63a34a22d977753b50cca91cc6b6527750463bd5dd8697bc" dependencies = [ "libc", "librocksdb-sys", @@ -8594,8 +8532,8 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-merkle-tree", "beefy-primitives", @@ -8613,23 +8551,37 @@ dependencies = [ "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", + "pallet-bounties", + "pallet-child-bounties", "pallet-collective", + "pallet-democracy", + "pallet-elections-phragmen", + "pallet-gilt", "pallet-grandpa", + "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-membership", "pallet-mmr", "pallet-multisig", "pallet-offences", + "pallet-preimage", "pallet-proxy", + "pallet-recovery", + "pallet-scheduler", "pallet-session", + "pallet-society", "pallet-staking", "pallet-sudo", "pallet-timestamp", + "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", "pallet-utility", + "pallet-vesting", "pallet-xcm", + "pallet-xcm-benchmarks", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", @@ -8655,6 +8607,7 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "static_assertions", "substrate-wasm-builder", "xcm", "xcm-builder", @@ -8663,14 +8616,16 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "polkadot-primitives", "polkadot-runtime-common", "smallvec", + "sp-core", "sp-runtime", + "sp-weights", ] [[package]] @@ -8745,20 +8700,6 @@ dependencies = [ "semver 1.0.16", ] -[[package]] -name = "rustix" -version = "0.33.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938a344304321a9da4973b9ff4f9f8db9caf4597dfd9dda6a60b523340a0fff0" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes 0.5.3", - "libc", - "linux-raw-sys 0.0.42", - "winapi", -] - [[package]] name = "rustix" version = "0.35.13" @@ -8770,7 +8711,7 @@ dependencies = [ "io-lifetimes 0.7.5", "libc", "linux-raw-sys 0.0.46", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -8784,7 +8725,7 @@ dependencies = [ "io-lifetimes 1.0.4", "libc", "linux-raw-sys 0.1.4", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -8852,15 +8793,6 @@ dependencies = [ "rustc_version 0.2.3", ] -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher 0.4.3", -] - [[package]] name = "same-file" version = "1.0.6" @@ -8873,7 +8805,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "sp-core", @@ -8884,7 +8816,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures 0.3.25", @@ -8911,7 +8843,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "futures-timer", @@ -8934,7 +8866,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -8950,7 +8882,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "impl-trait-for-tuples", "memmap2", @@ -8967,7 +8899,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -8978,13 +8910,13 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "chrono", "clap", "fdlimit", "futures 0.3.25", - "hex", "libp2p", "log", "names", @@ -8996,6 +8928,7 @@ dependencies = [ "sc-client-db", "sc-keystore", "sc-network", + "sc-network-common", "sc-service", "sc-telemetry", "sc-tracing", @@ -9017,7 +8950,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "fnv", "futures 0.3.25", @@ -9045,7 +8978,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "hash-db", "kvdb", @@ -9070,7 +9003,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures 0.3.25", @@ -9094,7 +9027,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures 0.3.25", @@ -9123,14 +9056,14 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "fork-tree", "futures 0.3.25", "log", "merlin", - "num-bigint", + "num-bigint 0.2.6", "num-rational 0.2.4", "num-traits", "parity-scale-codec", @@ -9165,7 +9098,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "jsonrpsee", @@ -9187,7 +9120,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "fork-tree", "parity-scale-codec", @@ -9200,7 +9133,7 @@ dependencies = [ [[package]] name = "sc-consensus-manual-seal" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "assert_matches", "async-trait", @@ -9234,7 +9167,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures 0.3.25", @@ -9252,14 +9185,13 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-state-machine", - "sp-timestamp", "thiserror", ] [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "lazy_static", "lru 0.7.8", @@ -9286,7 +9218,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "environmental", "parity-scale-codec", @@ -9302,7 +9234,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "parity-scale-codec", @@ -9317,15 +9249,14 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "cfg-if 1.0.0", "libc", "log", "once_cell", "parity-scale-codec", - "parity-wasm 0.42.2", - "rustix 0.33.7", + "parity-wasm 0.45.0", "rustix 0.35.13", "sc-allocator", "sc-executor-common", @@ -9338,16 +9269,16 @@ dependencies = [ [[package]] name = "sc-finality-grandpa" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ahash", + "array-bytes", "async-trait", "dyn-clone", "finality-grandpa", "fork-tree", "futures 0.3.25", "futures-timer", - "hex", "log", "parity-scale-codec", "parking_lot 0.12.1", @@ -9379,7 +9310,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "finality-grandpa", "futures 0.3.25", @@ -9400,7 +9331,7 @@ dependencies = [ [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ansi_term", "futures 0.3.25", @@ -9417,10 +9348,10 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "async-trait", - "hex", "parking_lot 0.12.1", "serde_json", "sp-application-crypto", @@ -9432,8 +9363,9 @@ dependencies = [ [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "async-trait", "asynchronous-codec", "bitflags", @@ -9444,7 +9376,6 @@ dependencies = [ "fork-tree", "futures 0.3.25", "futures-timer", - "hex", "ip_network", "libp2p", "linked-hash-map", @@ -9455,7 +9386,6 @@ dependencies = [ "parking_lot 0.12.1", "pin-project", "prost", - "prost-build", "rand 0.7.3", "sc-block-builder", "sc-client-api", @@ -9474,20 +9404,41 @@ dependencies = [ "substrate-prometheus-endpoint", "thiserror", "unsigned-varint", - "void", "zeroize", ] +[[package]] +name = "sc-network-bitswap" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "cid", + "futures 0.3.25", + "libp2p", + "log", + "prost", + "prost-build", + "sc-client-api", + "sc-network-common", + "sp-blockchain", + "sp-runtime", + "thiserror", + "unsigned-varint", + "void", +] + [[package]] name = "sc-network-common" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "bitflags", "bytes", "futures 0.3.25", + "futures-timer", "libp2p", + "linked_hash_set", "parity-scale-codec", "prost-build", "sc-consensus", @@ -9498,13 +9449,14 @@ dependencies = [ "sp-consensus", "sp-finality-grandpa", "sp-runtime", + "substrate-prometheus-endpoint", "thiserror", ] [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ahash", "futures 0.3.25", @@ -9522,10 +9474,10 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "futures 0.3.25", - "hex", "libp2p", "log", "parity-scale-codec", @@ -9543,14 +9495,15 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "fork-tree", "futures 0.3.25", - "hex", "libp2p", "log", "lru 0.7.8", + "mockall", "parity-scale-codec", "prost", "prost-build", @@ -9558,6 +9511,7 @@ dependencies = [ "sc-consensus", "sc-network-common", "sc-peerset", + "sc-utils", "smallvec", "sp-arithmetic", "sp-blockchain", @@ -9568,16 +9522,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sc-network-transactions" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "array-bytes", + "futures 0.3.25", + "hex", + "libp2p", + "log", + "parity-scale-codec", + "pin-project", + "sc-network-common", + "sc-peerset", + "sp-consensus", + "sp-runtime", + "substrate-prometheus-endpoint", +] + [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "bytes", "fnv", "futures 0.3.25", "futures-timer", - "hex", "hyper", "hyper-rustls", "libp2p", @@ -9601,7 +9574,7 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "libp2p", @@ -9614,7 +9587,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -9623,7 +9596,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "hash-db", @@ -9653,7 +9626,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "jsonrpsee", @@ -9676,7 +9649,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "jsonrpsee", @@ -9686,10 +9659,29 @@ dependencies = [ "tokio", ] +[[package]] +name = "sc-rpc-spec-v2" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "futures 0.3.25", + "hex", + "jsonrpsee", + "parity-scale-codec", + "sc-chain-spec", + "sc-transaction-pool-api", + "serde", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "thiserror", +] + [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "directories", @@ -9713,12 +9705,15 @@ dependencies = [ "sc-informant", "sc-keystore", "sc-network", + "sc-network-bitswap", "sc-network-common", "sc-network-light", "sc-network-sync", + "sc-network-transactions", "sc-offchain", "sc-rpc", "sc-rpc-server", + "sc-rpc-spec-v2", "sc-sysinfo", "sc-telemetry", "sc-tracing", @@ -9745,6 +9740,7 @@ dependencies = [ "sp-transaction-storage-proof", "sp-trie", "sp-version", + "static_init 1.0.3", "substrate-prometheus-endpoint", "tempfile", "thiserror", @@ -9756,7 +9752,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "parity-scale-codec", @@ -9770,7 +9766,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -9789,7 +9785,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "6.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "libc", @@ -9808,7 +9804,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "chrono", "futures 0.3.25", @@ -9826,7 +9822,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ansi_term", "atty", @@ -9857,7 +9853,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -9868,8 +9864,9 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "async-trait", "futures 0.3.25", "futures-timer", "linked-hash-map", @@ -9894,8 +9891,9 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "async-trait", "futures 0.3.25", "log", "serde", @@ -9907,7 +9905,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "futures-timer", @@ -9949,7 +9947,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -10000,6 +9998,7 @@ checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ "der", "generic-array 0.14.6", + "pkcs8", "subtle", "zeroize", ] @@ -10299,8 +10298,8 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" [[package]] name = "slot-range-helper" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "enumn", "parity-scale-codec", @@ -10376,7 +10375,7 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "hash-db", "log", @@ -10394,7 +10393,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "blake2", "proc-macro-crate", @@ -10406,7 +10405,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10419,7 +10418,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "5.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "integer-sqrt", "num-traits", @@ -10434,7 +10433,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10447,7 +10446,7 @@ dependencies = [ [[package]] name = "sp-authorship" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "parity-scale-codec", @@ -10459,7 +10458,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "sp-api", @@ -10471,7 +10470,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures 0.3.25", "log", @@ -10489,7 +10488,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures 0.3.25", @@ -10508,7 +10507,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "parity-scale-codec", @@ -10526,7 +10525,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "merlin", @@ -10549,7 +10548,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10563,7 +10562,7 @@ dependencies = [ [[package]] name = "sp-consensus-vrf" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10576,18 +10575,18 @@ dependencies = [ [[package]] name = "sp-core" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "base58", "bitflags", - "blake2-rfc", + "blake2", "byteorder", "dyn-clonable", "ed25519-zebra", "futures 0.3.25", "hash-db", "hash256-std-hasher", - "hex", "impl-serde", "lazy_static", "libsecp256k1", @@ -10622,7 +10621,7 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "4.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "blake2", "byteorder", @@ -10636,7 +10635,7 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro2", "quote", @@ -10647,7 +10646,7 @@ dependencies = [ [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "kvdb", "parking_lot 0.12.1", @@ -10656,7 +10655,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "4.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "proc-macro2", "quote", @@ -10666,7 +10665,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.12.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "environmental", "parity-scale-codec", @@ -10677,7 +10676,7 @@ dependencies = [ [[package]] name = "sp-finality-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "finality-grandpa", "log", @@ -10695,7 +10694,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -10709,10 +10708,9 @@ dependencies = [ [[package]] name = "sp-io" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "bytes", - "ed25519-dalek", "futures 0.3.25", "hash-db", "libsecp256k1", @@ -10736,7 +10734,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "lazy_static", "sp-core", @@ -10747,7 +10745,7 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.12.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures 0.3.25", @@ -10764,7 +10762,7 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "thiserror", "zstd", @@ -10773,10 +10771,11 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "parity-scale-codec", + "scale-info", "serde", "sp-api", "sp-core", @@ -10788,7 +10787,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10802,7 +10801,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "sp-api", "sp-core", @@ -10812,7 +10811,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "4.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "backtrace", "lazy_static", @@ -10822,7 +10821,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "rustc-hash", "serde", @@ -10832,7 +10831,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "either", "hash256-std-hasher", @@ -10849,12 +10848,13 @@ dependencies = [ "sp-core", "sp-io", "sp-std", + "sp-weights", ] [[package]] name = "sp-runtime-interface" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -10872,7 +10872,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "5.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "Inflector", "proc-macro-crate", @@ -10884,7 +10884,7 @@ dependencies = [ [[package]] name = "sp-sandbox" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "parity-scale-codec", @@ -10898,7 +10898,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10912,7 +10912,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "scale-info", @@ -10923,7 +10923,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.12.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "hash-db", "log", @@ -10945,12 +10945,12 @@ dependencies = [ [[package]] name = "sp-std" version = "4.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" [[package]] name = "sp-storage" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "impl-serde", "parity-scale-codec", @@ -10963,7 +10963,7 @@ dependencies = [ [[package]] name = "sp-tasks" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "log", "sp-core", @@ -10976,7 +10976,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "futures-timer", @@ -10992,7 +10992,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "5.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "sp-std", @@ -11004,7 +11004,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "sp-api", "sp-runtime", @@ -11013,7 +11013,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "async-trait", "log", @@ -11029,7 +11029,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ahash", "hash-db", @@ -11052,11 +11052,11 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "impl-serde", "parity-scale-codec", - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", "scale-info", "serde", "sp-core-hashing-proc-macro", @@ -11069,7 +11069,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -11080,7 +11080,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "6.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "impl-trait-for-tuples", "log", @@ -11090,12 +11090,38 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "sp-weights" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "ss58-registry" version = "1.38.0" @@ -11132,7 +11158,22 @@ dependencies = [ "cfg_aliases", "libc", "parking_lot 0.11.2", - "static_init_macro", + "static_init_macro 0.5.0", +] + +[[package]] +name = "static_init" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" +dependencies = [ + "bitflags", + "cfg_aliases", + "libc", + "parking_lot 0.11.2", + "parking_lot_core 0.8.6", + "static_init_macro 1.0.2", + "winapi", ] [[package]] @@ -11148,6 +11189,19 @@ dependencies = [ "syn", ] +[[package]] +name = "static_init_macro" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" +dependencies = [ + "cfg_aliases", + "memchr", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "statrs" version = "0.15.0" @@ -11205,7 +11259,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "platforms 2.0.0", ] @@ -11224,7 +11278,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "frame-system-rpc-runtime-api", "futures 0.3.25", @@ -11245,7 +11299,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "futures-util", "hyper", @@ -11255,10 +11309,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "substrate-rpc-client" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" +dependencies = [ + "async-trait", + "jsonrpsee", + "log", + "sc-rpc-api", + "serde", + "sp-runtime", +] + [[package]] name = "substrate-state-trie-migration-rpc" version = "4.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "jsonrpsee", "log", @@ -11279,11 +11346,11 @@ dependencies = [ [[package]] name = "substrate-test-client" version = "2.0.1" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ + "array-bytes", "async-trait", "futures 0.3.25", - "hex", "parity-scale-codec", "sc-client-api", "sc-client-db", @@ -11305,7 +11372,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "ansi_term", "build-helper", @@ -11404,6 +11471,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8" + [[package]] name = "test-case" version = "2.2.2" @@ -11428,22 +11501,18 @@ dependencies = [ [[package]] name = "test-runtime-constants" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "polkadot-primitives", "polkadot-runtime-common", "smallvec", + "sp-core", "sp-runtime", + "sp-weights", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" version = "1.0.38" @@ -11503,9 +11572,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.4.3+5.2.1-patched.2" +version = "0.5.2+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1792ccb507d955b46af42c123ea8863668fae24d03721e40cad6a41773dbb49" +checksum = "ec45c14da997d0925c7835883e4d5c181f196fa142f8c19d7643d1e9af2592c3" dependencies = [ "cc", "fs_extra", @@ -11574,7 +11643,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -11702,8 +11771,8 @@ dependencies = [ [[package]] name = "tracing-gum" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "polkadot-node-jaeger", "polkadot-primitives", @@ -11713,8 +11782,8 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "expander 0.0.6", "proc-macro-crate", @@ -11791,9 +11860,9 @@ dependencies = [ [[package]] name = "trust-dns-proto" -version = "0.21.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c31f240f59877c3d4bb3b3ea0ec5a6a0cff07323580ff8c7a605cd7d08b255d" +checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" dependencies = [ "async-trait", "cfg-if 1.0.0", @@ -11805,30 +11874,30 @@ dependencies = [ "idna 0.2.3", "ipnet", "lazy_static", - "log", "rand 0.8.5", "smallvec", "thiserror", "tinyvec", + "tracing", "url", ] [[package]] name = "trust-dns-resolver" -version = "0.21.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ba72c2ea84515690c9fcef4c6c660bb9df3036ed1051686de84605b74fd558" +checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" dependencies = [ "cfg-if 1.0.0", "futures-util", "ipconfig", "lazy_static", - "log", "lru-cache", "parking_lot 0.12.1", "resolv-conf", "smallvec", "thiserror", + "tracing", "trust-dns-proto", ] @@ -11841,11 +11910,10 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/zeitgeistpm/substrate?branch=moonbeam-polkadot-v0.9.29#b7176298ae07e18077b13521e6e0ef678a557aa2" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" dependencies = [ "clap", "frame-try-runtime", - "jsonrpsee", "log", "parity-scale-codec", "remote-externalities", @@ -11861,6 +11929,8 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-version", + "sp-weights", + "substrate-rpc-client", "zstd", ] @@ -12176,11 +12246,11 @@ dependencies = [ [[package]] name = "wasm-instrument" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962e5b0401bbb6c887f54e69b8c496ea36f704df65db73e81fd5ff8dc3e63a9f" +checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" dependencies = [ - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", ] [[package]] @@ -12200,58 +12270,63 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.9.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" +checksum = "06c326c93fbf86419608361a2c925a31754cf109da1b8b55737070b4d6669422" dependencies = [ - "downcast-rs", - "libc", - "libm 0.2.6", - "memory_units", - "num-rational 0.2.4", - "num-traits", - "parity-wasm 0.42.2", + "parity-wasm 0.45.0", "wasmi-validation", + "wasmi_core", ] [[package]] name = "wasmi-validation" -version = "0.4.1" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ff416ad1ff0c42e5a926ed5d5fab74c0f098749aa0ad8b2a34b982ce0e867b" +dependencies = [ + "parity-wasm 0.45.0", +] + +[[package]] +name = "wasmi_core" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165343ecd6c018fc09ebcae280752702c9a2ef3e6f8d02f1cfcbdb53ef6d7937" +checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" dependencies = [ - "parity-wasm 0.42.2", + "downcast-rs", + "libm 0.2.6", + "memory_units", + "num-rational 0.4.1", + "num-traits", ] [[package]] name = "wasmparser" -version = "0.85.0" +version = "0.89.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570460c58b21e9150d2df0eaaedbb7816c34bcec009ae0dcc976e40ba81463e7" +checksum = "ab5d3e08b13876f96dd55608d03cd4883a0545884932d5adf11925876c96daef" dependencies = [ "indexmap", ] [[package]] name = "wasmtime" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f50eadf868ab6a04b7b511460233377d0bfbb92e417b2f6a98b98fef2e098f5" +checksum = "4ad5af6ba38311282f2a21670d96e78266e8c8e2f38cbcd52c254df6ccbc7731" dependencies = [ "anyhow", - "backtrace", "bincode", "cfg-if 1.0.0", "indexmap", - "lazy_static", "libc", "log", - "object 0.28.4", + "object 0.29.0", "once_cell", "paste", "psm", "rayon", - "region", "serde", "target-lexicon", "wasmparser", @@ -12260,14 +12335,23 @@ dependencies = [ "wasmtime-environ", "wasmtime-jit", "wasmtime-runtime", - "winapi", + "windows-sys 0.36.1", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45de63ddfc8b9223d1adc8f7b2ee5f35d1f6d112833934ad7ea66e4f4339e597" +dependencies = [ + "cfg-if 1.0.0", ] [[package]] name = "wasmtime-cache" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1df23c642e1376892f3b72f311596976979cbf8b85469680cdd3a8a063d12a2" +checksum = "bcd849399d17d2270141cfe47fa0d91ee52d5f8ea9b98cf7ddde0d53e5f79882" dependencies = [ "anyhow", "base64 0.13.1", @@ -12275,19 +12359,19 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.33.7", + "rustix 0.35.13", "serde", "sha2 0.9.9", "toml", - "winapi", + "windows-sys 0.36.1", "zstd", ] [[package]] name = "wasmtime-cranelift" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f264ff6b4df247d15584f2f53d009fbc90032cfdc2605b52b961bffc71b6eccd" +checksum = "4bd91339b742ff20bfed4532a27b73c86b5bcbfedd6bea2dcdf2d64471e1b5c6" dependencies = [ "anyhow", "cranelift-codegen", @@ -12297,8 +12381,7 @@ dependencies = [ "cranelift-wasm", "gimli 0.26.2", "log", - "more-asserts", - "object 0.28.4", + "object 0.29.0", "target-lexicon", "thiserror", "wasmparser", @@ -12307,17 +12390,16 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839d2820e4b830f4b9e7aa08d4c0acabf4a5036105d639f6dfa1c6891c73bdc6" +checksum = "ebb881c61f4f627b5d45c54e629724974f8a8890d455bcbe634330cc27309644" dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", "indexmap", "log", - "more-asserts", - "object 0.28.4", + "object 0.29.0", "serde", "target-lexicon", "thiserror", @@ -12327,9 +12409,9 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0a0bcbfa18b946d890078ba0e1bc76bcc53eccfb40806c0020ec29dcd1bd49" +checksum = "1985c628011fe26adf5e23a5301bdc79b245e0e338f14bb58b39e4e25e4d8681" dependencies = [ "addr2line 0.17.0", "anyhow", @@ -12338,38 +12420,36 @@ dependencies = [ "cpp_demangle", "gimli 0.26.2", "log", - "object 0.28.4", - "region", + "object 0.29.0", "rustc-demangle", - "rustix 0.33.7", + "rustix 0.35.13", "serde", "target-lexicon", "thiserror", "wasmtime-environ", "wasmtime-jit-debug", "wasmtime-runtime", - "winapi", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-jit-debug" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4779d976206c458edd643d1ac622b6c37e4a0800a8b1d25dfbf245ac2f2cac" +checksum = "f671b588486f5ccec8c5a3dba6b4c07eac2e66ab8c60e6f4e53717c77f709731" dependencies = [ - "lazy_static", - "object 0.28.4", - "rustix 0.33.7", + "object 0.29.0", + "once_cell", + "rustix 0.35.13", ] [[package]] name = "wasmtime-runtime" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7eb6ffa169eb5dcd18ac9473c817358cd57bc62c244622210566d473397954a" +checksum = "ee8f92ad4b61736339c29361da85769ebc200f184361959d1792832e592a1afd" dependencies = [ "anyhow", - "backtrace", "cc", "cfg-if 1.0.0", "indexmap", @@ -12378,21 +12458,21 @@ dependencies = [ "mach", "memfd", "memoffset 0.6.5", - "more-asserts", + "paste", "rand 0.8.5", - "region", - "rustix 0.33.7", + "rustix 0.35.13", "thiserror", + "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", - "winapi", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-types" -version = "0.38.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d932b0ac5336f7308d869703dd225610a6a3aeaa8e968c52b43eed96cefb1c2" +checksum = "d23d61cb4c46e837b431196dd06abb11731541021916d03476a178b54dc07aeb" dependencies = [ "cranelift-entity", "serde", @@ -12440,8 +12520,8 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "beefy-primitives", "bitvec", @@ -12465,6 +12545,7 @@ dependencies = [ "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", + "pallet-fast-unstake", "pallet-grandpa", "pallet-identity", "pallet-im-online", @@ -12529,14 +12610,16 @@ dependencies = [ [[package]] name = "westend-runtime-constants" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "polkadot-primitives", "polkadot-runtime-common", "smallvec", + "sp-core", "sp-runtime", + "sp-weights", ] [[package]] @@ -12600,6 +12683,19 @@ dependencies = [ "windows_x86_64_msvc 0.34.0", ] +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + [[package]] name = "windows-sys" version = "0.42.0" @@ -12627,6 +12723,12 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + [[package]] name = "windows_aarch64_msvc" version = "0.42.1" @@ -12639,6 +12741,12 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + [[package]] name = "windows_i686_gnu" version = "0.42.1" @@ -12651,6 +12759,12 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + [[package]] name = "windows_i686_msvc" version = "0.42.1" @@ -12663,6 +12777,12 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + [[package]] name = "windows_x86_64_gnu" version = "0.42.1" @@ -12681,6 +12801,12 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "windows_x86_64_msvc" version = "0.42.1" @@ -12718,8 +12844,8 @@ dependencies = [ [[package]] name = "xcm" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "derivative", "impl-trait-for-tuples", @@ -12732,8 +12858,8 @@ dependencies = [ [[package]] name = "xcm-builder" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-support", "frame-system", @@ -12753,7 +12879,7 @@ dependencies = [ [[package]] name = "xcm-emulator" version = "0.1.0" -source = "git+https://github.com/zeitgeistpm/xcm-simulator?branch=moonbeam-polkadot-v0.9.29#4d235aab4d2ab8527aceb8b5849ca4eb18a08a08" +source = "git+https://github.com/shaunxw/xcm-simulator?rev=158a6bd2768c679563efa891aa17329635b2764b#158a6bd2768c679563efa891aa17329635b2764b" dependencies = [ "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -12778,8 +12904,8 @@ dependencies = [ [[package]] name = "xcm-executor" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "frame-benchmarking", "frame-support", @@ -12796,8 +12922,8 @@ dependencies = [ [[package]] name = "xcm-procedural" -version = "0.9.29" -source = "git+https://github.com/zeitgeistpm/polkadot?branch=moonbeam-polkadot-v0.9.29#91a493ceb0db61c9208dfe8c18e3886b1e5f119b" +version = "0.9.32" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.32#c71e872afed296d1825b15ea4b2a74750c1ba647" dependencies = [ "Inflector", "proc-macro2", @@ -13001,6 +13127,7 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", + "sp-std", "sp-transaction-pool", "sp-version", "substrate-fixed", diff --git a/external/nimbus-consensus/Cargo.toml b/external/nimbus-consensus/Cargo.toml index a1845ba86..f81859551 100644 --- a/external/nimbus-consensus/Cargo.toml +++ b/external/nimbus-consensus/Cargo.toml @@ -5,27 +5,27 @@ edition = "2021" version = "0.9.0" [dependencies] # Substrate deps -sc-client-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sc-consensus = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sc-consensus-manual-seal = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-block-builder = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-blockchain = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-consensus = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-keystore = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -substrate-prometheus-endpoint = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } # Polkadot dependencies -polkadot-client = { git = "https://github.com/zeitgeistpm/polkadot", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +polkadot-client = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "release-v0.9.32" } # Cumulus dependencies -cumulus-client-consensus-common = { git = "https://github.com/zeitgeistpm/cumulus", branch = "moonbeam-polkadot-v0.9.29" } -cumulus-primitives-core = { git = "https://github.com/zeitgeistpm/cumulus", branch = "moonbeam-polkadot-v0.9.29" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/zeitgeistpm/cumulus", branch = "moonbeam-polkadot-v0.9.29" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } # Nimbus Dependencies nimbus-primitives = { path = "../nimbus-primitives" } diff --git a/external/nimbus-primitives/Cargo.toml b/external/nimbus-primitives/Cargo.toml index f780237fc..3ad573737 100644 --- a/external/nimbus-primitives/Cargo.toml +++ b/external/nimbus-primitives/Cargo.toml @@ -9,16 +9,16 @@ version = "0.9.0" async-trait = { version = "0.1", optional = true } parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } -frame-support = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -frame-system = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } -sp-api = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-std = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", optional = true, default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false , branch = "polkadot-v0.9.32" } [features] default = [ "std" ] diff --git a/external/nimbus-primitives/src/inherents.rs b/external/nimbus-primitives/src/inherents.rs index 267b17d96..426b4d993 100644 --- a/external/nimbus-primitives/src/inherents.rs +++ b/external/nimbus-primitives/src/inherents.rs @@ -21,7 +21,7 @@ pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"author__"; /// A bare minimum inherent data provider that provides no real data. /// The inherent is simply used as a way to kick off some computation -/// until https://github.com/zeitgeistpm/substrate/pull/10128 lands. +/// until https://github.com/paritytech/substrate/pull/10128 lands. pub struct InherentDataProvider; #[cfg(feature = "std")] diff --git a/external/pallets/author-inherent/Cargo.toml b/external/pallets/author-inherent/Cargo.toml index 4e056fb2d..6221db389 100644 --- a/external/pallets/author-inherent/Cargo.toml +++ b/external/pallets/author-inherent/Cargo.toml @@ -7,26 +7,26 @@ license = "GPL-3.0-only" version = "0.9.0" [dependencies] -frame-support = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -frame-system = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } log = { version = "0.4.17", default-features = false } nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } -sp-api = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-authorship = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-std = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } # Benchmarks -frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", optional = true, default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false , branch = "polkadot-v0.9.32" } [dev-dependencies] -frame-support-test = { git = "https://github.com/zeitgeistpm/substrate", version = "3.0.0" , branch = "moonbeam-polkadot-v0.9.29" } -sp-core = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-io = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0" , branch = "polkadot-v0.9.32" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } [features] default = [ "std" ] diff --git a/external/pallets/author-inherent/src/lib.rs b/external/pallets/author-inherent/src/lib.rs index 6f873a8eb..1d3004172 100644 --- a/external/pallets/author-inherent/src/lib.rs +++ b/external/pallets/author-inherent/src/lib.rs @@ -116,7 +116,7 @@ pub mod pallet { impl Pallet { /// This inherent is a workaround to run code after the "real" inherents have executed, /// but before transactions are executed. - // This should go into on_post_inherents when it is ready https://github.com/zeitgeistpm/substrate/pull/10128 + // This should go into on_post_inherents when it is ready https://github.com/paritytech/substrate/pull/10128 // TODO better weight. For now we just set a somewhat conservative fudge factor #[pallet::weight((T::WeightInfo::kick_off_authorship_validation(), DispatchClass::Mandatory))] pub fn kick_off_authorship_validation(origin: OriginFor) -> DispatchResultWithPostInfo { diff --git a/external/pallets/author-mapping/Cargo.toml b/external/pallets/author-mapping/Cargo.toml index cf5a3925b..79fd56e11 100644 --- a/external/pallets/author-mapping/Cargo.toml +++ b/external/pallets/author-mapping/Cargo.toml @@ -10,13 +10,13 @@ log = { version = "0.4", default-features = false } serde = { version = "1.0.124", optional = true } # Substrate -frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", optional = true, default-features = false } -frame-support = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -frame-system = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-std = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } # Nimbus nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } @@ -24,9 +24,9 @@ nimbus-primitives = { path = "../../nimbus-primitives", default-features = false session-keys-primitives = { path = "../../session-keys", default-features = false } [dev-dependencies] -pallet-balances = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-io = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } [features] default = [ "std" ] diff --git a/external/pallets/author-mapping/src/lib.rs b/external/pallets/author-mapping/src/lib.rs index fca208903..73fb20778 100644 --- a/external/pallets/author-mapping/src/lib.rs +++ b/external/pallets/author-mapping/src/lib.rs @@ -81,7 +81,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// Overarching event type - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// Currency in which the security deposit will be taken. type DepositCurrency: Currency + ReservableCurrency; /// The amount that should be taken as a security deposit when registering a NimbusId. diff --git a/external/pallets/author-slot-filter/Cargo.toml b/external/pallets/author-slot-filter/Cargo.toml index 3d0cda7e9..e4b4ea067 100644 --- a/external/pallets/author-slot-filter/Cargo.toml +++ b/external/pallets/author-slot-filter/Cargo.toml @@ -6,23 +6,23 @@ edition = "2021" version = "0.9.0" [dependencies] -frame-support = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -frame-system = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } log = { version = "0.4.17", default-features = false } nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } serde = { version = "1.0.101", default-features = false, features = [ "derive" ] } -sp-core = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } -sp-std = { git = "https://github.com/zeitgeistpm/substrate", default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } # Benchmarks -frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", optional = true, default-features = false , branch = "moonbeam-polkadot-v0.9.29" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false , branch = "polkadot-v0.9.32" } [dev-dependencies] -frame-support-test = { git = "https://github.com/zeitgeistpm/substrate", version = "3.0.0" , branch = "moonbeam-polkadot-v0.9.29" } -sp-io = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0" , branch = "polkadot-v0.9.32" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } [features] default = [ "std" ] diff --git a/external/pallets/author-slot-filter/src/benchmarks.rs b/external/pallets/author-slot-filter/src/benchmarks.rs index 4a50a3a43..57537e76e 100644 --- a/external/pallets/author-slot-filter/src/benchmarks.rs +++ b/external/pallets/author-slot-filter/src/benchmarks.rs @@ -32,7 +32,7 @@ benchmarks! { #[cfg(test)] mod tests { - use crate::tests::Test; + use crate::mock::Test; use sp_io::TestExternalities; pub fn new_test_ext() -> TestExternalities { @@ -46,5 +46,5 @@ mod tests { impl_benchmark_test_suite!( Pallet, crate::benchmarks::tests::new_test_ext(), - crate::tests::Test + crate::mock::Test ); diff --git a/external/pallets/author-slot-filter/src/lib.rs b/external/pallets/author-slot-filter/src/lib.rs index a63adcffb..0fb60f5bb 100644 --- a/external/pallets/author-slot-filter/src/lib.rs +++ b/external/pallets/author-slot-filter/src/lib.rs @@ -61,7 +61,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// The overarching event type - type Event: From + IsType<::Event>; + type RuntimeEvent: From + IsType<::RuntimeEvent>; /// Deterministic on-chain pseudo-randomness used to do the filtering type RandomnessSource: Randomness; //TODO introduce a new trait for exhaustive sets and use it here. diff --git a/external/pallets/parachain-staking/Cargo.toml b/external/pallets/parachain-staking/Cargo.toml index 70e74825d..2c9a4b562 100644 --- a/external/pallets/parachain-staking/Cargo.toml +++ b/external/pallets/parachain-staking/Cargo.toml @@ -10,23 +10,23 @@ log = "0.4" serde = { version = "1.0.101", optional = true } # Substrate -frame-benchmarking = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", optional = true, default-features = false } -frame-support = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -frame-system = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-std = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } # Nimbus nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } [dev-dependencies] -pallet-balances = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } similar-asserts = "1.1.0" -sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-io = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } [features] default = [ "std" ] diff --git a/external/pallets/parachain-staking/src/lib.rs b/external/pallets/parachain-staking/src/lib.rs index eaabd4255..172fc371c 100644 --- a/external/pallets/parachain-staking/src/lib.rs +++ b/external/pallets/parachain-staking/src/lib.rs @@ -111,13 +111,13 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// Overarching event type - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The currency type type Currency: Currency + ReservableCurrency + LockableCurrency; /// The origin for monetary governance - type MonetaryGovernanceOrigin: EnsureOrigin; + type MonetaryGovernanceOrigin: EnsureOrigin; /// Minimum number of blocks per round #[pallet::constant] type MinBlocksPerRound: Get; @@ -658,7 +658,7 @@ pub mod pallet { "Account does not have enough balance to bond as a candidate." ); if let Err(error) = >::join_candidates( - T::Origin::from(Some(candidate.clone()).into()), + T::RuntimeOrigin::from(Some(candidate.clone()).into()), balance, candidate_count, ) { @@ -693,7 +693,7 @@ pub mod pallet { .cloned() .unwrap_or_default(); if let Err(error) = >::delegate_with_auto_compound( - T::Origin::from(Some(delegator.clone()).into()), + T::RuntimeOrigin::from(Some(delegator.clone()).into()), target.clone(), balance, auto_compound, diff --git a/external/session-keys/Cargo.toml b/external/session-keys/Cargo.toml index e84385752..e4822d04e 100644 --- a/external/session-keys/Cargo.toml +++ b/external/session-keys/Cargo.toml @@ -7,19 +7,19 @@ version = "0.1.0" [dependencies] async-trait = { version = "0.1", optional = true } -frame-support = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } nimbus-primitives = { path = "../nimbus-primitives", default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } -sp-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-consensus-babe = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-consensus-vrf = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-inherents = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-keystore = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", optional = true, default-features = false } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-std = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } [features] default = [ "std" ] diff --git a/external/session-keys/src/inherent.rs b/external/session-keys/src/inherent.rs index 7e645ee1a..f2948739d 100644 --- a/external/session-keys/src/inherent.rs +++ b/external/session-keys/src/inherent.rs @@ -48,7 +48,7 @@ pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"baberand"; /// A bare minimum inherent data provider that provides no real data. /// The inherent is simply used as a way to kick off some computation -/// until https://github.com/zeitgeistpm/substrate/pull/10128 lands. +/// until https://github.com/paritytech/substrate/pull/10128 lands. pub struct InherentDataProvider; #[cfg(feature = "std")] diff --git a/external/vrf/Cargo.toml b/external/vrf/Cargo.toml index 5b4e1df6b..f0c736803 100644 --- a/external/vrf/Cargo.toml +++ b/external/vrf/Cargo.toml @@ -10,12 +10,12 @@ version = "0.1.0" [dependencies] # Substrate codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } -sp-api = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-application-crypto = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-consensus-vrf = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-core = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29" } -sp-keystore = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } -sp-runtime = { git = "https://github.com/zeitgeistpm/substrate", branch = "moonbeam-polkadot-v0.9.29", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } # Moonbeam session-keys-primitives = { path = "../session-keys" } @@ -24,4 +24,4 @@ session-keys-primitives = { path = "../session-keys" } nimbus-primitives = { path = "../nimbus-primitives" } # Polkadot -polkadot-primitives = { git = "https://github.com/zeitgeistpm/polkadot", branch = "moonbeam-polkadot-v0.9.29" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.32" } diff --git a/node/Cargo.toml b/node/Cargo.toml index 6b4a288b8..b507c56db 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -3,63 +3,63 @@ name = "zeitgeist" path = "./src/main.rs" [build-dependencies] -substrate-build-script-utils = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +substrate-build-script-utils = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } [dependencies] -pallet-transaction-payment = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment-rpc = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment-rpc-runtime-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-basic-authorship = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-cli = { branch = "moonbeam-polkadot-v0.9.29", features = ["wasmtime"], git = "https://github.com/zeitgeistpm/substrate" } -sc-client-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-consensus = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-executor = { branch = "moonbeam-polkadot-v0.9.29", features = ["wasmtime"], git = "https://github.com/zeitgeistpm/substrate" } -sc-keystore = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-rpc = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-rpc-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-service = { branch = "moonbeam-polkadot-v0.9.29", features = ["wasmtime"], git = "https://github.com/zeitgeistpm/substrate" } -sc-sysinfo = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-telemetry = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-transaction-pool = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-transaction-pool-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-block-builder = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-blockchain = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-consensus = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-core = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-inherents = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-keyring = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-offchain = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-session = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-storage = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-transaction-pool = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-trie = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -substrate-frame-rpc-system = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-transaction-payment = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment-rpc = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment-rpc-runtime-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-basic-authorship = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-cli = { branch = "polkadot-v0.9.32", features = ["wasmtime"], git = "https://github.com/paritytech/substrate" } +sc-client-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-consensus = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-executor = { branch = "polkadot-v0.9.32", features = ["wasmtime"], git = "https://github.com/paritytech/substrate" } +sc-keystore = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-rpc = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-rpc-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-service = { branch = "polkadot-v0.9.32", features = ["wasmtime"], git = "https://github.com/paritytech/substrate" } +sc-sysinfo = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-telemetry = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-transaction-pool = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-transaction-pool-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-block-builder = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-blockchain = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-consensus = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-core = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-inherents = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-keyring = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-offchain = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-session = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-storage = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-transaction-pool = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-trie = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +substrate-frame-rpc-system = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } # Try-Runtime -try-runtime-cli = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +try-runtime-cli = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } # Benchmark -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -frame-benchmarking-cli = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +frame-benchmarking-cli = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } # Cumulus -cumulus-client-cli = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-client-collator = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-client-consensus-common = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-client-consensus-relay-chain = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-client-network = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-client-service = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-core = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-parachain-inherent = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-relay-chain-inprocess-interface = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-relay-chain-interface = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-relay-chain-rpc-interface = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/cumulus", optional = true } +cumulus-client-cli = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-client-collator = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-client-consensus-common = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-client-consensus-relay-chain = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-client-network = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-client-service = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-core = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-parachain-inherent = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-relay-chain-inprocess-interface = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-relay-chain-interface = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-relay-chain-rpc-interface = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/cumulus", optional = true } # Parachain @@ -69,33 +69,33 @@ nimbus-consensus = { default-features = false, path = "../external/nimbus-consen pallet-author-inherent = { default-features = false, path = "../external/pallets/author-inherent", optional = true } pallet-parachain-staking = { default-features = false, path = "../external/pallets/parachain-staking", optional = true } parity-scale-codec = { optional = true, version = "3.0.0" } -sc-chain-spec = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sc-network = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sc-network-common = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sc-tracing = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +sc-chain-spec = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sc-network = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sc-network-common = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sc-tracing = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } serde = { features = ["derive"], optional = true, version = "1.0.144" } session-keys-primitives = { default-features = false, path = "../external/session-keys", optional = true } -sp-keystore = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -substrate-prometheus-endpoint = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +sp-keystore = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +substrate-prometheus-endpoint = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } # Polkadot -polkadot-cli = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-parachain = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-primitives = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-service = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-test-service = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/polkadot", optional = true } +polkadot-cli = { branch = "release-v0.9.32", git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-parachain = { branch = "release-v0.9.32", git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-primitives = { branch = "release-v0.9.32", git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-service = { branch = "release-v0.9.32", git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-test-service = { branch = "release-v0.9.32", git = "https://github.com/paritytech/polkadot", optional = true } # Standalone -sc-consensus-aura = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sc-finality-grandpa = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-consensus-aura = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-finality-grandpa = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +sc-consensus-aura = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sc-finality-grandpa = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-consensus-aura = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-finality-grandpa = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } # Utility cfg-if = { version = "1.0.0" } -clap = { version = "3.2.20", features = ["derive"] } +clap = { version = "4.0.9", features = ["derive"] } hex-literal = { version = "0.3.4" } jsonrpsee = { version = "0.15.1", features = ["server"] } log = { optional = true, version = "0.4.17" } @@ -157,6 +157,7 @@ parachain = [ runtime-benchmarks = [ "battery-station-runtime?/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", + "frame-benchmarking-cli/runtime-benchmarks", "polkadot-service?/runtime-benchmarks", "zeitgeist-runtime?/runtime-benchmarks", ] diff --git a/node/src/benchmarking.rs b/node/src/benchmarking.rs index 9845c461b..d893ff953 100644 --- a/node/src/benchmarking.rs +++ b/node/src/benchmarking.rs @@ -163,7 +163,7 @@ pub fn create_benchmark_extrinsic_zeitgeist< >( client: &FullClient, sender: sp_core::sr25519::Pair, - call: zeitgeist_runtime::Call, + call: zeitgeist_runtime::RuntimeCall, nonce: u32, ) -> zeitgeist_runtime::UncheckedExtrinsic { let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); @@ -221,7 +221,7 @@ pub fn create_benchmark_extrinsic_battery_station< >( client: &FullClient, sender: sp_core::sr25519::Pair, - call: battery_station_runtime::Call, + call: battery_station_runtime::RuntimeCall, nonce: u32, ) -> battery_station_runtime::UncheckedExtrinsic { let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); diff --git a/node/src/cli.rs b/node/src/cli.rs index e0609c5eb..0446312c5 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -442,84 +442,84 @@ impl sc_client_api::BlockBackend for Client { impl sc_client_api::StorageProvider for Client { fn storage( &self, - id: &BlockId, + hash: &::Hash, key: &StorageKey, ) -> sp_blockchain::Result> { - match_client!(self, storage(id, key)) + match_client!(self, storage(hash, key)) } fn storage_keys( &self, - id: &BlockId, + hash: &::Hash, key_prefix: &StorageKey, ) -> sp_blockchain::Result> { - match_client!(self, storage_keys(id, key_prefix)) + match_client!(self, storage_keys(hash, key_prefix)) } fn storage_hash( &self, - id: &BlockId, + hash: &::Hash, key: &StorageKey, ) -> sp_blockchain::Result::Hash>> { - match_client!(self, storage_hash(id, key)) + match_client!(self, storage_hash(hash, key)) } fn storage_pairs( &self, - id: &BlockId, + hash: &::Hash, key_prefix: &StorageKey, ) -> sp_blockchain::Result> { - match_client!(self, storage_pairs(id, key_prefix)) + match_client!(self, storage_pairs(hash, key_prefix)) } fn storage_keys_iter<'a>( &self, - id: &BlockId, + hash: &::Hash, prefix: Option<&'a StorageKey>, start_key: Option<&StorageKey>, ) -> sp_blockchain::Result< KeyIterator<'a, >::State, Block>, > { - match_client!(self, storage_keys_iter(id, prefix, start_key)) + match_client!(self, storage_keys_iter(hash, prefix, start_key)) } fn child_storage( &self, - id: &BlockId, + hash: &::Hash, child_info: &ChildInfo, key: &StorageKey, ) -> sp_blockchain::Result> { - match_client!(self, child_storage(id, child_info, key)) + match_client!(self, child_storage(hash, child_info, key)) } fn child_storage_keys( &self, - id: &BlockId, + hash: &::Hash, child_info: &ChildInfo, key_prefix: &StorageKey, ) -> sp_blockchain::Result> { - match_client!(self, child_storage_keys(id, child_info, key_prefix)) + match_client!(self, child_storage_keys(hash, child_info, key_prefix)) } fn child_storage_keys_iter<'a>( &self, - id: &BlockId, + hash: &::Hash, child_info: ChildInfo, prefix: Option<&'a StorageKey>, start_key: Option<&StorageKey>, ) -> sp_blockchain::Result< KeyIterator<'a, >::State, Block>, > { - match_client!(self, child_storage_keys_iter(id, child_info, prefix, start_key)) + match_client!(self, child_storage_keys_iter(hash, child_info, prefix, start_key)) } fn child_storage_hash( &self, - id: &BlockId, + hash: &::Hash, child_info: &ChildInfo, key: &StorageKey, ) -> sp_blockchain::Result::Hash>> { - match_client!(self, child_storage_hash(id, child_info, key)) + match_client!(self, child_storage_hash(hash, child_info, key)) } } diff --git a/node/src/command.rs b/node/src/command.rs index 57a609a9e..86ab40238 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -114,6 +114,12 @@ pub fn run() -> sc_cli::Result<()> { BenchmarkCmd::Machine(cmd) => { runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())) } + #[cfg(not(feature = "runtime-benchmarks"))] + BenchmarkCmd::Storage(_) => Err( + "Storage benchmarking can be enabled with `--features runtime-benchmarks`." + .into(), + ), + #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => match chain_spec { #[cfg(feature = "with-zeitgeist-runtime")] spec if spec.is_zeitgeist() => runner.sync_run(|config| { diff --git a/node/src/service/service_parachain.rs b/node/src/service/service_parachain.rs index 34f298897..348af4d7e 100644 --- a/node/src/service/service_parachain.rs +++ b/node/src/service/service_parachain.rs @@ -290,7 +290,7 @@ where let prometheus_registry = parachain_config.prometheus_registry().cloned(); let transaction_pool = params.transaction_pool.clone(); let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); - let (network, system_rpc_tx, start_network) = + let (network, system_rpc_tx, tx_handler_controller, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { config: ¶chain_config, client: client.clone(), @@ -322,6 +322,7 @@ where keystore: params.keystore_container.sync_keystore(), network: network.clone(), rpc_builder, + tx_handler_controller: tx_handler_controller, system_rpc_tx, task_manager: &mut task_manager, telemetry: telemetry.as_mut(), @@ -389,7 +390,7 @@ where relay_chain_interface, relay_chain_slot_duration, import_queue, - collator_options: CollatorOptions { relay_chain_rpc_url: Default::default() }, + // collator_options: CollatorOptions { relay_chain_rpc_url: Default::default() }, }; start_full_node(params)?; diff --git a/node/src/service/service_standalone.rs b/node/src/service/service_standalone.rs index 235284feb..d5d4860e8 100644 --- a/node/src/service/service_standalone.rs +++ b/node/src/service/service_standalone.rs @@ -18,7 +18,7 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use crate::service::{AdditionalRuntimeApiCollection, RuntimeApiCollection}; -use sc_client_api::{BlockBackend, ExecutorProvider}; +use sc_client_api::BlockBackend; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; use sc_finality_grandpa::{grandpa_peers_set_config, protocol_standard_name, SharedVoterState}; @@ -95,7 +95,7 @@ where Vec::default(), )); - let (network, system_rpc_tx, network_starter) = + let (network, system_rpc_tx, tx_handler_controller, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -141,6 +141,7 @@ where task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), rpc_builder: rpc_builder, + tx_handler_controller: tx_handler_controller, backend, system_rpc_tx, config, @@ -169,12 +170,9 @@ where telemetry.as_ref().map(|x| x.handle()), ); - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let aura = sc_consensus_aura::start_aura::( + let aura = sc_consensus_aura::start_aura::( StartAuraParams { slot_duration, client, @@ -190,12 +188,11 @@ where slot_duration, ); - Ok((timestamp, slot)) + Ok((slot, timestamp)) }, force_authoring, backoff_authoring_blocks, keystore: keystore_container.sync_keystore(), - can_author_with, sync_oracle: network.clone(), justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), @@ -340,7 +337,7 @@ where let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let import_queue = sc_consensus_aura::import_queue::( + let import_queue = sc_consensus_aura::import_queue::( ImportQueueParams { block_import: grandpa_block_import.clone(), justification_import: Some(Box::new(grandpa_block_import.clone())), @@ -354,12 +351,9 @@ where slot_duration, ); - Ok((timestamp, slot)) + Ok((slot, timestamp)) }, spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::CanAuthorWithNativeVersion::new( - client.executor().clone(), - ), registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 38ffb0fac..8de2c8957 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,15 +1,15 @@ [dependencies] arbitrary = { default-features = false, optional = true, version = "1.0" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-currencies = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { default-features = false, features = ["derive"], optional = true, version = "1.0.144" } -sp-core = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-core = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } [dev-dependencies] test-case = "2.0.2" diff --git a/runtime/battery-station/Cargo.toml b/runtime/battery-station/Cargo.toml index 7576c8f15..82d48c8cd 100644 --- a/runtime/battery-station/Cargo.toml +++ b/runtime/battery-station/Cargo.toml @@ -1,66 +1,67 @@ [build-dependencies] -substrate-wasm-builder = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +substrate-wasm-builder = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } [dependencies] -frame-executive = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system-rpc-runtime-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-bounties = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-collective = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-democracy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-identity = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-membership = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-multisig = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-preimage = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-proxy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-randomness-collective-flip = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-scheduler = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-sudo = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment-rpc-runtime-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-treasury = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-utility = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-vesting = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-executive = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system-rpc-runtime-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-currencies = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +pallet-balances = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-bounties = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-collective = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-democracy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-identity = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-membership = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-multisig = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-preimage = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-proxy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-randomness-collective-flip = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-scheduler = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-sudo = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment-rpc-runtime-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-treasury = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-vesting = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-block-builder = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-core = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-inherents = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-offchain = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-session = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-transaction-pool = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-version = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-block-builder = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-core = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-inherents = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-offchain = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-session = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-std = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-transaction-pool = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-version = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } substrate-fixed = { default-features = false, features = ["serde"], git = "https://github.com/encointer/substrate-fixed" } # Try-Runtime -frame-try-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } +frame-try-runtime = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } # Benchmark -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate", optional = true } -frame-system-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate", optional = true } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate", optional = true } +frame-system-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate", optional = true } # Cumulus -cumulus-pallet-dmp-queue = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-pallet-parachain-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-pallet-xcm = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-pallet-xcmp-queue = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-core = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-timestamp = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-utility = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -parachain-info = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } +cumulus-pallet-dmp-queue = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-pallet-parachain-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-pallet-xcm = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-pallet-xcmp-queue = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-core = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-timestamp = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +parachain-info = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } # Parachain nimbus-primitives = { default-features = false, path = "../../external/nimbus-primitives", optional = true } @@ -73,14 +74,14 @@ session-keys-primitives = { default-features = false, path = "../../external/ses # Polkadot -polkadot-parachain = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } +polkadot-parachain = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } # Standalone -pallet-aura = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-grandpa = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-consensus-aura = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-finality-grandpa = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +pallet-aura = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-grandpa = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-consensus-aura = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-finality-grandpa = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } # Utility cfg-if = { version = "1.0.0" } @@ -88,17 +89,17 @@ hex-literal = { default-features = false, optional = true, version = "0.3.4" } log = { version = "0.4.17", default-features = false, optional = true } # XCM -kusama-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -orml-asset-registry = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-unknown-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-xcm-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-xtokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -pallet-xcm = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-primitives = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-runtime-parachains = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -xcm = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -xcm-builder = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -xcm-executor = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } +kusama-runtime = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +orml-asset-registry = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-xtokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +pallet-xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-runtime-parachains = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +xcm-builder = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +xcm-executor = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } # Zeitgeist @@ -117,9 +118,9 @@ zrml-swaps = { default-features = false, path = "../../zrml/swaps" } zrml-swaps-runtime-api = { default-features = false, path = "../../zrml/swaps/runtime-api" } [dev-dependencies] -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } test-case = "2.0.2" -xcm-emulator = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/xcm-simulator" } +xcm-emulator = { rev = "158a6bd2768c679563efa891aa17329635b2764b", git = "https://github.com/shaunxw/xcm-simulator" } [features] default = ["std"] @@ -170,7 +171,7 @@ runtime-benchmarks = [ "cumulus-pallet-xcmp-queue?/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", - "frame-system-benchmarking", + "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "hex-literal", "kusama-runtime?/runtime-benchmarks", diff --git a/runtime/battery-station/src/integration_tests/xcm/setup.rs b/runtime/battery-station/src/integration_tests/xcm/setup.rs index dfda13cf8..d1c071295 100644 --- a/runtime/battery-station/src/integration_tests/xcm/setup.rs +++ b/runtime/battery-station/src/integration_tests/xcm/setup.rs @@ -18,7 +18,7 @@ use crate::{ xcm_config::config::{battery_station, general_key}, - AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, Origin, Runtime, System, + AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, RuntimeOrigin, Runtime, System, }; use frame_support::{assert_ok, traits::GenesisBuild}; use orml_traits::asset_registry::AssetMetadata; @@ -133,7 +133,7 @@ pub(super) fn register_foreign_ztg(additional_meta: Option) { additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(Origin::root(), meta, Some(FOREIGN_ZTG_ID))); + assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_ZTG_ID))); } pub(super) fn register_foreign_sibling(additional_meta: Option) { @@ -147,7 +147,7 @@ pub(super) fn register_foreign_sibling(additional_meta: Option) additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(Origin::root(), meta, Some(FOREIGN_SIBLING_ID))); + assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_SIBLING_ID))); } pub(super) fn register_foreign_parent(additional_meta: Option) { @@ -161,7 +161,7 @@ pub(super) fn register_foreign_parent(additional_meta: Option) { additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(Origin::root(), meta, Some(FOREIGN_PARENT_ID))); + assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_PARENT_ID))); } #[inline] diff --git a/runtime/battery-station/src/integration_tests/xcm/test_net.rs b/runtime/battery-station/src/integration_tests/xcm/test_net.rs index de2b6acac..4f91fd7a3 100644 --- a/runtime/battery-station/src/integration_tests/xcm/test_net.rs +++ b/runtime/battery-station/src/integration_tests/xcm/test_net.rs @@ -17,7 +17,7 @@ use crate::{ parameters::ZeitgeistTreasuryAccount, xcm_config::config::battery_station, AccountId, - CurrencyId, DmpQueue, Origin, Runtime, XcmpQueue, + CurrencyId, DmpQueue, RuntimeOrigin, Runtime, XcmpQueue, }; use frame_support::{traits::GenesisBuild, weights::Weight}; use polkadot_primitives::v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; @@ -37,7 +37,7 @@ decl_test_relay_chain! { decl_test_parachain! { pub struct Zeitgeist { Runtime = Runtime, - Origin = Origin, + RuntimeOrigin = RuntimeOrigin, XcmpMessageHandler = XcmpQueue, DmpMessageHandler = DmpQueue, new_ext = para_ext(battery_station::ID), @@ -47,7 +47,7 @@ decl_test_parachain! { decl_test_parachain! { pub struct Sibling { Runtime = Runtime, - Origin = Origin, + RuntimeOrigin = RuntimeOrigin, XcmpMessageHandler = XcmpQueue, DmpMessageHandler = DmpQueue, new_ext = para_ext(PARA_ID_SIBLING), diff --git a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs index 793d345f7..91af6cfe0 100644 --- a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs @@ -26,7 +26,7 @@ use crate::{ test_net::{KusamaNet, Sibling, TestNet, Zeitgeist}, }, xcm_config::{config::battery_station, fees::default_per_second}, - AssetRegistry, Balance, Balances, CurrencyId, Origin, Tokens, XTokens, + AssetRegistry, Balance, Balances, CurrencyId, RuntimeOrigin, Tokens, XTokens, ZeitgeistTreasuryAccount, }; @@ -58,7 +58,7 @@ fn transfer_ztg_to_sibling() { assert_eq!(Balances::free_balance(&ALICE.into()), alice_initial_balance); assert_eq!(Balances::free_balance(&sibling_parachain_account()), 0); assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), + RuntimeOrigin::signed(ALICE.into()), CurrencyId::Ztg, transfer_amount, Box::new( @@ -128,7 +128,7 @@ fn transfer_ztg_sibling_to_zeitgeist() { assert_eq!(Balances::free_balance(&zeitgeist_parachain_account()), 0); assert_eq!(Tokens::free_balance(FOREIGN_ZTG_ID, &BOB.into()), bob_initial_balance); assert_ok!(XTokens::transfer( - Origin::signed(BOB.into()), + RuntimeOrigin::signed(BOB.into()), FOREIGN_ZTG_ID, transfer_amount, Box::new( @@ -215,7 +215,7 @@ fn transfer_ksm_to_relay_chain() { assert!(initial_balance >= transfer_amount); assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), + RuntimeOrigin::signed(ALICE.into()), FOREIGN_PARENT_ID, transfer_amount, Box::new( @@ -274,7 +274,7 @@ fn transfer_ztg_to_sibling_with_custom_fee() { assert_eq!(Balances::free_balance(&ALICE.into()), alice_initial_balance); assert_eq!(Balances::free_balance(&sibling_parachain_account()), 0); assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), + RuntimeOrigin::signed(ALICE.into()), CurrencyId::Ztg, transfer_amount, Box::new( diff --git a/runtime/battery-station/src/lib.rs b/runtime/battery-station/src/lib.rs index 9e169c9e7..60c46727a 100644 --- a/runtime/battery-station/src/lib.rs +++ b/runtime/battery-station/src/lib.rs @@ -101,8 +101,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { pub struct IsCallable; // Currently disables Court, Rikiddo and creation of markets using Court. -impl Contains for IsCallable { - fn contains(call: &Call) -> bool { +impl Contains for IsCallable { + fn contains(call: &RuntimeCall) -> bool { use zeitgeist_primitives::types::{ MarketDisputeMechanism::Court, ScoringRule::RikiddoSigmoidFeeMarketEma, }; @@ -112,9 +112,9 @@ impl Contains for IsCallable { #[allow(clippy::match_like_matches_macro)] match call { - Call::Court(_) => false, - Call::LiquidityMining(_) => false, - Call::PredictionMarkets(inner_call) => { + RuntimeCall::Court(_) => false, + RuntimeCall::LiquidityMining(_) => false, + RuntimeCall::PredictionMarkets(inner_call) => { match inner_call { // Disable Rikiddo markets create_market { scoring_rule: RikiddoSigmoidFeeMarketEma, .. } => false, @@ -145,8 +145,8 @@ create_runtime_with_additional_pallets!( ); impl pallet_sudo::Config for Runtime { - type Call = Call; - type Event = Event; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; } impl_config_traits!(); diff --git a/runtime/battery-station/src/parachain_params.rs b/runtime/battery-station/src/parachain_params.rs index 64b45a2fd..daaf82ddb 100644 --- a/runtime/battery-station/src/parachain_params.rs +++ b/runtime/battery-station/src/parachain_params.rs @@ -22,7 +22,7 @@ )] #![cfg(feature = "parachain")] -use super::{parameters::MAXIMUM_BLOCK_WEIGHT, Origin, ParachainInfo}; +use super::{parameters::MAXIMUM_BLOCK_WEIGHT, RuntimeOrigin, ParachainInfo}; use frame_support::{parameter_types, weights::Weight}; use orml_traits::parameter_type_with_key; use sp_runtime::{Perbill, Percent}; @@ -43,7 +43,7 @@ parameter_types! { pub const RelayNetwork: NetworkId = NetworkId::Any; pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UnitWeightCost: u64 = 200_000_000; // Staking diff --git a/runtime/battery-station/src/parameters.rs b/runtime/battery-station/src/parameters.rs index fee8dbc3e..f19c00fa0 100644 --- a/runtime/battery-station/src/parameters.rs +++ b/runtime/battery-station/src/parameters.rs @@ -28,6 +28,7 @@ use frame_support::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, DispatchClass, Weight, }, + traits::WithdrawReasons, PalletId, }; use frame_system::limits::{BlockLength, BlockWeights}; @@ -351,6 +352,8 @@ parameter_types! { // Vesting pub const MinVestedTransfer: Balance = ExistentialDeposit::get(); + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); } #[cfg(feature = "with-global-disputes")] diff --git a/runtime/battery-station/src/xcm_config/config.rs b/runtime/battery-station/src/xcm_config/config.rs index 238537fe9..6ccb40723 100644 --- a/runtime/battery-station/src/xcm_config/config.rs +++ b/runtime/battery-station/src/xcm_config/config.rs @@ -17,8 +17,8 @@ use super::fees::{native_per_second, FixedConversionRateProvider}; use crate::{ - AccountId, Ancestry, AssetManager, AssetRegistry, Balance, Call, CurrencyId, MaxInstructions, - Origin, ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, + AccountId, Ancestry, AssetManager, AssetRegistry, Balance, RuntimeCall, CurrencyId, MaxInstructions, + RuntimeOrigin, ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, UnitWeightCost, UnknownTokens, XcmpQueue, ZeitgeistTreasuryAccount, }; @@ -70,8 +70,8 @@ impl Config for XcmConfig { /// Additional filters that specify whether the XCM instruction should be executed at all. type Barrier = Barrier; /// The outer call dispatch type. - type Call = Call; - type CallDispatcher = Call; + type RuntimeCall = RuntimeCall; + // type CallDispatcher = Call; /// Combinations of (Location, Asset) pairs which are trusted as reserves. // Trust the parent chain, sibling parachains and children chains of this chain. type IsReserve = MultiNativeAsset; @@ -90,7 +90,7 @@ impl Config for XcmConfig { /// The means of determining an XCM message's weight. // Adds UnitWeightCost per instruction plus the weight of each instruction. // The total number of instructions are bounded by MaxInstructions - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; /// How to send an onward XCM message. type XcmSender = XcmRouter; } @@ -262,7 +262,7 @@ impl Convert for AccountIdToMultiLocation { } /// No local origins on this chain are allowed to dispatch XCM sends/executions. -pub type LocalOriginToLocation = SignedToAccountId32; +pub type LocalOriginToLocation = SignedToAccountId32; /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used /// when determining ownership of accounts for asset transacting and when attempting to use XCM @@ -283,18 +283,18 @@ pub type XcmOriginToTransactDispatchOrigin = ( // Sovereign account converter; this attempts to derive an `AccountId` from the origin location // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, + SovereignSignedViaLocation, // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognized. - RelayChainAsNative, + RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when // recognized. - SiblingParachainAsNative, + SiblingParachainAsNative, // Native signed account converter; this just converts an `AccountId32` origin into a normal // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, + SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, + XcmPassthrough, ); /// The means for routing XCM messages which are not for local execution into the right message diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 25402a32c..9acb6a2d3 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -1,31 +1,31 @@ [dependencies] # Pallets -cumulus-pallet-xcmp-queue = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } +cumulus-pallet-xcmp-queue = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-currencies = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-bounties = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-collective = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-democracy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-identity = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-membership = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-multisig = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-bounties = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-collective = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-democracy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-identity = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-membership = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-multisig = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } -pallet-preimage = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-proxy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-randomness-collective-flip = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-scheduler = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment-rpc-runtime-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-treasury = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-utility = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-vesting = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +pallet-preimage = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-proxy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-randomness-collective-flip = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-scheduler = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment-rpc-runtime-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-treasury = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-vesting = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } # Utility cfg-if = { version = "1.0.0" } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 78f0d557d..5a4f6c7ca 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -84,8 +84,8 @@ macro_rules! decl_common_types { CheckWeight, ChargeTransactionPayment, ); - pub type SignedPayload = generic::SignedPayload; - pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + pub type SignedPayload = generic::SignedPayload; + pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; // Governance type AdvisoryCommitteeInstance = pallet_collective::Instance1; @@ -360,7 +360,7 @@ macro_rules! impl_config_traits { // Configure Pallets #[cfg(feature = "parachain")] impl cumulus_pallet_dmp_queue::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExecuteOverweightOrigin = EnsureRootOrHalfTechnicalCommittee; type XcmExecutor = xcm_executor::XcmExecutor; } @@ -369,7 +369,7 @@ macro_rules! impl_config_traits { impl cumulus_pallet_parachain_system::Config for Runtime { type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; type DmpMessageHandler = DmpQueue; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type OnSystemEvent = (); type OutboundXcmpMessageSource = XcmpQueue; type ReservedDmpWeight = crate::parachain_params::ReservedDmpWeight; @@ -380,7 +380,7 @@ macro_rules! impl_config_traits { #[cfg(feature = "parachain")] impl cumulus_pallet_xcm::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type XcmExecutor = xcm_executor::XcmExecutor; } @@ -389,7 +389,7 @@ macro_rules! impl_config_traits { type ChannelInfo = ParachainSystem; type ControllerOrigin = EnsureRootOrTwoThirdsTechnicalCommittee; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExecuteOverweightOrigin = EnsureRootOrHalfTechnicalCommittee; type VersionWrapper = (); type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; @@ -404,9 +404,9 @@ macro_rules! impl_config_traits { type BlockLength = RuntimeBlockLength; type BlockNumber = BlockNumber; type BlockWeights = RuntimeBlockWeights; - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = RocksDbWeight; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Hashing = BlakeTwo256; type Header = generic::Header; @@ -419,10 +419,10 @@ macro_rules! impl_config_traits { type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; #[cfg(not(feature = "parachain"))] type OnSetCode = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = SS58Prefix; - type SystemWeightInfo = weights::frame_system::WeightInfo; + type SystemWeightInfo = frame_system::weights::SubstrateWeight; type Version = Version; } @@ -445,14 +445,14 @@ macro_rules! impl_config_traits { impl pallet_author_mapping::Config for Runtime { type DepositAmount = CollatorDeposit; type DepositCurrency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Keys = session_keys_primitives::VrfId; type WeightInfo = pallet_author_mapping::weights::SubstrateWeight; } #[cfg(feature = "parachain")] impl pallet_author_slot_filter::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type RandomnessSource = RandomnessCollectiveFlip; type PotentialAuthors = ParachainStaking; type WeightInfo = pallet_author_slot_filter::weights::SubstrateWeight; @@ -460,8 +460,8 @@ macro_rules! impl_config_traits { #[cfg(not(feature = "parachain"))] impl pallet_grandpa::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; + // type RuntimeCall = RuntimeCall; type KeyOwnerProofSystem = (); type KeyOwnerProof = ; + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; + type ExecuteXcmOrigin = EnsureXcmOrigin; type XcmExecuteFilter = Nothing; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = xcm_executor::XcmExecutor; type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Nothing; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; type LocationInverter = LocationInverter; - type Origin = Origin; - type Call = Call; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; // ^ Override for AdvertisedXcmVersion default @@ -508,7 +508,7 @@ macro_rules! impl_config_traits { type CandidateBondLessDelay = CandidateBondLessDelay; type Currency = Balances; type DelegationBondLessDelay = DelegationBondLessDelay; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type LeaveCandidatesDelay = LeaveCandidatesDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; @@ -536,7 +536,7 @@ macro_rules! impl_config_traits { type AuthorityOrigin = AsEnsureOriginWithArg; type Balance = Balance; type CustomMetadata = CustomMetadata; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -547,25 +547,35 @@ macro_rules! impl_config_traits { type WeightInfo = weights::orml_currencies::WeightInfo; } + pub struct CurrencyHooks(sp_std::marker::PhantomData); + impl orml_traits::currency::MutationHooks for CurrencyHooks { + type OnDust = orml_tokens::TransferDust; + type OnKilledTokenAccount = (); + type OnNewTokenAccount = (); + type OnSlash = (); + type PostDeposit = (); + type PostTransfer = (); + type PreDeposit = (); + type PreTransfer = (); + } + impl orml_tokens::Config for Runtime { type Amount = Amount; type Balance = Balance; + type CurrencyHooks = CurrencyHooks; type CurrencyId = CurrencyId; type DustRemovalWhitelist = DustRemovalWhitelist; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposits = ExistentialDeposits; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; - type OnDust = orml_tokens::TransferDust; - type OnKilledTokenAccount = (); - type OnNewTokenAccount = (); type ReserveIdentifier = [u8; 8]; type WeightInfo = weights::orml_tokens::WeightInfo; } #[cfg(feature = "parachain")] impl orml_unknown_tokens::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; } #[cfg(feature = "parachain")] @@ -575,14 +585,14 @@ macro_rules! impl_config_traits { type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; type CurrencyIdConvert = AssetConvert; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type LocationInverter = LocationInverter; type MaxAssetsForTransfer = MaxAssetsForTransfer; type MinXcmFee = ParachainMinFee; type MultiLocationsFilter = Everything; type ReserveProvider = orml_traits::location::AbsoluteReserveProvider; type SelfLocation = SelfLocation; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; type XcmExecutor = xcm_executor::XcmExecutor; } @@ -590,7 +600,7 @@ macro_rules! impl_config_traits { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; @@ -600,40 +610,39 @@ macro_rules! impl_config_traits { impl pallet_collective::Config for Runtime { type DefaultVote = PrimeDefaultVote; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxMembers = AdvisoryCommitteeMaxMembers; type MaxProposals = AdvisoryCommitteeMaxProposals; type MotionDuration = AdvisoryCommitteeMotionDuration; - type Origin = Origin; - type Proposal = Call; + type RuntimeOrigin = RuntimeOrigin; + type Proposal = RuntimeCall; type WeightInfo = weights::pallet_collective::WeightInfo; } impl pallet_collective::Config for Runtime { type DefaultVote = PrimeDefaultVote; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxMembers = CouncilMaxMembers; type MaxProposals = CouncilMaxProposals; type MotionDuration = CouncilMotionDuration; - type Origin = Origin; - type Proposal = Call; + type RuntimeOrigin = RuntimeOrigin; + type Proposal = RuntimeCall; type WeightInfo = weights::pallet_collective::WeightInfo; } impl pallet_collective::Config for Runtime { type DefaultVote = PrimeDefaultVote; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxMembers = TechnicalCommitteeMaxMembers; type MaxProposals = TechnicalCommitteeMaxProposals; type MotionDuration = TechnicalCommitteeMotionDuration; - type Origin = Origin; - type Proposal = Call; + type RuntimeOrigin = RuntimeOrigin; + type Proposal = RuntimeCall; type WeightInfo = weights::pallet_collective::WeightInfo; } impl pallet_democracy::Config for Runtime { - type Proposal = Call; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type EnactmentPeriod = EnactmentPeriod; type LaunchPeriod = LaunchPeriod; @@ -664,20 +673,23 @@ macro_rules! impl_config_traits { /// Origin for anyone able to veto proposals. type VetoOrigin = pallet_collective::EnsureMember; type CooloffPeriod = CooloffPeriod; - type PreimageByteDeposit = PreimageByteDeposit; - type OperationalPreimageOrigin = pallet_collective::EnsureMember; + // type PreimageByteDeposit = PreimageByteDeposit; + // type OperationalPreimageOrigin = pallet_collective::EnsureMember; type Slash = Treasury; type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; type MaxVotes = MaxVotes; - type WeightInfo = weights::pallet_democracy::WeightInfo; + type WeightInfo = pallet_democracy::weights::SubstrateWeight; type MaxProposals = MaxProposals; + type Preimages = Preimage; + type MaxBlacklisted = ConstU32<100>; + type MaxDeposits = ConstU32<100>; } impl pallet_identity::Config for Runtime { type BasicDeposit = BasicDeposit; type Currency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type FieldDeposit = FieldDeposit; type ForceOrigin = EnsureRootOrTwoThirdsAdvisoryCommittee; type MaxAdditionalFields = MaxAdditionalFields; @@ -691,7 +703,7 @@ macro_rules! impl_config_traits { impl pallet_membership::Config for Runtime { type AddOrigin = EnsureRootOrTwoThirdsCouncil; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxMembers = AdvisoryCommitteeMaxMembers; type MembershipChanged = AdvisoryCommittee; type MembershipInitialized = AdvisoryCommittee; @@ -704,7 +716,7 @@ macro_rules! impl_config_traits { impl pallet_membership::Config for Runtime { type AddOrigin = EnsureRootOrThreeFourthsCouncil; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxMembers = CouncilMaxMembers; type MembershipChanged = Council; type MembershipInitialized = Council; @@ -717,7 +729,7 @@ macro_rules! impl_config_traits { impl pallet_membership::Config for Runtime { type AddOrigin = EnsureRootOrTwoThirdsCouncil; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxMembers = TechnicalCommitteeMaxMembers; type MembershipChanged = TechnicalCommittee; type MembershipInitialized = TechnicalCommittee; @@ -729,42 +741,41 @@ macro_rules! impl_config_traits { } impl pallet_multisig::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = ConstU16<100>; - type WeightInfo = weights::pallet_multisig::WeightInfo; + type WeightInfo = pallet_multisig::weights::SubstrateWeight; } impl pallet_preimage::Config for Runtime { type WeightInfo = weights::pallet_preimage::WeightInfo; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type ManagerOrigin = EnsureRoot; - type MaxSize = PreimageMaxSize; type BaseDeposit = PreimageBaseDeposit; type ByteDeposit = PreimageByteDeposit; } - impl InstanceFilter for ProxyType { - fn filter(&self, c: &Call) -> bool { + impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { match self { ProxyType::Any => true, ProxyType::CancelProxy => { - matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement { .. })) + matches!(c, RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })) } ProxyType::Governance => matches!( c, - Call::Democracy(..) - | Call::Council(..) - | Call::TechnicalCommittee(..) - | Call::AdvisoryCommittee(..) - | Call::Treasury(..) + RuntimeCall::Democracy(..) + | RuntimeCall::Council(..) + | RuntimeCall::TechnicalCommittee(..) + | RuntimeCall::AdvisoryCommittee(..) + | RuntimeCall::Treasury(..) ), #[cfg(feature = "parachain")] - ProxyType::Staking => matches!(c, Call::ParachainStaking(..)), + ProxyType::Staking => matches!(c, RuntimeCall::ParachainStaking(..)), #[cfg(not(feature = "parachain"))] ProxyType::Staking => false, } @@ -781,14 +792,14 @@ macro_rules! impl_config_traits { } impl pallet_proxy::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; type Currency = Balances; type ProxyType = ProxyType; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; type MaxProxies = ConstU32<32>; - type WeightInfo = weights::pallet_proxy::WeightInfo; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; type MaxPending = ConstU32<32>; type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; @@ -798,17 +809,16 @@ macro_rules! impl_config_traits { impl pallet_randomness_collective_flip::Config for Runtime {} impl pallet_scheduler::Config for Runtime { - type Event = Event; - type Origin = Origin; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type PalletsOrigin = OriginCaller; - type Call = Call; + type RuntimeCall = RuntimeCall; type MaximumWeight = MaximumSchedulerWeight; type ScheduleOrigin = EnsureRoot; type MaxScheduledPerBlock = MaxScheduledPerBlock; - type WeightInfo = weights::pallet_scheduler::WeightInfo; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; - type PreimageProvider = Preimage; - type NoPreimagePostponement = NoPreimagePostponement; + type Preimages = Preimage; } // Timestamp @@ -854,7 +864,7 @@ macro_rules! impl_config_traits { } impl pallet_transaction_payment::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type LengthToFee = ConstantMultiplier; type OnChargeTransaction = @@ -868,7 +878,7 @@ macro_rules! impl_config_traits { type Burn = Burn; type BurnDestination = (); type Currency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxApprovals = MaxApprovals; type OnSlash = (); type PalletId = TreasuryPalletId; @@ -892,23 +902,24 @@ macro_rules! impl_config_traits { type CuratorDepositMin = CuratorDepositMin; type CuratorDepositMultiplier = CuratorDepositMultiplier; type DataDepositPerByte = DataDepositPerByte; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaximumReasonLength = MaximumReasonLength; type WeightInfo = weights::pallet_bounties::WeightInfo; } impl pallet_utility::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; type WeightInfo = weights::pallet_utility::WeightInfo; } impl pallet_vesting::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BlockNumberToBalance = sp_runtime::traits::ConvertInto; type MinVestedTransfer = MinVestedTransfer; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = weights::pallet_vesting::WeightInfo; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the @@ -923,7 +934,7 @@ macro_rules! impl_config_traits { type AuthorizedDisputeResolutionOrigin = EnsureRootOrHalfAdvisoryCommittee; type CorrectionPeriod = CorrectionPeriod; type DisputeResolution = zrml_prediction_markets::Pallet; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type PalletId = AuthorizedPalletId; type WeightInfo = zrml_authorized::weights::WeightInfo; @@ -932,7 +943,7 @@ macro_rules! impl_config_traits { impl zrml_court::Config for Runtime { type CourtCaseDuration = CourtCaseDuration; type DisputeResolution = zrml_prediction_markets::Pallet; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type PalletId = CourtPalletId; type Random = RandomnessCollectiveFlip; @@ -942,7 +953,7 @@ macro_rules! impl_config_traits { } impl zrml_liquidity_mining::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type MarketId = MarketId; type PalletId = LiquidityMiningPalletId; @@ -990,7 +1001,7 @@ macro_rules! impl_config_traits { type DestroyOrigin = EnsureRootOrAllAdvisoryCommittee; type DisputeBond = DisputeBond; type DisputeFactor = DisputeFactor; - type Event = Event; + type RuntimeEvent = RuntimeEvent; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; #[cfg(feature = "with-global-disputes")] @@ -1048,7 +1059,7 @@ macro_rules! impl_config_traits { impl zrml_simple_disputes::Config for Runtime { type DisputeResolution = zrml_prediction_markets::Pallet; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type PalletId = SimpleDisputesPalletId; } @@ -1056,7 +1067,7 @@ macro_rules! impl_config_traits { #[cfg(feature = "with-global-disputes")] impl zrml_global_disputes::Config for Runtime { type Currency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type GlobalDisputeLockId = GlobalDisputeLockId; type GlobalDisputesPalletId = GlobalDisputesPalletId; type MarketCommons = MarketCommons; @@ -1069,7 +1080,7 @@ macro_rules! impl_config_traits { } impl zrml_swaps::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExitFee = ExitFee; type FixedTypeU = FixedU128; type FixedTypeS = FixedI128; @@ -1096,7 +1107,7 @@ macro_rules! impl_config_traits { } impl zrml_styx::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type SetBurnAmountOrigin = EnsureRootOrHalfCouncil; type Currency = Balances; type WeightInfo = zrml_styx::weights::WeightInfo; @@ -1330,17 +1341,17 @@ macro_rules! create_runtime_api { } } - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi for Runtime { fn query_call_info( - call: Call, + call: RuntimeCall, len: u32, ) -> pallet_transaction_payment::RuntimeDispatchInfo { TransactionPayment::query_call_info(call, len) } fn query_call_fee_details( - call: Call, + call: RuntimeCall, len: u32, ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_call_fee_details(call, len) diff --git a/runtime/common/src/weights/mod.rs b/runtime/common/src/weights/mod.rs index a7f1dec2c..efb8f6fd9 100644 --- a/runtime/common/src/weights/mod.rs +++ b/runtime/common/src/weights/mod.rs @@ -30,13 +30,13 @@ pub mod orml_tokens; pub mod pallet_balances; pub mod pallet_bounties; pub mod pallet_collective; -pub mod pallet_democracy; +// pub mod pallet_democracy; pub mod pallet_identity; pub mod pallet_membership; -pub mod pallet_multisig; +// pub mod pallet_multisig; pub mod pallet_preimage; -pub mod pallet_proxy; -pub mod pallet_scheduler; +// pub mod pallet_proxy; +// pub mod pallet_scheduler; pub mod pallet_timestamp; pub mod pallet_treasury; pub mod pallet_utility; diff --git a/runtime/zeitgeist/Cargo.toml b/runtime/zeitgeist/Cargo.toml index ceac1d737..65d7bc031 100644 --- a/runtime/zeitgeist/Cargo.toml +++ b/runtime/zeitgeist/Cargo.toml @@ -1,64 +1,65 @@ [build-dependencies] -substrate-wasm-builder = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +substrate-wasm-builder = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } [dependencies] -frame-executive = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system-rpc-runtime-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-bounties = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-collective = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-democracy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-identity = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-membership = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-multisig = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-preimage = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-proxy = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-randomness-collective-flip = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-scheduler = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-transaction-payment-rpc-runtime-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-treasury = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-utility = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-vesting = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-executive = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system-rpc-runtime-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-currencies = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +pallet-balances = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-bounties = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-collective = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-democracy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-identity = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-membership = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-multisig = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-preimage = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-proxy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-randomness-collective-flip = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-scheduler = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-transaction-payment-rpc-runtime-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-treasury = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-vesting = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-block-builder = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-core = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-inherents = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-offchain = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-session = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-transaction-pool = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-version = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-block-builder = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-core = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-inherents = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-offchain = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-session = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-std = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-transaction-pool = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-version = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } substrate-fixed = { default-features = false, features = ["serde"], git = "https://github.com/encointer/substrate-fixed" } # Try-Runtime -frame-try-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } +frame-try-runtime = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } # Benchmark -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate", optional = true } -frame-system-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate", optional = true } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate", optional = true } +frame-system-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate", optional = true } # Cumulus -cumulus-pallet-dmp-queue = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-pallet-parachain-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-pallet-xcm = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-pallet-xcmp-queue = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-core = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-timestamp = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -cumulus-primitives-utility = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } -parachain-info = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/cumulus", optional = true } +cumulus-pallet-dmp-queue = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-pallet-parachain-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-pallet-xcm = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-pallet-xcmp-queue = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-core = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-timestamp = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +cumulus-primitives-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } +parachain-info = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } # Parachain @@ -71,14 +72,14 @@ session-keys-primitives = { default-features = false, path = "../../external/ses # Polkadot -polkadot-parachain = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } +polkadot-parachain = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } # Standalone -pallet-aura = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -pallet-grandpa = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-consensus-aura = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-finality-grandpa = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +pallet-aura = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +pallet-grandpa = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-consensus-aura = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-finality-grandpa = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } # Utility cfg-if = { version = "1.0.0" } @@ -86,17 +87,17 @@ hex-literal = { default-features = false, optional = true, version = "0.3.4" } log = { version = "0.4.17", default-features = false, optional = true } # XCM -kusama-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -orml-asset-registry = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-unknown-tokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-xcm-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-xtokens = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -pallet-xcm = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-primitives = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -polkadot-runtime-parachains = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -xcm = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -xcm-builder = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } -xcm-executor = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } +kusama-runtime = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +orml-asset-registry = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-xtokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +pallet-xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-runtime-parachains = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +xcm-builder = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +xcm-executor = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } # Zeitgeist @@ -115,9 +116,9 @@ zrml-swaps = { default-features = false, path = "../../zrml/swaps" } zrml-swaps-runtime-api = { default-features = false, path = "../../zrml/swaps/runtime-api" } [dev-dependencies] -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } test-case = "2.0.2" -xcm-emulator = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/xcm-simulator" } +xcm-emulator = { rev = "158a6bd2768c679563efa891aa17329635b2764b", git = "https://github.com/shaunxw/xcm-simulator" } [features] default = ["std"] @@ -168,7 +169,7 @@ runtime-benchmarks = [ "cumulus-pallet-xcmp-queue?/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", - "frame-system-benchmarking", + "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "hex-literal", "kusama-runtime?/runtime-benchmarks", diff --git a/runtime/zeitgeist/src/integration_tests/xcm/setup.rs b/runtime/zeitgeist/src/integration_tests/xcm/setup.rs index 6ce5521fa..6a7a8bacd 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/setup.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/setup.rs @@ -18,7 +18,7 @@ use crate::{ xcm_config::config::{general_key, zeitgeist}, - AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, Origin, Runtime, System, + AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, RuntimeOrigin, Runtime, System, }; use frame_support::{assert_ok, traits::GenesisBuild}; use orml_traits::asset_registry::AssetMetadata; @@ -133,7 +133,7 @@ pub(super) fn register_foreign_ztg(additional_meta: Option) { additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(Origin::root(), meta, Some(FOREIGN_ZTG_ID))); + assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_ZTG_ID))); } pub(super) fn register_foreign_sibling(additional_meta: Option) { @@ -147,7 +147,7 @@ pub(super) fn register_foreign_sibling(additional_meta: Option) additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(Origin::root(), meta, Some(FOREIGN_SIBLING_ID))); + assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_SIBLING_ID))); } pub(super) fn register_foreign_parent(additional_meta: Option) { @@ -161,7 +161,7 @@ pub(super) fn register_foreign_parent(additional_meta: Option) { additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(Origin::root(), meta, Some(FOREIGN_PARENT_ID))); + assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_PARENT_ID))); } #[inline] diff --git a/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs b/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs index db07a0ca5..71748407a 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs @@ -17,7 +17,7 @@ use crate::{ parameters::ZeitgeistTreasuryAccount, xcm_config::config::zeitgeist, AccountId, CurrencyId, - DmpQueue, Origin, Runtime, XcmpQueue, + DmpQueue, RuntimeOrigin, Runtime, XcmpQueue, }; use frame_support::{traits::GenesisBuild, weights::Weight}; use polkadot_primitives::v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; @@ -37,7 +37,7 @@ decl_test_relay_chain! { decl_test_parachain! { pub struct Zeitgeist { Runtime = Runtime, - Origin = Origin, + RuntimeOrigin = RuntimeOrigin, XcmpMessageHandler = XcmpQueue, DmpMessageHandler = DmpQueue, new_ext = para_ext(zeitgeist::ID), @@ -47,7 +47,7 @@ decl_test_parachain! { decl_test_parachain! { pub struct Sibling { Runtime = Runtime, - Origin = Origin, + RuntimeOrigin = RuntimeOrigin, XcmpMessageHandler = XcmpQueue, DmpMessageHandler = DmpQueue, new_ext = para_ext(PARA_ID_SIBLING), diff --git a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs index 9b7f19032..acb2c5da7 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs @@ -26,7 +26,7 @@ use crate::{ test_net::{KusamaNet, Sibling, TestNet, Zeitgeist}, }, xcm_config::{config::zeitgeist, fees::default_per_second}, - AssetRegistry, Balance, Balances, CurrencyId, Origin, Tokens, XTokens, + AssetRegistry, Balance, Balances, CurrencyId, RuntimeOrigin, Tokens, XTokens, ZeitgeistTreasuryAccount, }; @@ -58,7 +58,7 @@ fn transfer_ztg_to_sibling() { assert_eq!(Balances::free_balance(&ALICE.into()), alice_initial_balance); assert_eq!(Balances::free_balance(&sibling_parachain_account()), 0); assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), + RuntimeOrigin::signed(ALICE.into()), CurrencyId::Ztg, transfer_amount, Box::new( @@ -128,7 +128,7 @@ fn transfer_ztg_sibling_to_zeitgeist() { assert_eq!(Balances::free_balance(&zeitgeist_parachain_account()), 0); assert_eq!(Tokens::free_balance(FOREIGN_ZTG_ID, &BOB.into()), bob_initial_balance); assert_ok!(XTokens::transfer( - Origin::signed(BOB.into()), + RuntimeOrigin::signed(BOB.into()), FOREIGN_ZTG_ID, transfer_amount, Box::new( @@ -215,7 +215,7 @@ fn transfer_ksm_to_relay_chain() { assert!(initial_balance >= transfer_amount); assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), + RuntimeOrigin::signed(ALICE.into()), FOREIGN_PARENT_ID, transfer_amount, Box::new( @@ -274,7 +274,7 @@ fn transfer_ztg_to_sibling_with_custom_fee() { assert_eq!(Balances::free_balance(&ALICE.into()), alice_initial_balance); assert_eq!(Balances::free_balance(&sibling_parachain_account()), 0); assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), + RuntimeOrigin::signed(ALICE.into()), CurrencyId::Ztg, transfer_amount, Box::new( diff --git a/runtime/zeitgeist/src/lib.rs b/runtime/zeitgeist/src/lib.rs index f8759964a..ad1e8b989 100644 --- a/runtime/zeitgeist/src/lib.rs +++ b/runtime/zeitgeist/src/lib.rs @@ -101,8 +101,8 @@ pub struct IsCallable; // Currently disables Court, Rikiddo and creation of markets using Court or SimpleDisputes // dispute mechanism. -impl Contains for IsCallable { - fn contains(call: &Call) -> bool { +impl Contains for IsCallable { + fn contains(call: &RuntimeCall) -> bool { #[cfg(feature = "parachain")] use cumulus_pallet_dmp_queue::Call::service_overweight; use frame_system::Call::{ @@ -124,10 +124,10 @@ impl Contains for IsCallable { #[allow(clippy::match_like_matches_macro)] match call { // Membership is managed by the respective Membership instance - Call::AdvisoryCommittee(set_members { .. }) => false, + RuntimeCall::AdvisoryCommittee(set_members { .. }) => false, // See "balance.set_balance" - Call::AssetManager(update_balance { .. }) => false, - Call::Balances(inner_call) => { + RuntimeCall::AssetManager(update_balance { .. }) => false, + RuntimeCall::Balances(inner_call) => { match inner_call { // Balances should not be set. All newly generated tokens be minted by well // known and approved processes, like staking. However, this could be used @@ -142,12 +142,12 @@ impl Contains for IsCallable { } } // Membership is managed by the respective Membership instance - Call::Council(set_members { .. }) => false, - Call::Court(_) => false, + RuntimeCall::Council(set_members { .. }) => false, + RuntimeCall::Court(_) => false, #[cfg(feature = "parachain")] - Call::DmpQueue(service_overweight { .. }) => false, - Call::LiquidityMining(_) => false, - Call::PredictionMarkets(inner_call) => { + RuntimeCall::DmpQueue(service_overweight { .. }) => false, + RuntimeCall::LiquidityMining(_) => false, + RuntimeCall::PredictionMarkets(inner_call) => { match inner_call { // Disable Rikiddo markets create_market { scoring_rule: RikiddoSigmoidFeeMarketEma, .. } => false, @@ -162,7 +162,7 @@ impl Contains for IsCallable { _ => true, } } - Call::System(inner_call) => { + RuntimeCall::System(inner_call) => { match inner_call { // Some "waste" storage will never impact proper operation. // Cleaning up storage should be done by pallets or independent migrations. @@ -183,9 +183,9 @@ impl Contains for IsCallable { } } // Membership is managed by the respective Membership instance - Call::TechnicalCommittee(set_members { .. }) => false, + RuntimeCall::TechnicalCommittee(set_members { .. }) => false, // There should be no reason to force vested transfer. - Call::Vesting(force_vested_transfer { .. }) => false, + RuntimeCall::Vesting(force_vested_transfer { .. }) => false, _ => true, } } diff --git a/runtime/zeitgeist/src/parachain_params.rs b/runtime/zeitgeist/src/parachain_params.rs index 7cfd9097c..b7193a3e2 100644 --- a/runtime/zeitgeist/src/parachain_params.rs +++ b/runtime/zeitgeist/src/parachain_params.rs @@ -22,7 +22,7 @@ )] #![cfg(feature = "parachain")] -use super::{parameters::MAXIMUM_BLOCK_WEIGHT, Origin, ParachainInfo}; +use super::{parameters::MAXIMUM_BLOCK_WEIGHT, RuntimeOrigin, ParachainInfo}; use frame_support::{parameter_types, weights::Weight}; use orml_traits::parameter_type_with_key; use sp_runtime::{Perbill, Percent}; @@ -43,7 +43,7 @@ parameter_types! { pub const RelayNetwork: NetworkId = NetworkId::Kusama; pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UnitWeightCost: u64 = 200_000_000; // Staking diff --git a/runtime/zeitgeist/src/parameters.rs b/runtime/zeitgeist/src/parameters.rs index d6eef76ad..577bdb56c 100644 --- a/runtime/zeitgeist/src/parameters.rs +++ b/runtime/zeitgeist/src/parameters.rs @@ -28,6 +28,7 @@ use frame_support::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, DispatchClass, Weight, }, + traits::WithdrawReasons, PalletId, }; use frame_system::limits::{BlockLength, BlockWeights}; @@ -351,6 +352,8 @@ parameter_types! { // Vesting pub const MinVestedTransfer: Balance = ExistentialDeposit::get(); + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); } #[cfg(feature = "with-global-disputes")] diff --git a/runtime/zeitgeist/src/xcm_config/config.rs b/runtime/zeitgeist/src/xcm_config/config.rs index 0b1b83b6c..b2fd46231 100644 --- a/runtime/zeitgeist/src/xcm_config/config.rs +++ b/runtime/zeitgeist/src/xcm_config/config.rs @@ -17,8 +17,8 @@ use super::fees::{native_per_second, FixedConversionRateProvider}; use crate::{ - AccountId, Ancestry, AssetManager, AssetRegistry, Balance, Call, CurrencyId, MaxInstructions, - Origin, ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, + AccountId, Ancestry, AssetManager, AssetRegistry, Balance, RuntimeCall, CurrencyId, MaxInstructions, + RuntimeOrigin, ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, UnitWeightCost, UnknownTokens, XcmpQueue, ZeitgeistTreasuryAccount, }; @@ -70,8 +70,8 @@ impl Config for XcmConfig { /// Additional filters that specify whether the XCM instruction should be executed at all. type Barrier = Barrier; /// The outer call dispatch type. - type Call = Call; - type CallDispatcher = Call; + type RuntimeCall = RuntimeCall; + // type CallDispatcher = Call; /// Combinations of (Location, Asset) pairs which are trusted as reserves. // Trust the parent chain, sibling parachains and children chains of this chain. type IsReserve = MultiNativeAsset; @@ -90,7 +90,7 @@ impl Config for XcmConfig { /// The means of determining an XCM message's weight. // Adds UnitWeightCost per instruction plus the weight of each instruction. // The total number of instructions are bounded by MaxInstructions - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; /// How to send an onward XCM message. type XcmSender = XcmRouter; } @@ -262,7 +262,7 @@ impl Convert for AccountIdToMultiLocation { } /// No local origins on this chain are allowed to dispatch XCM sends/executions. -pub type LocalOriginToLocation = SignedToAccountId32; +pub type LocalOriginToLocation = SignedToAccountId32; /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used /// when determining ownership of accounts for asset transacting and when attempting to use XCM @@ -283,18 +283,18 @@ pub type XcmOriginToTransactDispatchOrigin = ( // Sovereign account converter; this attempts to derive an `AccountId` from the origin location // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, + SovereignSignedViaLocation, // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognized. - RelayChainAsNative, + RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when // recognized. - SiblingParachainAsNative, + SiblingParachainAsNative, // Native signed account converter; this just converts an `AccountId32` origin into a normal // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, + SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, + XcmPassthrough, ); /// The means for routing XCM messages which are not for local execution into the right message diff --git a/zrml/authorized/Cargo.toml b/zrml/authorized/Cargo.toml index 7f2098d5f..95c2850de 100644 --- a/zrml/authorized/Cargo.toml +++ b/zrml/authorized/Cargo.toml @@ -1,17 +1,17 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } [features] diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index bcb064678..fff34ff8b 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -120,7 +120,7 @@ mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// Event - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The period, in which the authority can correct the outcome of a market. /// This value must not be zero. @@ -140,7 +140,7 @@ mod pallet { >; /// The origin that is allowed to resolved disupute in Authorized dispute mechanism. - type AuthorizedDisputeResolutionOrigin: EnsureOrigin; + type AuthorizedDisputeResolutionOrigin: EnsureOrigin; /// Identifier of this pallet #[pallet::constant] @@ -193,7 +193,7 @@ mod pallet { type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; type Moment = MomentOf; - type Origin = T::Origin; + type Origin = T::RuntimeOrigin; fn on_dispute( disputes: &[MarketDispute], diff --git a/zrml/authorized/src/mock.rs b/zrml/authorized/src/mock.rs index 49517fc84..eb69c4733 100644 --- a/zrml/authorized/src/mock.rs +++ b/zrml/authorized/src/mock.rs @@ -132,7 +132,7 @@ impl DisputeResolutionApi for MockResolution { } impl crate::Config for Runtime { - type Event = (); + type RuntimeEvent = (); type CorrectionPeriod = CorrectionPeriod; type DisputeResolution = MockResolution; type MarketCommons = MarketCommons; @@ -154,9 +154,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = (); + type RuntimeEvent = (); type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -165,7 +165,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -177,7 +177,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = (); + type RuntimeEvent = (); type ExistentialDeposit = (); type MaxLocks = (); type MaxReserves = MaxReserves; diff --git a/zrml/authorized/src/tests.rs b/zrml/authorized/src/tests.rs index 7cd33883c..aa2844c47 100644 --- a/zrml/authorized/src/tests.rs +++ b/zrml/authorized/src/tests.rs @@ -19,7 +19,7 @@ use crate::{ market_mock, - mock::{Authorized, AuthorizedDisputeResolutionUser, ExtBuilder, Origin, Runtime, BOB}, + mock::{Authorized, AuthorizedDisputeResolutionUser, ExtBuilder, RuntimeOrigin, Runtime, BOB}, mock_storage::pallet as mock_storage, AuthorizedOutcomeReports, Error, }; @@ -35,7 +35,7 @@ fn authorize_market_outcome_inserts_a_new_outcome() { ExtBuilder::default().build().execute_with(|| { Markets::::insert(0, market_mock::()); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1) )); @@ -54,7 +54,7 @@ fn authorize_market_outcome_does_not_reset_dispute_resolution() { Markets::::insert(0, market_mock::()); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1), )); @@ -68,7 +68,7 @@ fn authorize_market_outcome_does_not_reset_dispute_resolution() { assert_eq!(mock_storage::MarketIdsPerDisputeBlock::::get(resolve_at_0), vec![0]); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(2) )); @@ -87,7 +87,7 @@ fn authorize_market_outcome_fails_if_market_does_not_exist() { ExtBuilder::default().build().execute_with(|| { assert_noop!( Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1) ), @@ -104,7 +104,7 @@ fn authorize_market_outcome_fails_on_non_authorized_market() { Markets::::insert(0, market); assert_noop!( Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1) ), @@ -121,7 +121,7 @@ fn authorize_market_outcome_fails_on_undisputed_market() { Markets::::insert(0, market); assert_noop!( Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1) ), @@ -136,7 +136,7 @@ fn authorize_market_outcome_fails_on_invalid_report() { Markets::::insert(0, market_mock::()); assert_noop!( Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Categorical(123) ), @@ -150,7 +150,7 @@ fn authorize_market_outcome_fails_on_unauthorized_account() { ExtBuilder::default().build().execute_with(|| { Markets::::insert(0, market_mock::()); assert_noop!( - Authorized::authorize_market_outcome(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)), + Authorized::authorize_market_outcome(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(1)), DispatchError::BadOrigin, ); }); @@ -182,7 +182,7 @@ fn on_resolution_removes_stored_outcomes() { let market = market_mock::(); Markets::::insert(0, &market); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(2) )); @@ -198,12 +198,12 @@ fn on_resolution_returns_the_reported_outcome() { Markets::::insert(0, &market); // Authorize outcome, then overwrite it. assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1) )); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(2) )); @@ -220,12 +220,12 @@ fn authorized_market_outcome_can_handle_multiple_markets() { Markets::::insert(0, market_mock::()); Markets::::insert(1, market_mock::()); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(123) )); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 1, OutcomeReport::Scalar(456) )); @@ -249,7 +249,7 @@ fn get_auto_resolve_works() { let market = market_mock::(); Markets::::insert(0, &market); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Scalar(1) )); diff --git a/zrml/court/Cargo.toml b/zrml/court/Cargo.toml index 096c6da68..4ff800939 100644 --- a/zrml/court/Cargo.toml +++ b/zrml/court/Cargo.toml @@ -1,20 +1,20 @@ [dependencies] arrayvec = { default-features = false, version = "0.7" } -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } rand = { default-features = false, features = ["alloc", "std_rng"], version = "0.8" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-randomness-collective-flip = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-randomness-collective-flip = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } [features] diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 09671e0b1..2418c62b3 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -160,7 +160,7 @@ mod pallet { >; /// Event - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// Market commons type MarketCommons: MarketCommonsPalletApi< @@ -508,7 +508,7 @@ mod pallet { type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; type Moment = MomentOf; - type Origin = T::Origin; + type Origin = T::RuntimeOrigin; fn on_dispute( disputes: &[MarketDispute], diff --git a/zrml/court/src/mock.rs b/zrml/court/src/mock.rs index fd33e1859..dba4f3cd7 100644 --- a/zrml/court/src/mock.rs +++ b/zrml/court/src/mock.rs @@ -115,7 +115,7 @@ impl DisputeResolutionApi for NoopResolution { impl crate::Config for Runtime { type CourtCaseDuration = CourtCaseDuration; type DisputeResolution = NoopResolution; - type Event = (); + type RuntimeEvent = (); type MarketCommons = MarketCommons; type PalletId = CourtPalletId; type Random = RandomnessCollectiveFlip; @@ -132,9 +132,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = (); + type RuntimeEvent = (); type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -143,7 +143,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -155,7 +155,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = (); + type RuntimeEvent = (); type ExistentialDeposit = (); type MaxLocks = (); type MaxReserves = MaxReserves; diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index a383ac109..a4203c509 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -19,7 +19,7 @@ use crate::{ mock::{ - Balances, Court, ExtBuilder, Origin, RandomnessCollectiveFlip, Runtime, System, ALICE, BOB, + Balances, Court, ExtBuilder, RuntimeOrigin, RandomnessCollectiveFlip, Runtime, System, ALICE, BOB, CHARLIE, INITIAL_BALANCE, }, Error, Juror, JurorStatus, Jurors, MarketOf, RequestedJurors, Votes, @@ -67,11 +67,11 @@ const DEFAULT_SET_OF_JURORS: &[(u128, Juror)] = &[ #[test] fn exit_court_successfully_removes_a_juror_and_frees_balances() { ExtBuilder::default().build().execute_with(|| { - assert_ok!(Court::join_court(Origin::signed(ALICE))); + assert_ok!(Court::join_court(RuntimeOrigin::signed(ALICE))); assert_eq!(Jurors::::iter().count(), 1); assert_eq!(Balances::free_balance(ALICE), 998 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 2 * BASE); - assert_ok!(Court::exit_court(Origin::signed(ALICE))); + assert_ok!(Court::exit_court(RuntimeOrigin::signed(ALICE))); assert_eq!(Jurors::::iter().count(), 0); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 0); @@ -82,7 +82,7 @@ fn exit_court_successfully_removes_a_juror_and_frees_balances() { fn exit_court_will_not_remove_an_unknown_juror() { ExtBuilder::default().build().execute_with(|| { assert_noop!( - Court::exit_court(Origin::signed(ALICE)), + Court::exit_court(RuntimeOrigin::signed(ALICE)), Error::::JurorDoesNotExists ); }); @@ -92,12 +92,12 @@ fn exit_court_will_not_remove_an_unknown_juror() { fn join_court_reserves_balance_according_to_the_number_of_jurors() { ExtBuilder::default().build().execute_with(|| { assert_eq!(Balances::free_balance(ALICE), 1000 * BASE); - assert_ok!(Court::join_court(Origin::signed(ALICE))); + assert_ok!(Court::join_court(RuntimeOrigin::signed(ALICE))); assert_eq!(Balances::free_balance(ALICE), 998 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 2 * BASE); assert_eq!(Balances::free_balance(BOB), 1000 * BASE); - assert_ok!(Court::join_court(Origin::signed(BOB))); + assert_ok!(Court::join_court(RuntimeOrigin::signed(BOB))); assert_eq!(Balances::free_balance(BOB), 996 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &BOB), 4 * BASE); }); @@ -106,7 +106,7 @@ fn join_court_reserves_balance_according_to_the_number_of_jurors() { #[test] fn join_court_successfully_stores_a_juror() { ExtBuilder::default().build().execute_with(|| { - assert_ok!(Court::join_court(Origin::signed(ALICE))); + assert_ok!(Court::join_court(RuntimeOrigin::signed(ALICE))); assert_eq!( Jurors::::iter().next().unwrap(), (ALICE, Juror { status: JurorStatus::Ok }) @@ -117,9 +117,9 @@ fn join_court_successfully_stores_a_juror() { #[test] fn join_court_will_not_insert_an_already_stored_juror() { ExtBuilder::default().build().execute_with(|| { - assert_ok!(Court::join_court(Origin::signed(ALICE))); + assert_ok!(Court::join_court(RuntimeOrigin::signed(ALICE))); assert_noop!( - Court::join_court(Origin::signed(ALICE)), + Court::join_court(RuntimeOrigin::signed(ALICE)), Error::::JurorAlreadyExists ); }); @@ -153,11 +153,11 @@ fn on_resolution_denies_non_court_markets() { fn on_dispute_stores_jurors_that_should_vote() { ExtBuilder::default().build().execute_with(|| { setup_blocks(123); - let _ = Court::join_court(Origin::signed(ALICE)); - let _ = Court::join_court(Origin::signed(BOB)); + let _ = Court::join_court(RuntimeOrigin::signed(ALICE)); + let _ = Court::join_court(RuntimeOrigin::signed(BOB)); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); assert_noop!( - Court::join_court(Origin::signed(ALICE)), + Court::join_court(RuntimeOrigin::signed(ALICE)), Error::::JurorAlreadyExists ); assert_eq!(RequestedJurors::::iter().count(), 2); @@ -169,13 +169,13 @@ fn on_dispute_stores_jurors_that_should_vote() { fn on_resolution_awards_winners_and_slashes_losers() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); - Court::join_court(Origin::signed(ALICE)).unwrap(); - Court::join_court(Origin::signed(BOB)).unwrap(); - Court::join_court(Origin::signed(CHARLIE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(ALICE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(BOB)).unwrap(); + Court::join_court(RuntimeOrigin::signed(CHARLIE)).unwrap(); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); - Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(3)).unwrap(); + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); + Court::vote(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Scalar(3)).unwrap(); let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); assert_eq!(Balances::free_balance(ALICE), 998 * BASE + 3 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 2 * BASE); @@ -190,13 +190,13 @@ fn on_resolution_awards_winners_and_slashes_losers() { fn on_resolution_decides_market_outcome_based_on_the_majority() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); - Court::join_court(Origin::signed(ALICE)).unwrap(); - Court::join_court(Origin::signed(BOB)).unwrap(); - Court::join_court(Origin::signed(CHARLIE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(ALICE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(BOB)).unwrap(); + Court::join_court(RuntimeOrigin::signed(CHARLIE)).unwrap(); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); let outcome = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); assert_eq!(outcome, Some(OutcomeReport::Scalar(1))); }); @@ -206,9 +206,9 @@ fn on_resolution_decides_market_outcome_based_on_the_majority() { fn on_resolution_sets_late_jurors_as_tardy() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); - Court::join_court(Origin::signed(ALICE)).unwrap(); - Court::join_court(Origin::signed(BOB)).unwrap(); - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::join_court(RuntimeOrigin::signed(ALICE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(BOB)).unwrap(); + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(ALICE).unwrap().status, JurorStatus::Ok); @@ -220,13 +220,13 @@ fn on_resolution_sets_late_jurors_as_tardy() { fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tardy() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); - Court::join_court(Origin::signed(ALICE)).unwrap(); - Court::join_court(Origin::signed(BOB)).unwrap(); - Court::join_court(Origin::signed(CHARLIE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(ALICE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(BOB)).unwrap(); + Court::join_court(RuntimeOrigin::signed(CHARLIE)).unwrap(); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(CHARLIE).unwrap().status, JurorStatus::Tardy); }); @@ -236,10 +236,10 @@ fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tard fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); - Court::join_court(Origin::signed(ALICE)).unwrap(); - Court::join_court(Origin::signed(BOB)).unwrap(); + Court::join_court(RuntimeOrigin::signed(ALICE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(BOB)).unwrap(); Court::set_stored_juror_as_tardy(&BOB).unwrap(); - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); let join_court_stake = 40000000000; @@ -254,13 +254,13 @@ fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { fn on_resolution_removes_requested_jurors_and_votes() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); - Court::join_court(Origin::signed(ALICE)).unwrap(); - Court::join_court(Origin::signed(BOB)).unwrap(); - Court::join_court(Origin::signed(CHARLIE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(ALICE)).unwrap(); + Court::join_court(RuntimeOrigin::signed(BOB)).unwrap(); + Court::join_court(RuntimeOrigin::signed(CHARLIE)).unwrap(); Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); + Court::vote(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); assert_eq!(RequestedJurors::::iter().count(), 0); assert_eq!(Votes::::iter().count(), 0); @@ -317,7 +317,7 @@ fn random_jurors_returns_a_subset_of_jurors() { fn vote_will_not_accept_unknown_accounts() { ExtBuilder::default().build().execute_with(|| { assert_noop!( - Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(0)), + Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(0)), Error::::OnlyJurorsCanVote ); }); @@ -326,8 +326,8 @@ fn vote_will_not_accept_unknown_accounts() { #[test] fn vote_will_stored_outcome_from_a_juror() { ExtBuilder::default().build().execute_with(|| { - let _ = Court::join_court(Origin::signed(ALICE)); - let _ = Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(0)); + let _ = Court::join_court(RuntimeOrigin::signed(ALICE)); + let _ = Court::vote(RuntimeOrigin::signed(ALICE), 0, OutcomeReport::Scalar(0)); assert_eq!(Votes::::get(ALICE, 0).unwrap(), (0, OutcomeReport::Scalar(0))); }); } diff --git a/zrml/global-disputes/Cargo.toml b/zrml/global-disputes/Cargo.toml index dde21457d..25a78dbba 100644 --- a/zrml/global-disputes/Cargo.toml +++ b/zrml/global-disputes/Cargo.toml @@ -1,11 +1,11 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-std = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-std = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } @@ -14,9 +14,9 @@ num-traits = { version = "0.2.15", default-features = false, optional = true } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } test-case = "2.0.2" diff --git a/zrml/global-disputes/src/benchmarks.rs b/zrml/global-disputes/src/benchmarks.rs index 486d08cae..aaa7260f8 100644 --- a/zrml/global-disputes/src/benchmarks.rs +++ b/zrml/global-disputes/src/benchmarks.rs @@ -48,7 +48,7 @@ where T::Currency::deposit_creating(caller, BalanceOf::::max_value() / 2u128.saturated_into()); } -fn assert_last_event(generic_event: ::Event) { +fn assert_last_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_last_event(generic_event.into()); } diff --git a/zrml/global-disputes/src/lib.rs b/zrml/global-disputes/src/lib.rs index e71ed9e76..b06ed649f 100644 --- a/zrml/global-disputes/src/lib.rs +++ b/zrml/global-disputes/src/lib.rs @@ -58,7 +58,7 @@ mod pallet { /// The currency implementation used to lock tokens for voting. type Currency: LockableCurrency; - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The vote lock identifier. #[pallet::constant] diff --git a/zrml/global-disputes/src/mock.rs b/zrml/global-disputes/src/mock.rs index 94c87681d..3be6d6bd1 100644 --- a/zrml/global-disputes/src/mock.rs +++ b/zrml/global-disputes/src/mock.rs @@ -63,7 +63,7 @@ parameter_types! { impl crate::Config for Runtime { type Currency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type GlobalDisputeLockId = GlobalDisputeLockId; type GlobalDisputesPalletId = GlobalDisputesPalletId; type MarketCommons = MarketCommons; @@ -83,9 +83,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -94,7 +94,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -106,7 +106,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = (); type MaxLocks = (); type MaxReserves = MaxReserves; diff --git a/zrml/global-disputes/src/tests.rs b/zrml/global-disputes/src/tests.rs index 8c46b357d..14f48b797 100644 --- a/zrml/global-disputes/src/tests.rs +++ b/zrml/global-disputes/src/tests.rs @@ -83,7 +83,7 @@ fn add_vote_outcome_works() { let free_balance_reward_account = Balances::free_balance(GlobalDisputes::reward_account(&market_id)); assert_ok!(GlobalDisputes::add_vote_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), )); @@ -112,7 +112,7 @@ fn add_vote_outcome_fails_if_no_global_dispute_present() { let market_id = 0u128; assert_noop!( GlobalDisputes::add_vote_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), ), @@ -131,7 +131,7 @@ fn add_vote_outcome_fails_if_global_dispute_finished() { assert_noop!( GlobalDisputes::add_vote_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), ), @@ -158,7 +158,7 @@ fn add_vote_outcome_fails_if_outcome_already_exists() { ); assert_noop!( GlobalDisputes::add_vote_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), ), @@ -180,7 +180,7 @@ fn add_vote_outcome_fails_if_balance_too_low() { .unwrap(); assert_noop!( GlobalDisputes::add_vote_outcome( - Origin::signed(POOR_PAUL), + RuntimeOrigin::signed(POOR_PAUL), market_id, OutcomeReport::Scalar(20), ), @@ -216,11 +216,11 @@ fn reward_outcome_owner_works_for_multiple_owners() { let free_balance_bob_before = Balances::free_balance(&BOB); let free_balance_charlie_before = Balances::free_balance(&CHARLIE); - assert_ok!(GlobalDisputes::purge_outcomes(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::purge_outcomes(RuntimeOrigin::signed(ALICE), market_id,)); System::assert_last_event(Event::::OutcomesFullyCleaned { market_id }.into()); - assert_ok!(GlobalDisputes::reward_outcome_owner(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::reward_outcome_owner(RuntimeOrigin::signed(ALICE), market_id,)); System::assert_last_event( Event::::OutcomeOwnersRewarded { @@ -264,9 +264,9 @@ fn reward_outcome_owner_has_dust() { }; >::insert(market_id, winner_info); - assert_ok!(GlobalDisputes::purge_outcomes(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::purge_outcomes(RuntimeOrigin::signed(ALICE), market_id,)); - assert_ok!(GlobalDisputes::reward_outcome_owner(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::reward_outcome_owner(RuntimeOrigin::signed(ALICE), market_id,)); // 100 * BASE = 1_000_000_000_000 checked_div 6 = 166_666_666_666 // 166_666_666_666 * 6 = 999_999_999_996 so 4 left @@ -297,13 +297,13 @@ fn reward_outcome_owner_works_for_one_owner() { }; >::insert(market_id, winner_info); - assert_ok!(GlobalDisputes::purge_outcomes(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::purge_outcomes(RuntimeOrigin::signed(ALICE), market_id,)); System::assert_last_event(Event::::OutcomesFullyCleaned { market_id }.into()); let free_balance_alice_before = Balances::free_balance(&ALICE); - assert_ok!(GlobalDisputes::reward_outcome_owner(Origin::signed(ALICE), market_id)); + assert_ok!(GlobalDisputes::reward_outcome_owner(RuntimeOrigin::signed(ALICE), market_id)); System::assert_last_event( Event::::OutcomeOwnersRewarded { market_id, owners: vec![ALICE] }.into(), @@ -332,7 +332,7 @@ fn reward_outcome_owner_works_for_no_reward_funds() { }; >::insert(market_id, winner_info); - assert_ok!(GlobalDisputes::purge_outcomes(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::purge_outcomes(RuntimeOrigin::signed(ALICE), market_id,)); System::assert_last_event(Event::::OutcomesFullyCleaned { market_id }.into()); @@ -344,7 +344,7 @@ fn reward_outcome_owner_works_for_no_reward_funds() { // so no loosers, who provided the VotingOutcomeFee assert!(reward_account_free_balance.is_zero()); - assert_ok!(GlobalDisputes::reward_outcome_owner(Origin::signed(ALICE), market_id)); + assert_ok!(GlobalDisputes::reward_outcome_owner(RuntimeOrigin::signed(ALICE), market_id)); System::assert_last_event( Event::::OutcomeOwnersRewardedWithNoFunds { market_id }.into(), @@ -391,7 +391,7 @@ fn vote_fails_if_amount_below_min_outcome_vote_amount() { assert_noop!( GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(40), MinOutcomeVoteAmount::get() - 1, @@ -422,7 +422,7 @@ fn vote_fails_for_insufficient_funds() { // Paul does not have 50 * BASE assert_noop!( GlobalDisputes::vote_on_outcome( - Origin::signed(POOR_PAUL), + RuntimeOrigin::signed(POOR_PAUL), market_id, OutcomeReport::Scalar(0), 50 * BASE @@ -440,28 +440,28 @@ fn determine_voting_winner_sets_the_last_outcome_for_same_vote_balances_as_the_c setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(0), 42 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Scalar(20), 42 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Scalar(40), 42 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(60), 42 * BASE @@ -485,7 +485,7 @@ fn vote_on_outcome_check_event() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(60), 42 * BASE @@ -537,7 +537,7 @@ fn reserve_before_init_vote_outcome_is_not_allowed_for_voting() { assert_noop!( GlobalDisputes::vote_on_outcome( - Origin::signed(*disputor), + RuntimeOrigin::signed(*disputor), market_id, OutcomeReport::Scalar(0), arbitrary_amount + 1 @@ -546,7 +546,7 @@ fn reserve_before_init_vote_outcome_is_not_allowed_for_voting() { ); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(*disputor), + RuntimeOrigin::signed(*disputor), market_id, OutcomeReport::Scalar(0), arbitrary_amount @@ -573,7 +573,7 @@ fn transfer_fails_with_fully_locked_balance() { let arbitrary_amount = 42 * BASE; assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(*disputor), + RuntimeOrigin::signed(*disputor), market_id, OutcomeReport::Scalar(0), free_balance_disputor_before - arbitrary_amount @@ -586,10 +586,10 @@ fn transfer_fails_with_fully_locked_balance() { ); assert_noop!( - Balances::transfer(Origin::signed(*disputor), BOB, arbitrary_amount + 1), + Balances::transfer(RuntimeOrigin::signed(*disputor), BOB, arbitrary_amount + 1), pallet_balances::Error::::LiquidityRestrictions ); - assert_ok!(Balances::transfer(Origin::signed(*disputor), BOB, arbitrary_amount)); + assert_ok!(Balances::transfer(RuntimeOrigin::signed(*disputor), BOB, arbitrary_amount)); }); } @@ -605,7 +605,7 @@ fn reserve_fails_with_fully_locked_balance() { let arbitrary_amount = 42 * BASE; assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(*disputor), + RuntimeOrigin::signed(*disputor), market_id, OutcomeReport::Scalar(0), free_balance_disputor_before - arbitrary_amount @@ -633,26 +633,26 @@ fn determine_voting_winner_works_four_outcome_votes() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(0), 10 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Scalar(20), 10 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Scalar(40), 11 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(60), 10 * BASE @@ -680,25 +680,25 @@ fn determine_voting_winner_works_three_outcome_votes() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), 30 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Scalar(40), 50 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Scalar(0), 10 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(0), 41 * BASE @@ -724,25 +724,25 @@ fn determine_voting_winner_works_two_outcome_votes() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(60), 10 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Scalar(20), 50 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Scalar(60), 20 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(60), 21 * BASE @@ -768,7 +768,7 @@ fn determine_voting_winner_works_with_accumulated_votes_for_alice() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), BASE @@ -776,7 +776,7 @@ fn determine_voting_winner_works_with_accumulated_votes_for_alice() { check_outcome_sum(&market_id, OutcomeReport::Scalar(20), BASE); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Scalar(0), 10 * BASE @@ -784,7 +784,7 @@ fn determine_voting_winner_works_with_accumulated_votes_for_alice() { check_outcome_sum(&market_id, OutcomeReport::Scalar(0), 10 * BASE); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), 10 * BASE @@ -792,7 +792,7 @@ fn determine_voting_winner_works_with_accumulated_votes_for_alice() { check_outcome_sum(&market_id, OutcomeReport::Scalar(20), 11 * BASE); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(0), 40 * BASE @@ -802,7 +802,7 @@ fn determine_voting_winner_works_with_accumulated_votes_for_alice() { // Now Alice wins again assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(20), 40 * BASE @@ -826,14 +826,14 @@ fn reward_outcome_owner_cleans_outcome_info() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(0), 10 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Scalar(20), 10 * BASE @@ -845,14 +845,14 @@ fn reward_outcome_owner_cleans_outcome_info() { assert!(GlobalDisputes::determine_voting_winner(&market_id).is_some()); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(BOB), BOB)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(BOB), BOB)); - assert_ok!(GlobalDisputes::purge_outcomes(Origin::signed(ALICE), market_id,)); + assert_ok!(GlobalDisputes::purge_outcomes(RuntimeOrigin::signed(ALICE), market_id,)); System::assert_last_event(Event::::OutcomesFullyCleaned { market_id }.into()); - assert_ok!(GlobalDisputes::reward_outcome_owner(Origin::signed(BOB), market_id,)); + assert_ok!(GlobalDisputes::reward_outcome_owner(RuntimeOrigin::signed(BOB), market_id,)); assert_eq!(>::iter_prefix(market_id).next(), None); }); @@ -866,7 +866,7 @@ fn unlock_clears_lock_info() { setup_vote_outcomes_with_hundred(&market_id); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(0), 50 * BASE @@ -876,7 +876,7 @@ fn unlock_clears_lock_info() { assert_eq!(>::get(ALICE), vec![(market_id, 50 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); assert_eq!(>::get(ALICE), vec![]); }); @@ -917,7 +917,7 @@ fn vote_fails_if_outcome_does_not_exist() { assert_noop!( GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(42), 50 * BASE @@ -944,25 +944,25 @@ fn locking_works_for_one_market() { assert!(Balances::locks(EVE).is_empty()); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id, OutcomeReport::Scalar(0), 50 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Scalar(20), 40 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Scalar(40), 30 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), market_id, OutcomeReport::Scalar(60), 20 * BASE @@ -982,7 +982,7 @@ fn locking_works_for_one_market() { assert_eq!(>::get(ALICE), vec![(market_id, 50 * BASE)]); assert_eq!(Balances::locks(ALICE), vec![the_lock(50 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); assert_eq!(>::get(ALICE), vec![]); assert!(Balances::locks(ALICE).is_empty()); @@ -993,7 +993,7 @@ fn locking_works_for_one_market() { assert_eq!(>::get(EVE), vec![(market_id, 20 * BASE)]); assert_eq!(Balances::locks(EVE), vec![the_lock(20 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(BOB), BOB)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(BOB), BOB)); assert_eq!(>::get(BOB), vec![]); assert!(Balances::locks(BOB).is_empty()); assert_eq!(>::get(CHARLIE), vec![(market_id, 30 * BASE)]); @@ -1001,13 +1001,13 @@ fn locking_works_for_one_market() { assert_eq!(>::get(EVE), vec![(market_id, 20 * BASE)]); assert_eq!(Balances::locks(EVE), vec![the_lock(20 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(CHARLIE), CHARLIE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(CHARLIE), CHARLIE)); assert_eq!(>::get(CHARLIE), vec![]); assert!(Balances::locks(CHARLIE).is_empty()); assert_eq!(>::get(EVE), vec![(market_id, 20 * BASE)]); assert_eq!(Balances::locks(EVE), vec![the_lock(20 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(EVE), EVE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(EVE), EVE)); assert_eq!(>::get(EVE), vec![]); assert!(Balances::locks(EVE).is_empty()); }); @@ -1028,26 +1028,26 @@ fn locking_works_for_two_markets_with_stronger_first_unlock() { assert!(Balances::locks(BOB).is_empty()); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id_1, OutcomeReport::Scalar(0), 50 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id_1, OutcomeReport::Scalar(20), 40 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id_2, OutcomeReport::Scalar(0), 30 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id_2, OutcomeReport::Scalar(20), 20 * BASE @@ -1072,7 +1072,7 @@ fn locking_works_for_two_markets_with_stronger_first_unlock() { vec![(market_id_1, 50 * BASE), (market_id_2, 30 * BASE)] ); assert_eq!(Balances::locks(ALICE), vec![the_lock(50 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); assert_eq!(>::get(ALICE), vec![(market_id_2, 30 * BASE)]); assert_eq!(Balances::locks(ALICE), vec![the_lock(30 * BASE)]); assert_eq!( @@ -1081,7 +1081,7 @@ fn locking_works_for_two_markets_with_stronger_first_unlock() { ); assert_eq!(Balances::locks(BOB), vec![the_lock(40 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(BOB), BOB)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(BOB), BOB)); assert_eq!(>::get(BOB), vec![(market_id_2, 20 * BASE)]); assert_eq!(Balances::locks(BOB), vec![the_lock(20 * BASE)]); assert_eq!(>::get(ALICE), vec![(market_id_2, 30 * BASE)]); @@ -1090,14 +1090,14 @@ fn locking_works_for_two_markets_with_stronger_first_unlock() { assert!(GlobalDisputes::determine_voting_winner(&market_id_2).is_some()); assert_eq!(>::get(ALICE), vec![(market_id_2, 30 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); assert_eq!(>::get(ALICE), vec![]); assert!(Balances::locks(ALICE).is_empty()); assert_eq!(>::get(BOB), vec![(market_id_2, 20 * BASE)]); assert_eq!(Balances::locks(BOB), vec![the_lock(20 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(BOB), BOB)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(BOB), BOB)); assert_eq!(>::get(BOB), vec![]); assert!(Balances::locks(BOB).is_empty()); }); @@ -1118,26 +1118,26 @@ fn locking_works_for_two_markets_with_weaker_first_unlock() { assert!(Balances::locks(BOB).is_empty()); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id_1, OutcomeReport::Scalar(0), 50 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id_1, OutcomeReport::Scalar(20), 40 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), market_id_2, OutcomeReport::Scalar(0), 30 * BASE )); assert_ok!(GlobalDisputes::vote_on_outcome( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id_2, OutcomeReport::Scalar(20), 20 * BASE @@ -1162,7 +1162,7 @@ fn locking_works_for_two_markets_with_weaker_first_unlock() { vec![(market_id_1, 50 * BASE), (market_id_2, 30 * BASE)] ); assert_eq!(Balances::locks(ALICE), vec![the_lock(50 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); assert_eq!(>::get(ALICE), vec![(market_id_1, 50 * BASE)]); assert_eq!(Balances::locks(ALICE), vec![the_lock(50 * BASE)]); assert_eq!( @@ -1171,7 +1171,7 @@ fn locking_works_for_two_markets_with_weaker_first_unlock() { ); assert_eq!(Balances::locks(BOB), vec![the_lock(40 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(BOB), BOB)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(BOB), BOB)); assert_eq!(>::get(BOB), vec![(market_id_1, 40 * BASE)]); assert_eq!(Balances::locks(BOB), vec![the_lock(40 * BASE)]); assert_eq!(>::get(ALICE), vec![(market_id_1, 50 * BASE)]); @@ -1181,14 +1181,14 @@ fn locking_works_for_two_markets_with_weaker_first_unlock() { assert_eq!(>::get(ALICE), vec![(market_id_1, 50 * BASE)]); assert_eq!(Balances::locks(ALICE), vec![the_lock(50 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(ALICE), ALICE)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(ALICE), ALICE)); assert_eq!(>::get(ALICE), vec![]); assert!(Balances::locks(ALICE).is_empty()); assert_eq!(>::get(BOB), vec![(market_id_1, 40 * BASE)]); assert_eq!(Balances::locks(BOB), vec![the_lock(40 * BASE)]); - assert_ok!(GlobalDisputes::unlock_vote_balance(Origin::signed(BOB), BOB)); + assert_ok!(GlobalDisputes::unlock_vote_balance(RuntimeOrigin::signed(BOB), BOB)); assert_eq!(>::get(BOB), vec![]); assert!(Balances::locks(BOB).is_empty()); }); diff --git a/zrml/liquidity-mining/Cargo.toml b/zrml/liquidity-mining/Cargo.toml index 7559a5db9..f143dff10 100644 --- a/zrml/liquidity-mining/Cargo.toml +++ b/zrml/liquidity-mining/Cargo.toml @@ -1,18 +1,18 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate", optional = true } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate", optional = true } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { default-features = false, optional = true, version = "1.0.144" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } [features] diff --git a/zrml/liquidity-mining/src/lib.rs b/zrml/liquidity-mining/src/lib.rs index 76cc13ac2..acb18915a 100644 --- a/zrml/liquidity-mining/src/lib.rs +++ b/zrml/liquidity-mining/src/lib.rs @@ -100,7 +100,7 @@ mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; type MarketCommons: MarketCommonsPalletApi< AccountId = Self::AccountId, diff --git a/zrml/liquidity-mining/src/mock.rs b/zrml/liquidity-mining/src/mock.rs index b4660ff92..912b7ad9b 100644 --- a/zrml/liquidity-mining/src/mock.rs +++ b/zrml/liquidity-mining/src/mock.rs @@ -56,7 +56,7 @@ construct_runtime!( ); impl crate::Config for Runtime { - type Event = (); + type RuntimeEvent = (); type MarketCommons = MarketCommons; type MarketId = MarketId; type PalletId = LiquidityMiningPalletId; @@ -71,9 +71,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = (); + type RuntimeEvent = (); type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -82,7 +82,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -95,7 +95,7 @@ impl pallet_balances::Config for Runtime { type Balance = Balance; type DustRemoval = (); type ReserveIdentifier = [u8; 8]; - type Event = (); + type RuntimeEvent = (); type ExistentialDeposit = ExistentialDeposit; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; diff --git a/zrml/liquidity-mining/src/tests.rs b/zrml/liquidity-mining/src/tests.rs index 8486df344..5023a06c5 100644 --- a/zrml/liquidity-mining/src/tests.rs +++ b/zrml/liquidity-mining/src/tests.rs @@ -18,7 +18,7 @@ #![cfg(test)] use crate::{ - mock::{Balances, ExtBuilder, LiquidityMining, Origin, Runtime, System, ALICE, BOB}, + mock::{Balances, ExtBuilder, LiquidityMining, RuntimeOrigin, Runtime, System, ALICE, BOB}, track_incentives_based_on_bought_shares::TrackIncentivesBasedOnBoughtShares, track_incentives_based_on_sold_shares::TrackIncentivesBasedOnSoldShares, BlockBoughtShares, BlockSoldShares, LiquidityMiningPalletApi as _, OwnedValues, @@ -192,7 +192,7 @@ fn only_sudo_can_change_per_block_distribution() { ExtBuilder::default().build().execute_with(|| { assert_ok!(LiquidityMining::set_per_block_distribution(RawOrigin::Root.into(), 100)); assert_err!( - LiquidityMining::set_per_block_distribution(Origin::signed(ALICE), 100), + LiquidityMining::set_per_block_distribution(RuntimeOrigin::signed(ALICE), 100), DispatchError::BadOrigin ); }); diff --git a/zrml/market-commons/Cargo.toml b/zrml/market-commons/Cargo.toml index ad44a7d7e..ae85191f5 100644 --- a/zrml/market-commons/Cargo.toml +++ b/zrml/market-commons/Cargo.toml @@ -1,16 +1,16 @@ [dependencies] -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-arithmetic = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-arithmetic = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } [features] diff --git a/zrml/market-commons/src/mock.rs b/zrml/market-commons/src/mock.rs index 46f374882..393b97de2 100644 --- a/zrml/market-commons/src/mock.rs +++ b/zrml/market-commons/src/mock.rs @@ -60,9 +60,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = (); + type RuntimeEvent = (); type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -71,7 +71,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -83,7 +83,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = (); + type RuntimeEvent = (); type ExistentialDeposit = (); type MaxLocks = (); type MaxReserves = MaxReserves; diff --git a/zrml/orderbook-v1/Cargo.toml b/zrml/orderbook-v1/Cargo.toml index f05ad24a4..e2e7dd6ce 100644 --- a/zrml/orderbook-v1/Cargo.toml +++ b/zrml/orderbook-v1/Cargo.toml @@ -1,18 +1,18 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } # Mock -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +orml-tokens = { branch = "polkadot-v0.9.32", git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } [dev-dependencies] zrml-orderbook-v1 = { features = ["mock"], path = "." } diff --git a/zrml/orderbook-v1/fuzz/Cargo.toml b/zrml/orderbook-v1/fuzz/Cargo.toml index b2c36842f..fcde37c37 100644 --- a/zrml/orderbook-v1/fuzz/Cargo.toml +++ b/zrml/orderbook-v1/fuzz/Cargo.toml @@ -6,7 +6,7 @@ test = false [dependencies] arbitrary = { features = ["derive"], version = "1.0" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } libfuzzer-sys = "0.4" zeitgeist-primitives = { path = "../../../primitives" } zrml-orderbook-v1 = { features = ["mock"], path = ".." } diff --git a/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs b/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs index c624197df..02adff777 100644 --- a/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs +++ b/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs @@ -34,31 +34,31 @@ fuzz_target!(|data: Data| { // Make arbitrary order and attempt to fill let order_asset = asset(data.make_fill_order_asset); let order_hash = Orderbook::order_hash( - &ensure_signed(Origin::signed(data.make_fill_order_origin.into())).unwrap(), + &ensure_signed(RuntimeOrigin::signed(data.make_fill_order_origin.into())).unwrap(), order_asset, Orderbook::nonce(), ); let _ = Orderbook::make_order( - Origin::signed(data.make_fill_order_origin.into()), + RuntimeOrigin::signed(data.make_fill_order_origin.into()), order_asset, orderside(data.make_fill_order_side), data.make_fill_order_amount, data.make_fill_order_price, ); - let _ = Orderbook::fill_order(Origin::signed(data.fill_order_origin.into()), order_hash); + let _ = Orderbook::fill_order(RuntimeOrigin::signed(data.fill_order_origin.into()), order_hash); // Make arbitrary order and attempt to cancel let order_asset = asset(data.make_cancel_order_asset); let order_hash = Orderbook::order_hash( - &ensure_signed(Origin::signed(data.make_cancel_order_origin.into())).unwrap(), + &ensure_signed(RuntimeOrigin::signed(data.make_cancel_order_origin.into())).unwrap(), order_asset, Orderbook::nonce(), ); let _ = Orderbook::make_order( - Origin::signed(data.make_cancel_order_origin.into()), + RuntimeOrigin::signed(data.make_cancel_order_origin.into()), order_asset, orderside(data.make_cancel_order_side), data.make_cancel_order_amount, @@ -66,7 +66,7 @@ fuzz_target!(|data: Data| { ); let _ = Orderbook::cancel_order( - Origin::signed(data.make_cancel_order_origin.into()), + RuntimeOrigin::signed(data.make_cancel_order_origin.into()), order_asset, order_hash, ); diff --git a/zrml/orderbook-v1/src/lib.rs b/zrml/orderbook-v1/src/lib.rs index 61cf64ad7..c97f84cec 100644 --- a/zrml/orderbook-v1/src/lib.rs +++ b/zrml/orderbook-v1/src/lib.rs @@ -256,7 +256,7 @@ mod pallet { pub trait Config: frame_system::Config { type Currency: ReservableCurrency; - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; type MarketId: MarketId; diff --git a/zrml/orderbook-v1/src/mock.rs b/zrml/orderbook-v1/src/mock.rs index 6b71f3c2d..832454948 100644 --- a/zrml/orderbook-v1/src/mock.rs +++ b/zrml/orderbook-v1/src/mock.rs @@ -52,7 +52,7 @@ construct_runtime!( impl crate::Config for Runtime { type Currency = Balances; - type Event = (); + type RuntimeEvent = (); type MarketId = MarketId; type Shares = Tokens; type WeightInfo = orderbook_v1::weights::WeightInfo; @@ -66,9 +66,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = (); + type RuntimeEvent = (); type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -77,7 +77,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -90,13 +90,11 @@ impl orml_tokens::Config for Runtime { type Balance = Balance; type CurrencyId = CurrencyId; type DustRemovalWhitelist = Everything; - type Event = (); + type RuntimeEvent = (); type ExistentialDeposits = ExistentialDeposits; type MaxLocks = (); type MaxReserves = MaxReserves; - type OnDust = (); - type OnKilledTokenAccount = (); - type OnNewTokenAccount = (); + type CurrencyHooks = (); type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } @@ -105,7 +103,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = (); + type RuntimeEvent = (); type ExistentialDeposit = ExistentialDeposit; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; diff --git a/zrml/orderbook-v1/src/tests.rs b/zrml/orderbook-v1/src/tests.rs index e448ba140..26c8be49e 100644 --- a/zrml/orderbook-v1/src/tests.rs +++ b/zrml/orderbook-v1/src/tests.rs @@ -34,7 +34,7 @@ fn it_makes_orders() { // Make an order from Alice to buy shares. assert_ok!(Orderbook::make_order( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::CategoricalOutcome(0, 2), OrderSide::Bid, 25, @@ -47,7 +47,7 @@ fn it_makes_orders() { // Make an order from Bob to sell shares. assert_ok!(Orderbook::make_order( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), Asset::CategoricalOutcome(0, 1), OrderSide::Ask, 10, @@ -67,7 +67,7 @@ fn it_takes_orders() { // Make an order from Bob to sell shares. assert_ok!(Orderbook::make_order( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), Asset::CategoricalOutcome(0, 1), OrderSide::Ask, 10, @@ -75,7 +75,7 @@ fn it_takes_orders() { )); let order_hash = Orderbook::order_hash(&BOB, Asset::CategoricalOutcome(0, 1), 0); - assert_ok!(Orderbook::fill_order(Origin::signed(ALICE), order_hash)); + assert_ok!(Orderbook::fill_order(RuntimeOrigin::signed(ALICE), order_hash)); let alice_bal = >::free_balance(&ALICE); let alice_shares = Tokens::free_balance(Asset::CategoricalOutcome(0, 1), &ALICE); @@ -94,15 +94,15 @@ fn it_cancels_orders() { ExtBuilder::default().build().execute_with(|| { // Make an order from Alice to buy shares. let share_id = Asset::CategoricalOutcome(0, 2); - assert_ok!(Orderbook::make_order(Origin::signed(ALICE), share_id, OrderSide::Bid, 25, 10)); + assert_ok!(Orderbook::make_order(RuntimeOrigin::signed(ALICE), share_id, OrderSide::Bid, 25, 10)); let order_hash = Orderbook::order_hash(&ALICE, share_id, 0); assert_noop!( - Orderbook::cancel_order(Origin::signed(BOB), share_id, order_hash), + Orderbook::cancel_order(RuntimeOrigin::signed(BOB), share_id, order_hash), Error::::NotOrderCreator, ); - assert_ok!(Orderbook::cancel_order(Origin::signed(ALICE), share_id, order_hash)); + assert_ok!(Orderbook::cancel_order(RuntimeOrigin::signed(ALICE), share_id, order_hash)); }); } diff --git a/zrml/prediction-markets/Cargo.toml b/zrml/prediction-markets/Cargo.toml index f12cf796f..b8a119af2 100644 --- a/zrml/prediction-markets/Cargo.toml +++ b/zrml/prediction-markets/Cargo.toml @@ -1,13 +1,13 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.144", default-features = false, optional = true } -sp-arithmetic = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-arithmetic = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-authorized = { default-features = false, path = "../authorized" } zrml-court = { default-features = false, path = "../court" } @@ -19,17 +19,17 @@ zrml-simple-disputes = { default-features = false, path = "../simple-disputes" } # Mock -orml-asset-registry = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -pallet-randomness-collective-flip = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate", optional = true } -pallet-treasury = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +orml-asset-registry = { branch = "polkadot-v0.9.32", git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-currencies = { branch = "polkadot-v0.9.32", git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-tokens = { branch = "polkadot-v0.9.32", git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +pallet-randomness-collective-flip = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +pallet-timestamp = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate", optional = true } +pallet-treasury = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sp-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } substrate-fixed = { optional = true, git = "https://github.com/encointer/substrate-fixed" } -xcm = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/polkadot", optional = true, default-features = false } +xcm = { branch = "release-v0.9.32", git = "https://github.com/paritytech/polkadot", optional = true, default-features = false } zrml-prediction-markets-runtime-api = { features = ["std"], optional = true, path = "./runtime-api" } zrml-rikiddo = { optional = true, path = "../rikiddo" } zrml-swaps = { optional = true, path = "../swaps" } diff --git a/zrml/prediction-markets/fuzz/Cargo.toml b/zrml/prediction-markets/fuzz/Cargo.toml index f0813cf25..e35beb6a4 100644 --- a/zrml/prediction-markets/fuzz/Cargo.toml +++ b/zrml/prediction-markets/fuzz/Cargo.toml @@ -6,7 +6,7 @@ test = false [dependencies] arbitrary = { features = ["derive"], version = "1.0" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } libfuzzer-sys = "0.4" zeitgeist-primitives = { features = ["arbitrary", "mock"], default-features = false, path = "../../../primitives" } zrml-prediction-markets = { features = ["mock"], path = ".." } diff --git a/zrml/prediction-markets/fuzz/pm_full_workflow.rs b/zrml/prediction-markets/fuzz/pm_full_workflow.rs index 0ca237096..c97116f4a 100644 --- a/zrml/prediction-markets/fuzz/pm_full_workflow.rs +++ b/zrml/prediction-markets/fuzz/pm_full_workflow.rs @@ -25,7 +25,7 @@ use zeitgeist_primitives::types::{ Asset, Deadlines, MarketCreation, MarketDisputeMechanism, MarketPeriod, MarketType, MultiHash, OutcomeReport, ScoringRule, }; -use zrml_prediction_markets::mock::{ExtBuilder, Origin, PredictionMarkets, System}; +use zrml_prediction_markets::mock::{ExtBuilder, RuntimeOrigin, PredictionMarkets, System}; fuzz_target!(|data: Data| { let mut ext = ExtBuilder::default().build(); @@ -39,7 +39,7 @@ fuzz_target!(|data: Data| { dispute_duration: 3_u32.into(), }; let _ = PredictionMarkets::create_market( - Origin::signed(data.create_scalar_market_origin.into()), + RuntimeOrigin::signed(data.create_scalar_market_origin.into()), Asset::Ztg, data.create_scalar_market_oracle.into(), MarketPeriod::Block(data.create_scalar_market_period), @@ -55,7 +55,7 @@ fuzz_target!(|data: Data| { System::set_block_number(2); let _ = PredictionMarkets::buy_complete_set( - Origin::signed(data.buy_complete_set_origin.into()), + RuntimeOrigin::signed(data.buy_complete_set_origin.into()), data.buy_complete_set_market_id.into(), data.buy_complete_set_amount, ); @@ -63,7 +63,7 @@ fuzz_target!(|data: Data| { System::set_block_number(3); let _ = PredictionMarkets::report( - Origin::signed(data.report_origin.into()), + RuntimeOrigin::signed(data.report_origin.into()), data.report_market_id.into(), outcome(data.report_outcome), ); @@ -73,7 +73,7 @@ fuzz_target!(|data: Data| { let dispute_market_id = data.dispute_market_id.into(); let _ = PredictionMarkets::dispute( - Origin::signed(data.report_origin.into()), + RuntimeOrigin::signed(data.report_origin.into()), dispute_market_id, outcome(data.report_outcome), ); @@ -82,7 +82,7 @@ fuzz_target!(|data: Data| { System::set_block_number(5); let _ = PredictionMarkets::redeem_shares( - Origin::signed(data.redeem_origin.into()), + RuntimeOrigin::signed(data.redeem_origin.into()), data.redeem_market_id.into(), ); diff --git a/zrml/prediction-markets/runtime-api/Cargo.toml b/zrml/prediction-markets/runtime-api/Cargo.toml index 194f41697..b7bb2c86b 100644 --- a/zrml/prediction-markets/runtime-api/Cargo.toml +++ b/zrml/prediction-markets/runtime-api/Cargo.toml @@ -1,6 +1,6 @@ [dependencies] parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../../primitives" } [features] diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index f6e0cebe4..100a6b7ad 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -48,7 +48,7 @@ use zrml_market_commons::MarketCommonsPalletApi; use frame_support::{traits::Hooks, BoundedVec}; -fn assert_last_event(generic_event: ::Event) { +fn assert_last_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_last_event(generic_event.into()); } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index bf8ff9213..7264cae74 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -36,7 +36,7 @@ mod pallet { use alloc::{format, vec, vec::Vec}; use core::{cmp, marker::PhantomData}; use frame_support::{ - dispatch::{DispatchResultWithPostInfo, Weight}, + dispatch::{DispatchResultWithPostInfo, Pays, Weight}, ensure, log, pallet_prelude::{ConstU32, StorageMap, StorageValue, ValueQuery}, storage::{with_transaction, TransactionOutcome}, @@ -45,7 +45,6 @@ mod pallet { NamedReservableCurrency, OnUnbalanced, StorageVersion, }, transactional, - weights::Pays, Blake2_128Concat, BoundedVec, PalletId, Twox64Concat, }; use frame_system::{ensure_signed, pallet_prelude::OriginFor}; @@ -1525,7 +1524,7 @@ mod pallet { type AdvisoryBondSlashPercentage: Get; /// The origin that is allowed to approve / reject pending advised markets. - type ApproveOrigin: EnsureOrigin; + type ApproveOrigin: EnsureOrigin; /// Shares of outcome assets and native currency type AssetManager: ZeitgeistAssetManager< @@ -1549,11 +1548,11 @@ mod pallet { BlockNumber = Self::BlockNumber, MarketId = MarketIdOf, Moment = MomentOf, - Origin = Self::Origin, + Origin = Self::RuntimeOrigin, >; /// The origin that is allowed to close markets. - type CloseOrigin: EnsureOrigin; + type CloseOrigin: EnsureOrigin; /// See [`zrml_court::CourtPalletApi`]. type Court: zrml_court::CourtPalletApi< @@ -1562,11 +1561,11 @@ mod pallet { BlockNumber = Self::BlockNumber, MarketId = MarketIdOf, Moment = MomentOf, - Origin = Self::Origin, + Origin = Self::RuntimeOrigin, >; /// The origin that is allowed to destroy markets. - type DestroyOrigin: EnsureOrigin; + type DestroyOrigin: EnsureOrigin; /// The base amount of currency that must be bonded in order to create a dispute. #[pallet::constant] @@ -1578,7 +1577,7 @@ mod pallet { type DisputeFactor: Get>; /// Event - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// See [`GlobalDisputesPalletApi`]. #[cfg(feature = "with-global-disputes")] @@ -1663,7 +1662,7 @@ mod pallet { type PalletId: Get; /// The origin that is allowed to reject pending advised markets. - type RejectOrigin: EnsureOrigin; + type RejectOrigin: EnsureOrigin; /// The base amount of currency that must be bonded to ensure the oracle reports /// in a timely manner. @@ -1671,10 +1670,10 @@ mod pallet { type OracleBond: Get>; /// The origin that is allowed to request edits in pending advised markets. - type RequestEditOrigin: EnsureOrigin; + type RequestEditOrigin: EnsureOrigin; /// The origin that is allowed to resolve markets. - type ResolveOrigin: EnsureOrigin; + type ResolveOrigin: EnsureOrigin; /// See [`DisputeApi`]. type SimpleDisputes: DisputeApi< @@ -1683,7 +1682,7 @@ mod pallet { BlockNumber = Self::BlockNumber, MarketId = MarketIdOf, Moment = MomentOf, - Origin = Self::Origin, + Origin = Self::RuntimeOrigin, >; /// Handler for slashed funds. diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 1f6fab770..6073e7bdf 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -25,8 +25,8 @@ use alloc::format; use alloc::vec::Vec; #[cfg(feature = "try-runtime")] use frame_support::migration::storage_key_iter; -#[cfg(feature = "try-runtime")] -use frame_support::traits::OnRuntimeUpgradeHelpersExt; +// #[cfg(feature = "try-runtime")] +// use frame_support::traits::OnRuntimeUpgradeHelpersExt; use frame_support::{ dispatch::Weight, log, @@ -149,7 +149,7 @@ impl OnRuntimeUpgrade for AddOutsiderBo } #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result<(), &'static str> { + fn pre_upgrade() -> Result, &'static str> { use frame_support::pallet_prelude::Blake2_128Concat; let old_markets = storage_key_iter::, OldMarketOf, Blake2_128Concat>( @@ -157,27 +157,29 @@ impl OnRuntimeUpgrade for AddOutsiderBo MARKETS, ) .collect::>(); - Self::set_temp_storage(old_markets, "old_markets"); + // Self::set_temp_storage(old_markets, "old_markets"); - let markets = Markets::::iter_keys().count() as u32; - let decodable_markets = Markets::::iter_values().count() as u32; - if markets != decodable_markets { - log::error!( - "Can only decode {} of {} markets - others will be dropped", - decodable_markets, - markets - ); - } else { - log::info!("Markets: {}, Decodable Markets: {}", markets, decodable_markets); - } + // let markets = Markets::::iter_keys().count() as u32; + // let decodable_markets = Markets::::iter_values().count() as u32; + // if markets != decodable_markets { + // log::error!( + // "Can only decode {} of {} markets - others will be dropped", + // decodable_markets, + // markets + // ); + // } else { + // log::info!("Markets: {}, Decodable Markets: {}", markets, decodable_markets); + // } - Ok(()) + Ok(old_markets.encode()) } #[cfg(feature = "try-runtime")] - fn post_upgrade() -> Result<(), &'static str> { + fn post_upgrade(old_markets: Vec) -> Result<(), &'static str> { + // let old_markets: BTreeMap, OldMarketOf> = + // Self::get_temp_storage("old_markets").unwrap(); let old_markets: BTreeMap, OldMarketOf> = - Self::get_temp_storage("old_markets").unwrap(); + Decode::decode(&mut old_markets.as_slice()).expect("old_markets not generated properly by pre_upgrade"); let new_market_count = >::market_iter().count(); assert_eq!(old_markets.len(), new_market_count); for (market_id, new_market) in >::market_iter() { diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index b537658c6..4046d8df5 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -104,7 +104,7 @@ construct_runtime!( SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, GlobalDisputes: zrml_global_disputes::{Event, Pallet, Storage}, Swaps: zrml_swaps::{Call, Event, Pallet}, - System: frame_system::{Config, Event, Pallet, Storage}, + System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet}, Tokens: orml_tokens::{Config, Event, Pallet, Storage}, Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, @@ -130,7 +130,7 @@ construct_runtime!( RikiddoSigmoidFeeMarketEma: zrml_rikiddo::{Pallet, Storage}, SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, Swaps: zrml_swaps::{Call, Event, Pallet}, - System: frame_system::{Config, Event, Pallet, Storage}, + System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet}, Tokens: orml_tokens::{Config, Event, Pallet, Storage}, Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, @@ -149,7 +149,7 @@ impl crate::Config for Runtime { type DestroyOrigin = EnsureSignedBy; type DisputeBond = DisputeBond; type DisputeFactor = DisputeFactor; - type Event = Event; + type RuntimeEvent = RuntimeEvent; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; #[cfg(feature = "with-global-disputes")] @@ -190,9 +190,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -202,7 +202,7 @@ impl frame_system::Config for Runtime { type OnKilledAccount = (); type OnNewAccount = (); type OnSetCode = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -221,13 +221,11 @@ impl orml_tokens::Config for Runtime { type Balance = Balance; type CurrencyId = CurrencyId; type DustRemovalWhitelist = Everything; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposits = ExistentialDeposits; type MaxLocks = (); type MaxReserves = MaxReserves; - type OnDust = (); - type OnKilledTokenAccount = (); - type OnNewTokenAccount = (); + type CurrencyHooks = (); type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } @@ -244,7 +242,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type MaxLocks = (); type MaxReserves = MaxReserves; @@ -269,7 +267,7 @@ impl zrml_authorized::Config for Runtime { type AuthorizedDisputeResolutionOrigin = EnsureSignedBy; type CorrectionPeriod = CorrectionPeriod; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type DisputeResolution = prediction_markets::Pallet; type MarketCommons = MarketCommons; type PalletId = AuthorizedPalletId; @@ -279,7 +277,7 @@ impl zrml_authorized::Config for Runtime { impl zrml_court::Config for Runtime { type CourtCaseDuration = CourtCaseDuration; type DisputeResolution = prediction_markets::Pallet; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type PalletId = CourtPalletId; type Random = RandomnessCollectiveFlip; @@ -289,7 +287,7 @@ impl zrml_court::Config for Runtime { } impl zrml_liquidity_mining::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type MarketId = MarketId; type PalletId = LiquidityMiningPalletId; @@ -319,7 +317,7 @@ impl zrml_rikiddo::Config for Runtime { } impl zrml_simple_disputes::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type DisputeResolution = prediction_markets::Pallet; type MarketCommons = MarketCommons; type PalletId = SimpleDisputesPalletId; @@ -327,7 +325,7 @@ impl zrml_simple_disputes::Config for Runtime { #[cfg(feature = "with-global-disputes")] impl zrml_global_disputes::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type Currency = Balances; type GlobalDisputeLockId = GlobalDisputeLockId; @@ -341,7 +339,7 @@ impl zrml_global_disputes::Config for Runtime { } impl zrml_swaps::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExitFee = ExitFee; type FixedTypeU = ::FixedTypeU; type FixedTypeS = ::FixedTypeS; @@ -369,7 +367,7 @@ impl pallet_treasury::Config for Runtime { type Burn = (); type BurnDestination = (); type Currency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxApprovals = MaxApprovals; type OnSlash = (); type PalletId = TreasuryPalletId; diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 576e34ea1..1bc046ebd 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -94,7 +94,7 @@ fn simple_create_categorical_market( scoring_rule: ScoringRule, ) { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(period), @@ -114,7 +114,7 @@ fn simple_create_scalar_market( scoring_rule: ScoringRule, ) { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(period), @@ -141,7 +141,7 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_blocknumb ); run_blocks(3); let market_id = 0; - assert_ok!(PredictionMarkets::admin_move_market_to_closed(Origin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), market_id)); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Closed); let new_end = now + 3; @@ -161,7 +161,7 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_timestamp let end = start + 42.saturated_into::() * MILLISECS_PER_BLOCK as u64; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(start..end), @@ -182,7 +182,7 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_timestamp set_timestamp_for_on_initialize(start + shift + MILLISECS_PER_BLOCK as u64); run_blocks(shift_blocks); - assert_ok!(PredictionMarkets::admin_move_market_to_closed(Origin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), market_id)); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Closed); let new_end = start + shift; @@ -196,7 +196,7 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_timestamp fn admin_move_market_to_closed_fails_if_market_does_not_exist() { ExtBuilder::default().build().execute_with(|| { assert_noop!( - PredictionMarkets::admin_move_market_to_closed(Origin::signed(SUDO), 0), + PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), 0), zrml_market_commons::Error::::MarketDoesNotExist ); }); @@ -223,7 +223,7 @@ fn admin_move_market_to_closed_fails_if_market_is_not_active(market_status: Mark Ok(()) })); assert_noop!( - PredictionMarkets::admin_move_market_to_closed(Origin::signed(SUDO), market_id), + PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), market_id), Error::::MarketIsNotActive, ); }); @@ -234,7 +234,7 @@ fn admin_move_market_to_closed_correctly_clears_auto_open_and_close_blocks() { ExtBuilder::default().build().execute_with(|| { let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(22..66), @@ -247,7 +247,7 @@ fn admin_move_market_to_closed_correctly_clears_auto_open_and_close_blocks() { vec![::MinWeight::get(); category_count.into()], )); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(33..66), @@ -260,7 +260,7 @@ fn admin_move_market_to_closed_correctly_clears_auto_open_and_close_blocks() { vec![::MinWeight::get(); category_count.into()], )); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(22..33), @@ -272,7 +272,7 @@ fn admin_move_market_to_closed_correctly_clears_auto_open_and_close_blocks() { ::MinLiquidity::get(), vec![::MinWeight::get(); category_count.into()], )); - assert_ok!(PredictionMarkets::admin_move_market_to_closed(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), 0)); let auto_close = MarketIdsPerCloseBlock::::get(66); assert_eq!(auto_close.len(), 1); @@ -290,7 +290,7 @@ fn create_scalar_market_fails_on_invalid_range(range: RangeInclusive) { ExtBuilder::default().build().execute_with(|| { assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(123..456), @@ -316,7 +316,7 @@ fn create_market_fails_on_min_dispute_period() { }; assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(123..456), @@ -342,7 +342,7 @@ fn create_market_fails_on_min_oracle_duration() { }; assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(123..456), @@ -368,7 +368,7 @@ fn create_market_fails_on_max_dispute_period() { }; assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(123..456), @@ -394,7 +394,7 @@ fn create_market_fails_on_max_grace_period() { }; assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(123..456), @@ -420,7 +420,7 @@ fn create_market_fails_on_max_oracle_duration() { }; assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(123..456), @@ -450,7 +450,7 @@ fn create_market_with_foreign_assets() { assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::ForeignAsset(420), BOB, MarketPeriod::Block(123..456), @@ -466,7 +466,7 @@ fn create_market_with_foreign_assets() { // As per Mock asset_registry genesis ForeignAsset(50) is not registered in asset_registry. assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::ForeignAsset(50), BOB, MarketPeriod::Block(123..456), @@ -481,7 +481,7 @@ fn create_market_with_foreign_assets() { ); // As per Mock asset_registry genesis ForeignAsset(100) has allow_as_base_asset set to true. assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::ForeignAsset(100), BOB, MarketPeriod::Block(123..456), @@ -514,7 +514,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_active() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -545,7 +545,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_reported() { let market = MarketCommons::market(&0).unwrap(); run_to_block(end + market.deadlines.grace_period); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -556,7 +556,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_reported() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -589,13 +589,13 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_disputed() { assert_ne!(grace_period, 0); run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); run_to_block(grace_period + 2); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); @@ -606,7 +606,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_disputed() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -639,18 +639,18 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { assert_ne!(grace_period, 0); run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); run_to_block(grace_period + 2); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(DAVE), + RuntimeOrigin::signed(DAVE), 0, OutcomeReport::Categorical(1) )); @@ -667,7 +667,7 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { let balance_free_before_charlie = Balances::free_balance(&CHARLIE); let balance_free_before_dave = Balances::free_balance(&DAVE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), market_id)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &CHARLIE), SENTINEL_AMOUNT, @@ -703,7 +703,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_resolved() { let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -716,7 +716,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_resolved() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -750,7 +750,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_proposed() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -789,9 +789,9 @@ fn admin_destroy_market_correctly_slashes_advised_market_proposed_with_edit_requ let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -819,7 +819,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_active() { 0..1, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); assert_ok!(AssetManager::deposit(Asset::Ztg, &ALICE, 2 * SENTINEL_AMOUNT)); assert_ok!(Balances::reserve_named( &PredictionMarkets::reserve_id(), @@ -827,7 +827,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_active() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -855,12 +855,12 @@ fn admin_destroy_market_correctly_slashes_advised_market_reported() { 0..end, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -871,7 +871,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_reported() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -899,17 +899,17 @@ fn admin_destroy_market_correctly_slashes_advised_market_disputed() { 0..end, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); @@ -920,7 +920,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_disputed() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -948,12 +948,12 @@ fn admin_destroy_market_correctly_slashes_advised_market_resolved() { 0..end, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -966,7 +966,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_resolved() { SENTINEL_AMOUNT )); let balance_free_before_alice = Balances::free_balance(&ALICE); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!( Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), SENTINEL_AMOUNT @@ -991,7 +991,7 @@ fn admin_destroy_market_correctly_cleans_up_accounts() { let swap_fee = ::MaxSwapFee::get(); let min_liquidity = ::MinLiquidity::get(); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, ALICE, MarketPeriod::Block(0..42), @@ -1004,12 +1004,12 @@ fn admin_destroy_market_correctly_cleans_up_accounts() { vec![::MinWeight::get(); 3], )); // Buy some outcome tokens for Alice so that we can check that they get destroyed. - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(ALICE), 0, BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(ALICE), 0, BASE)); let market_id = 0; let pool_id = 0; let pool_account = Swaps::pool_account_id(&pool_id); let market_account = MarketCommons::market_account(market_id); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_eq!(AssetManager::free_balance(Asset::CategoricalOutcome(0, 0), &pool_account), 0); assert_eq!(AssetManager::free_balance(Asset::CategoricalOutcome(0, 1), &pool_account), 0); assert_eq!(AssetManager::free_balance(Asset::CategoricalOutcome(0, 2), &pool_account), 0); @@ -1056,7 +1056,7 @@ fn admin_destroy_market_correctly_clears_auto_open_and_close_blocks() { ExtBuilder::default().build().execute_with(|| { let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(22..66), @@ -1069,7 +1069,7 @@ fn admin_destroy_market_correctly_clears_auto_open_and_close_blocks() { vec![::MinWeight::get(); category_count.into()], )); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(33..66), @@ -1082,7 +1082,7 @@ fn admin_destroy_market_correctly_clears_auto_open_and_close_blocks() { vec![::MinWeight::get(); category_count.into()], )); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(22..33), @@ -1094,7 +1094,7 @@ fn admin_destroy_market_correctly_clears_auto_open_and_close_blocks() { ::MinLiquidity::get(), vec![::MinWeight::get(); category_count.into()], )); - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); let auto_close = MarketIdsPerCloseBlock::::get(66); assert_eq!(auto_close.len(), 1); @@ -1137,12 +1137,12 @@ fn admin_move_market_to_resolved_resolves_reported_market() { let category = 1; let outcome_report = OutcomeReport::Categorical(category); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, outcome_report.clone() )); assert_ok!(PredictionMarkets::admin_move_market_to_resolved( - Origin::signed(SUDO), + RuntimeOrigin::signed(SUDO), market_id )); @@ -1196,7 +1196,7 @@ fn admin_move_market_to_resovled_fails_if_market_is_not_reported_or_disputed( Ok(()) })); assert_noop!( - PredictionMarkets::admin_move_market_to_resolved(Origin::signed(SUDO), market_id,), + PredictionMarkets::admin_move_market_to_resolved(RuntimeOrigin::signed(SUDO), market_id,), Error::::InvalidMarketStatus, ); }); @@ -1272,7 +1272,7 @@ fn it_does_not_create_market_with_too_few_categories() { ExtBuilder::default().build().execute_with(|| { assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..100), @@ -1293,7 +1293,7 @@ fn it_does_not_create_market_with_too_many_categories() { ExtBuilder::default().build().execute_with(|| { assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..100), @@ -1321,7 +1321,7 @@ fn it_allows_sudo_to_destroy_markets() { ); // destroy the market - assert_ok!(PredictionMarkets::admin_destroy_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_destroy_market(RuntimeOrigin::signed(SUDO), 0)); assert_noop!( MarketCommons::market(&0), @@ -1347,12 +1347,12 @@ fn it_allows_advisory_origin_to_approve_markets() { // Make sure it fails from the random joe assert_noop!( - PredictionMarkets::approve_market(Origin::signed(BOB), 0), + PredictionMarkets::approve_market(RuntimeOrigin::signed(BOB), 0), DispatchError::BadOrigin ); // Now it should work from SUDO - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let after_market = MarketCommons::market(&0); assert_eq!(after_market.unwrap().status, MarketStatus::Active); @@ -1378,12 +1378,12 @@ fn it_allows_request_edit_origin_to_request_edits_for_markets() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; // Make sure it fails from the random joe assert_noop!( - PredictionMarkets::request_edit(Origin::signed(BOB), 0, edit_reason.clone()), + PredictionMarkets::request_edit(RuntimeOrigin::signed(BOB), 0, edit_reason.clone()), DispatchError::BadOrigin ); // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason.clone())); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason.clone())); System::assert_last_event( Event::MarketRequestedEdit( 0, @@ -1415,7 +1415,7 @@ fn request_edit_fails_on_bad_origin() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; // Make sure it fails from the random joe assert_noop!( - PredictionMarkets::request_edit(Origin::signed(BOB), 0, edit_reason), + PredictionMarkets::request_edit(RuntimeOrigin::signed(BOB), 0, edit_reason), DispatchError::BadOrigin ); }); @@ -1439,7 +1439,7 @@ fn edit_request_fails_if_edit_reason_is_too_long() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize + 1]; assert_noop!( - PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason), + PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason), Error::::EditReasonLengthExceedsMaxEditReasonLen ); }); @@ -1462,11 +1462,11 @@ fn market_with_edit_request_cannot_be_approved() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); assert_noop!( - PredictionMarkets::approve_market(Origin::signed(SUDO), 0), + PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0), Error::::MarketEditRequestAlreadyInProgress ); }); @@ -1492,7 +1492,7 @@ fn it_allows_the_advisory_origin_to_reject_markets() { vec![0; ::MaxRejectReasonLen::get() as usize]; // Now it should work from SUDO assert_ok!(PredictionMarkets::reject_market( - Origin::signed(SUDO), + RuntimeOrigin::signed(SUDO), 0, reject_reason.clone() )); @@ -1524,7 +1524,7 @@ fn reject_errors_if_reject_reason_is_too_long() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize + 1]; assert_noop!( - PredictionMarkets::reject_market(Origin::signed(SUDO), 0, reject_reason), + PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason), Error::::RejectReasonLengthExceedsMaxRejectReasonLen ); }); @@ -1548,9 +1548,9 @@ fn it_allows_the_advisory_origin_to_reject_markets_with_edit_request() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; let reject_reason = vec![0_u8; ::MaxRejectReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); - assert_ok!(PredictionMarkets::reject_market(Origin::signed(SUDO), 0, reject_reason)); + assert_ok!(PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason)); assert!(!MarketIdsForEdit::::contains_key(0)); assert_noop!( @@ -1587,7 +1587,7 @@ fn reject_market_unreserves_oracle_bond_and_slashes_advisory_bond() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::reject_market(Origin::signed(SUDO), 0, reject_reason)); + assert_ok!(PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason)); // AdvisoryBond gets slashed after reject_market // OracleBond gets unreserved after reject_market @@ -1649,7 +1649,7 @@ fn reject_market_clears_auto_close_blocks() { ); let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::reject_market(Origin::signed(SUDO), 0, reject_reason)); + assert_ok!(PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason)); let auto_close = MarketIdsPerCloseBlock::::get(66); assert_eq!(auto_close.len(), 1); @@ -1733,7 +1733,7 @@ fn on_market_close_auto_rejects_expired_advised_market_with_edit_request() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), market_id, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), market_id, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); run_blocks(end); @@ -1766,7 +1766,7 @@ fn on_market_open_successfully_auto_opens_market_pool_with_blocks() { let end = 66; let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(start..end), @@ -1797,7 +1797,7 @@ fn on_market_close_successfully_auto_closes_market_with_blocks() { let end = 33; let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(0..end), @@ -1835,7 +1835,7 @@ fn on_market_open_successfully_auto_opens_market_with_timestamps() { let end: Moment = (66 * MILLISECS_PER_BLOCK).into(); let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(start..end), @@ -1869,7 +1869,7 @@ fn on_market_close_successfully_auto_closes_market_with_timestamps() { let end: Moment = (2 * MILLISECS_PER_BLOCK).into(); let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(0..end), @@ -1915,7 +1915,7 @@ fn on_market_open_successfully_auto_opens_multiple_markets_after_stall() { let end: Moment = (666 * MILLISECS_PER_BLOCK).into(); let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(start..end), @@ -1928,7 +1928,7 @@ fn on_market_open_successfully_auto_opens_multiple_markets_after_stall() { vec![::MinWeight::get(); category_count.into()], )); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(start..end), @@ -1960,7 +1960,7 @@ fn on_market_close_successfully_auto_closes_multiple_markets_after_stall() { let end: Moment = (5 * MILLISECS_PER_BLOCK).into(); let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(0..end), @@ -1973,7 +1973,7 @@ fn on_market_close_successfully_auto_closes_multiple_markets_after_stall() { vec![::MinWeight::get(); category_count.into()], )); assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(0..end), @@ -2012,7 +2012,7 @@ fn on_initialize_skips_the_genesis_block() { ExtBuilder::default().build().execute_with(|| { let category_count = 3; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Timestamp(0..end), @@ -2055,7 +2055,7 @@ fn it_allows_to_buy_a_complete_set() { ); // Allows someone to generate a complete set - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); @@ -2094,7 +2094,7 @@ fn it_does_not_allow_to_buy_a_complete_set_on_pending_advised_market() { ScoringRule::CPMM, ); assert_noop!( - PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, CENT), + PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, CENT), Error::::MarketIsNotActive, ); }); @@ -2105,7 +2105,7 @@ fn create_categorical_market_fails_if_market_begin_is_equal_to_end() { ExtBuilder::default().build().execute_with(|| { assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(3..3), @@ -2135,7 +2135,7 @@ fn create_categorical_market_fails_if_market_period_is_invalid( ExtBuilder::default().build().execute_with(|| { assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, period, @@ -2158,7 +2158,7 @@ fn create_categorical_market_fails_if_end_is_not_far_enough_ahead() { run_to_block(end_block); assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..end_block), @@ -2175,7 +2175,7 @@ fn create_categorical_market_fails_if_end_is_not_far_enough_ahead() { let end_time = MILLISECS_PER_BLOCK as u64 / 2; assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..end_time), @@ -2201,7 +2201,7 @@ fn it_does_not_allow_zero_amounts_in_buy_complete_set() { ScoringRule::CPMM, ); assert_noop!( - PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, 0), + PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 0), Error::::ZeroAmount ); }); @@ -2217,7 +2217,7 @@ fn it_does_not_allow_buying_complete_sets_with_insufficient_balance() { ScoringRule::CPMM, ); assert_noop!( - PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, 10000 * BASE), + PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 10000 * BASE), Error::::NotEnoughBalance ); }; @@ -2240,16 +2240,16 @@ fn it_allows_to_deploy_a_pool() { ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, 100 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 100 * BASE)); assert_ok!(Balances::transfer( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), ::PalletId::get().into_account_truncating(), 100 * BASE )); assert_ok!(PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, ::MaxSwapFee::get(), ::MinLiquidity::get(), @@ -2274,9 +2274,9 @@ fn deploy_swap_pool_for_market_fails_if_market_has_a_pool() { 0..1, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, 200 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 200 * BASE)); assert_ok!(PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, ::MaxSwapFee::get(), ::MinLiquidity::get(), @@ -2284,7 +2284,7 @@ fn deploy_swap_pool_for_market_fails_if_market_has_a_pool() { )); assert_noop!( PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, ::MaxSwapFee::get(), ::MinLiquidity::get(), @@ -2308,7 +2308,7 @@ fn it_does_not_allow_to_deploy_a_pool_on_pending_advised_market() { assert_noop!( PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, ::MaxSwapFee::get(), ::MinLiquidity::get(), @@ -2331,9 +2331,9 @@ fn it_allows_to_sell_a_complete_set() { ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, CENT)); - assert_ok!(PredictionMarkets::sell_complete_set(Origin::signed(BOB), 0, CENT)); + assert_ok!(PredictionMarkets::sell_complete_set(RuntimeOrigin::signed(BOB), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); @@ -2369,7 +2369,7 @@ fn it_does_not_allow_zero_amounts_in_sell_complete_set() { ScoringRule::CPMM, ); assert_noop!( - PredictionMarkets::sell_complete_set(Origin::signed(BOB), 0, 0), + PredictionMarkets::sell_complete_set(RuntimeOrigin::signed(BOB), 0, 0), Error::::ZeroAmount ); }); @@ -2384,10 +2384,10 @@ fn it_does_not_allow_to_sell_complete_sets_with_insufficient_balance() { 0..1, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, 2 * CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 2 * CENT)); assert_eq!(AssetManager::slash(Asset::CategoricalOutcome(0, 1), &BOB, CENT), 0); assert_noop!( - PredictionMarkets::sell_complete_set(Origin::signed(BOB), 0, 2 * CENT), + PredictionMarkets::sell_complete_set(RuntimeOrigin::signed(BOB), 0, 2 * CENT), Error::::InsufficientShareBalance ); }; @@ -2420,7 +2420,7 @@ fn it_allows_to_report_the_outcome_of_a_market() { assert!(market.report.is_none()); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -2439,7 +2439,7 @@ fn it_allows_to_report_the_outcome_of_a_market() { }); assert_ok!(PredictionMarkets::report( - Origin::signed(SUDO), + RuntimeOrigin::signed(SUDO), 0, OutcomeReport::Categorical(1) )); @@ -2464,7 +2464,7 @@ fn report_fails_before_grace_period_is_over() { assert!(market.report.is_none()); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::NotAllowedToReportYet ); }); @@ -2490,12 +2490,12 @@ fn it_allows_only_oracle_to_report_the_outcome_of_a_market_during_oracle_duratio assert!(market.report.is_none()); assert_noop!( - PredictionMarkets::report(Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), Error::::ReporterNotOracle ); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -2512,7 +2512,7 @@ fn it_allows_only_oracle_to_report_the_outcome_of_a_market_during_oracle_duratio fn it_allows_only_oracle_to_report_the_outcome_of_a_market_during_oracle_duration_moment() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -2524,7 +2524,7 @@ fn it_allows_only_oracle_to_report_the_outcome_of_a_market_during_oracle_duratio ScoringRule::CPMM )); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, CENT)); // set the timestamp let market = MarketCommons::market(&0).unwrap(); @@ -2536,11 +2536,11 @@ fn it_allows_only_oracle_to_report_the_outcome_of_a_market_during_oracle_duratio Timestamp::set_timestamp(100_000_000 + grace_period); assert_noop!( - PredictionMarkets::report(Origin::signed(EVE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1)), Error::::ReporterNotOracle ); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -2561,7 +2561,7 @@ fn report_fails_on_mismatched_outcome_for_categorical_market() { let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Scalar(123)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(123)), Error::::OutcomeMismatch, ); let market = MarketCommons::market(&0).unwrap(); @@ -2584,7 +2584,7 @@ fn report_fails_on_out_of_range_outcome_for_categorical_market() { let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(2)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(2)), Error::::OutcomeMismatch, ); let market = MarketCommons::market(&0).unwrap(); @@ -2607,7 +2607,7 @@ fn report_fails_on_mismatched_outcome_for_scalar_market() { let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(0)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0)), Error::::OutcomeMismatch, ); let market = MarketCommons::market(&0).unwrap(); @@ -2633,7 +2633,7 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -2642,7 +2642,7 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { run_to_block(dispute_at); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); @@ -2669,7 +2669,7 @@ fn dispute_fails_authority_reported_already() { ExtBuilder::default().build().execute_with(|| { let end = 2; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..end), @@ -2687,7 +2687,7 @@ fn dispute_fails_authority_reported_already() { run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -2696,13 +2696,13 @@ fn dispute_fails_authority_reported_already() { run_to_block(dispute_at); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); assert_noop!( - PredictionMarkets::dispute(Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), AuthorizedError::::OnlyOneDisputeAllowed ); }); @@ -2724,7 +2724,7 @@ fn it_allows_anyone_to_report_an_unreported_market() { run_to_block(end + market.deadlines.grace_period + market.deadlines.oracle_duration + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(ALICE), // alice reports her own market now + RuntimeOrigin::signed(ALICE), // alice reports her own market now 0, OutcomeReport::Categorical(1), )); @@ -2756,14 +2756,14 @@ fn it_correctly_resolves_a_market_that_was_reported_on() { ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); let report_at = end + market.deadlines.grace_period + 1; run_to_block(report_at); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -2815,14 +2815,14 @@ fn it_resolves_a_disputed_market() { ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); let report_at = end + market.deadlines.grace_period + 1; run_to_block(report_at); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); @@ -2831,7 +2831,7 @@ fn it_resolves_a_disputed_market() { run_to_block(dispute_at_0); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) )); @@ -2840,7 +2840,7 @@ fn it_resolves_a_disputed_market() { run_to_block(dispute_at_1); assert_ok!(PredictionMarkets::dispute( - Origin::signed(DAVE), + RuntimeOrigin::signed(DAVE), 0, OutcomeReport::Categorical(0) )); @@ -2849,7 +2849,7 @@ fn it_resolves_a_disputed_market() { run_to_block(dispute_at_2); assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1) )); @@ -2894,7 +2894,7 @@ fn it_resolves_a_disputed_market() { let disputes = crate::Disputes::::get(0); assert_eq!(disputes.len(), 0); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(CHARLIE), 0)); // Make sure rewards are right: // @@ -2959,7 +2959,7 @@ fn dispute_fails_unless_reported_or_disputed_market(status: MarketStatus) { })); assert_noop!( - PredictionMarkets::dispute(Origin::signed(EVE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::dispute(RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1)), Error::::InvalidMarketStatus ); }); @@ -2970,7 +2970,7 @@ fn start_global_dispute_works() { ExtBuilder::default().build().execute_with(|| { let end = 2; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..2), @@ -2987,7 +2987,7 @@ fn start_global_dispute_works() { let grace_period = market.deadlines.grace_period; run_to_block(end + grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Categorical(0) )); @@ -2997,18 +2997,18 @@ fn start_global_dispute_works() { if i == 1 { #[cfg(feature = "with-global-disputes")] assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), + PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id), Error::::InvalidMarketStatus ); } else { #[cfg(feature = "with-global-disputes")] assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), + PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id), Error::::MaxDisputesNeeded ); } assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Categorical(i.saturated_into()) )); @@ -3030,7 +3030,7 @@ fn start_global_dispute_works() { use zrml_global_disputes::GlobalDisputesPalletApi; let now = >::block_number(); - assert_ok!(PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id)); + assert_ok!(PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id)); // report check assert_eq!( @@ -3060,7 +3060,7 @@ fn start_global_dispute_works() { System::assert_last_event(Event::GlobalDisputeStarted(market_id).into()); assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), + PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id), Error::::GlobalDisputeAlreadyStarted ); } @@ -3072,7 +3072,7 @@ fn start_global_dispute_fails_on_wrong_mdm() { ExtBuilder::default().build().execute_with(|| { let end = 2; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..2), @@ -3089,7 +3089,7 @@ fn start_global_dispute_fails_on_wrong_mdm() { let grace_period = market.deadlines.grace_period; run_to_block(end + grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), market_id, OutcomeReport::Categorical(0) )); @@ -3098,7 +3098,7 @@ fn start_global_dispute_fails_on_wrong_mdm() { // only one dispute allowed for authorized mdm assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), market_id, OutcomeReport::Categorical(1u32.saturated_into()) )); @@ -3108,7 +3108,7 @@ fn start_global_dispute_fails_on_wrong_mdm() { #[cfg(feature = "with-global-disputes")] assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), + PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id), Error::::InvalidDisputeMechanism ); }); @@ -3121,13 +3121,13 @@ fn start_global_dispute_works_without_feature() { #[cfg(not(feature = "with-global-disputes"))] assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), non_market_id), + PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), non_market_id), Error::::GlobalDisputesDisabled ); #[cfg(feature = "with-global-disputes")] assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), non_market_id), + PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), non_market_id), zrml_market_commons::Error::::MarketDoesNotExist ); }); @@ -3144,13 +3144,13 @@ fn it_allows_to_redeem_shares() { ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -3158,7 +3158,7 @@ fn it_allows_to_redeem_shares() { let market = MarketCommons::market(&0).unwrap(); assert_eq!(market.status, MarketStatus::Resolved); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(CHARLIE), 0)); let bal = Balances::free_balance(&CHARLIE); assert_eq!(bal, 1_000 * BASE); System::assert_last_event( @@ -3190,7 +3190,7 @@ fn create_market_and_deploy_assets_results_in_expected_balances_and_pool_params( let base_asset_weight = (category_count as u128) * weight; let total_weight = 2 * base_asset_weight; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, oracle, period, @@ -3264,7 +3264,7 @@ fn process_subsidy_activates_market_with_sufficient_subsidy() { ScoringRule::RikiddoSigmoidFeeMarketEma, ); let min_subsidy = ::MinSubsidy::get(); - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(ALICE), 0, min_subsidy)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(ALICE), 0, min_subsidy)); run_to_block(min_sub_period); let subsidy_queue = crate::MarketsCollectingSubsidy::::get(); assert_eq!(subsidy_queue.len(), 0); @@ -3294,8 +3294,8 @@ fn process_subsidy_blocks_market_with_insufficient_subsidy() { ScoringRule::RikiddoSigmoidFeeMarketEma, ); let subsidy = ::MinSubsidy::get() / 3; - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(ALICE), 0, subsidy)); - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(BOB), 0, subsidy)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(ALICE), 0, subsidy)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(BOB), 0, subsidy)); run_to_block(min_sub_period); let subsidy_queue = crate::MarketsCollectingSubsidy::::get(); assert_eq!(subsidy_queue.len(), 0); @@ -3409,14 +3409,14 @@ fn only_creator_can_edit_market() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); // ALICE is market creator through simple_create_categorical_market assert_noop!( PredictionMarkets::edit_market( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), Asset::Ztg, 0, CHARLIE, @@ -3451,14 +3451,14 @@ fn edit_cycle_for_proposed_markets() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); // BOB was the oracle before through simple_create_categorical_market // After this edit its changed to ALICE assert_ok!(PredictionMarkets::edit_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, 0, CHARLIE, @@ -3497,7 +3497,7 @@ fn edit_market_with_foreign_asset() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(Origin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); assert!(MarketIdsForEdit::::contains_key(0)); @@ -3505,7 +3505,7 @@ fn edit_market_with_foreign_asset() { // As per Mock asset_registry genesis ForeignAsset(50) is not registered in asset_registry. assert_noop!( PredictionMarkets::edit_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::ForeignAsset(50), 0, CHARLIE, @@ -3521,7 +3521,7 @@ fn edit_market_with_foreign_asset() { // As per Mock asset_registry genesis ForeignAsset(420) has allow_as_base_asset set to false. assert_noop!( PredictionMarkets::edit_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::ForeignAsset(420), 0, CHARLIE, @@ -3536,7 +3536,7 @@ fn edit_market_with_foreign_asset() { ); // As per Mock asset_registry genesis ForeignAsset(100) has allow_as_base_asset set to true. assert_ok!(PredictionMarkets::edit_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::ForeignAsset(100), 0, CHARLIE, @@ -3557,7 +3557,7 @@ fn the_entire_market_lifecycle_works_with_timestamps() { ExtBuilder::default().build().execute_with(|| { // Creates a permissionless market. assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -3570,7 +3570,7 @@ fn the_entire_market_lifecycle_works_with_timestamps() { )); // is ok - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); // set the timestamp @@ -3580,12 +3580,12 @@ fn the_entire_market_lifecycle_works_with_timestamps() { Timestamp::set_timestamp(100_000_000 + grace_period); assert_noop!( - PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, CENT), + PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, CENT), Error::::MarketIsNotActive, ); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -3596,7 +3596,7 @@ fn the_entire_market_lifecycle_works_with_timestamps() { fn full_scalar_market_lifecycle() { let test = |base_asset: Asset| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -3608,7 +3608,7 @@ fn full_scalar_market_lifecycle() { ScoringRule::CPMM )); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, 100 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, 100 * BASE)); // check balances let assets = PredictionMarkets::outcome_assets(0, &MarketCommons::market(&0).unwrap()); @@ -3626,7 +3626,7 @@ fn full_scalar_market_lifecycle() { Timestamp::set_timestamp(100_000_000 + grace_period); // report - assert_ok!(PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Scalar(100))); + assert_ok!(PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(100))); let market_after_report = MarketCommons::market(&0).unwrap(); assert!(market_after_report.report.is_some()); @@ -3636,7 +3636,7 @@ fn full_scalar_market_lifecycle() { assert_eq!(report.outcome, OutcomeReport::Scalar(100)); // dispute - assert_ok!(PredictionMarkets::dispute(Origin::signed(DAVE), 0, OutcomeReport::Scalar(25))); + assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(DAVE), 0, OutcomeReport::Scalar(25))); let disputes = crate::Disputes::::get(0); assert_eq!(disputes.len(), 1); @@ -3649,7 +3649,7 @@ fn full_scalar_market_lifecycle() { // give EVE some shares assert_ok!(Tokens::transfer( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), EVE, Asset::ScalarOutcome(0, ScalarPosition::Short), 50 * BASE @@ -3660,7 +3660,7 @@ fn full_scalar_market_lifecycle() { 50 * BASE ); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(CHARLIE), 0)); for asset in assets.iter() { let bal = Tokens::free_balance(*asset, &CHARLIE); assert_eq!(bal, 0); @@ -3692,7 +3692,7 @@ fn full_scalar_market_lifecycle() { .into(), ); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(EVE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(EVE), 0)); let base_asset_bal_eve_after = AssetManager::free_balance(base_asset, &EVE); assert_eq!(base_asset_bal_eve_after, 101250 * CENT); // 12.5 (SHORT) + 1000 (balance) System::assert_last_event( @@ -3760,7 +3760,7 @@ fn reject_market_fails_on_permissionless_market() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; assert_noop!( - PredictionMarkets::reject_market(Origin::signed(SUDO), 0, reject_reason), + PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason), Error::::InvalidMarketStatus ); }); @@ -3776,11 +3776,11 @@ fn reject_market_fails_on_approved_market() { 0..1, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; assert_noop!( - PredictionMarkets::reject_market(Origin::signed(SUDO), 0, reject_reason), + PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason), Error::::InvalidMarketStatus ); }); @@ -3791,7 +3791,7 @@ fn market_resolve_does_not_hold_liquidity_withdraw() { ExtBuilder::default().build().execute_with(|| { let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..end), @@ -3803,22 +3803,22 @@ fn market_resolve_does_not_hold_liquidity_withdraw() { ScoringRule::CPMM )); deploy_swap_pool(MarketCommons::market(&0).unwrap(), 0).unwrap(); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(ALICE), 0, BASE)); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(BOB), 0, 2 * BASE)); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, 3 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(ALICE), 0, BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 2 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, 3 * BASE)); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(2) )); run_to_block(grace_period + market.deadlines.dispute_duration + 2); - assert_ok!(Swaps::pool_exit(Origin::signed(FRED), 0, BASE * 100, vec![0, 0])); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(BOB), 0)); + assert_ok!(Swaps::pool_exit(RuntimeOrigin::signed(FRED), 0, BASE * 100, vec![0, 0])); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(BOB), 0)); }) } @@ -3828,7 +3828,7 @@ fn authorized_correctly_resolves_disputed_market() { let test = |base_asset: Asset| { let end = 2; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -3839,13 +3839,13 @@ fn authorized_correctly_resolves_disputed_market() { MarketDisputeMechanism::Authorized, ScoringRule::CPMM, )); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, CENT)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, CENT)); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); @@ -3856,7 +3856,7 @@ fn authorized_correctly_resolves_disputed_market() { let dispute_at = grace_period + 1 + 1; run_to_block(dispute_at); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) )); @@ -3873,12 +3873,12 @@ fn authorized_correctly_resolves_disputed_market() { // Fred authorizses an outcome, but fat-fingers it on the first try. assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Categorical(0) )); assert_ok!(Authorized::authorize_market_outcome( - Origin::signed(AuthorizedDisputeResolutionUser::get()), + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), 0, OutcomeReport::Categorical(1) )); @@ -3941,7 +3941,7 @@ fn authorized_correctly_resolves_disputed_market() { let disputes = crate::Disputes::::get(0); assert_eq!(disputes.len(), 0); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(CHARLIE), 0)); if base_asset == Asset::Ztg { let charlie_balance = AssetManager::free_balance(Asset::Ztg, &CHARLIE); @@ -3981,7 +3981,7 @@ fn approve_market_correctly_unreserves_advisory_bond() { let test = |base_asset: Asset| { reserve_sentinel_amounts(); assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..100), @@ -3995,7 +3995,7 @@ fn approve_market_correctly_unreserves_advisory_bond() { let market_id = 0; let alice_balance_before = Balances::free_balance(&ALICE); check_reserve(&ALICE, AdvisoryBond::get() + OracleBond::get()); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), market_id)); check_reserve(&ALICE, OracleBond::get()); assert_eq!(Balances::free_balance(&ALICE), alice_balance_before + AdvisoryBond::get()); let market = MarketCommons::market(&market_id).unwrap(); @@ -4019,7 +4019,7 @@ fn deploy_swap_pool_correctly_sets_weight_of_base_asset() { ::MinWeight::get() + 33, ]; assert_ok!(PredictionMarkets::create_cpmm_market_and_deploy_assets( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, ALICE, MarketPeriod::Block(0..42), @@ -4045,7 +4045,7 @@ fn deploy_swap_pool_for_market_returns_error_if_weights_is_too_short() { ExtBuilder::default().build().execute_with(|| { let category_count = 5; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..100), @@ -4057,13 +4057,13 @@ fn deploy_swap_pool_for_market_returns_error_if_weights_is_too_short() { ScoringRule::CPMM )); let amount = 123 * BASE; - assert_ok!(Balances::set_balance(Origin::root(), ALICE, 2 * amount, 0)); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(ALICE), 0, amount)); + assert_ok!(Balances::set_balance(RuntimeOrigin::root(), ALICE, 2 * amount, 0)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(ALICE), 0, amount)); // Attempt to create a pool with four weights; but we need five instead (base asset not // counted). assert_noop!( PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), 0, 1, amount, @@ -4082,7 +4082,7 @@ fn deploy_swap_pool_for_market_returns_error_if_weights_is_too_long() { ExtBuilder::default().build().execute_with(|| { let category_count = 5; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(0..100), @@ -4094,13 +4094,13 @@ fn deploy_swap_pool_for_market_returns_error_if_weights_is_too_long() { ScoringRule::CPMM )); let amount = 123 * BASE; - assert_ok!(Balances::set_balance(Origin::root(), ALICE, 2 * amount, 0)); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(ALICE), 0, amount)); + assert_ok!(Balances::set_balance(RuntimeOrigin::root(), ALICE, 2 * amount, 0)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(ALICE), 0, amount)); // Attempt to create a pool with six weights; but we need five instead (base asset not // counted). assert_noop!( PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), 0, ::MaxSwapFee::get(), amount, @@ -4122,7 +4122,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4139,7 +4139,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); @@ -4167,7 +4167,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..100), @@ -4189,7 +4189,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark assert!(market.bonds.outsider.is_none()); assert_ok!(PredictionMarkets::report( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) )); @@ -4232,7 +4232,7 @@ fn outsider_reports_wrong_outcome() { let end = 100; let alice_balance_before = Balances::free_balance(&ALICE); assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4251,7 +4251,7 @@ fn outsider_reports_wrong_outcome() { let report_at = grace_period + market.deadlines.oracle_duration + 1; run_to_block(report_at); assert_ok!(PredictionMarkets::report( - Origin::signed(outsider), + RuntimeOrigin::signed(outsider), 0, OutcomeReport::Categorical(1) )); @@ -4262,7 +4262,7 @@ fn outsider_reports_wrong_outcome() { let dispute_at_0 = report_at + 1; run_to_block(dispute_at_0); assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(0) )); @@ -4301,7 +4301,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4312,7 +4312,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma MarketDisputeMechanism::SimpleDisputes, ScoringRule::CPMM, )); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let alice_balance_before = Balances::free_balance(&ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -4320,7 +4320,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma let report_at = grace_period + 1; run_to_block(report_at); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1) )); @@ -4346,7 +4346,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4357,7 +4357,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma MarketDisputeMechanism::SimpleDisputes, ScoringRule::CPMM, )); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let alice_balance_before = Balances::free_balance(&ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -4365,7 +4365,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma let report_at = grace_period + market.deadlines.oracle_duration + 1; run_to_block(report_at); assert_ok!(PredictionMarkets::report( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) )); @@ -4392,7 +4392,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4409,12 +4409,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) )); @@ -4441,7 +4441,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4452,19 +4452,19 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma MarketDisputeMechanism::SimpleDisputes, ScoringRule::CPMM, )); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let alice_balance_before = Balances::free_balance(&ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) )); @@ -4491,7 +4491,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4508,18 +4508,18 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); // EVE disputes with wrong outcome assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); @@ -4549,7 +4549,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4560,25 +4560,25 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma MarketDisputeMechanism::SimpleDisputes, ScoringRule::CPMM, )); - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let alice_balance_before = Balances::free_balance(&ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(0) )); // EVE disputes with wrong outcome assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); @@ -4605,7 +4605,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4628,7 +4628,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark run_to_block(after_oracle_duration); // CHARLIE is not an Oracle assert_ok!(PredictionMarkets::report( - Origin::signed(outsider), + RuntimeOrigin::signed(outsider), 0, OutcomeReport::Categorical(0) )); @@ -4638,12 +4638,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark // EVE disputes with wrong outcome assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(FRED), + RuntimeOrigin::signed(FRED), 0, OutcomeReport::Categorical(0) )); @@ -4676,7 +4676,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma reserve_sentinel_amounts(); let end = 100; assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), base_asset, BOB, MarketPeriod::Block(0..end), @@ -4690,7 +4690,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma let outsider = CHARLIE; - assert_ok!(PredictionMarkets::approve_market(Origin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); let alice_balance_before = Balances::free_balance(&ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -4699,7 +4699,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma run_to_block(after_oracle_duration); // CHARLIE is not an Oracle assert_ok!(PredictionMarkets::report( - Origin::signed(outsider), + RuntimeOrigin::signed(outsider), 0, OutcomeReport::Categorical(0) )); @@ -4709,12 +4709,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma // EVE disputes with wrong outcome assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), + RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1) )); assert_ok!(PredictionMarkets::dispute( - Origin::signed(FRED), + RuntimeOrigin::signed(FRED), 0, OutcomeReport::Categorical(0) )); @@ -4742,7 +4742,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma fn report_fails_on_market_state_proposed() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -4754,7 +4754,7 @@ fn report_fails_on_market_state_proposed() { ScoringRule::CPMM )); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4764,7 +4764,7 @@ fn report_fails_on_market_state_proposed() { fn report_fails_on_market_state_closed_for_advised_market() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -4776,7 +4776,7 @@ fn report_fails_on_market_state_closed_for_advised_market() { ScoringRule::CPMM )); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4786,7 +4786,7 @@ fn report_fails_on_market_state_closed_for_advised_market() { fn report_fails_on_market_state_collecting_subsidy() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(100_000_000..200_000_000), @@ -4798,7 +4798,7 @@ fn report_fails_on_market_state_collecting_subsidy() { ScoringRule::RikiddoSigmoidFeeMarketEma )); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4808,7 +4808,7 @@ fn report_fails_on_market_state_collecting_subsidy() { fn report_fails_on_market_state_insufficient_subsidy() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(100_000_000..200_000_000), @@ -4824,7 +4824,7 @@ fn report_fails_on_market_state_insufficient_subsidy() { Ok(()) }); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4834,7 +4834,7 @@ fn report_fails_on_market_state_insufficient_subsidy() { fn report_fails_on_market_state_active() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -4846,7 +4846,7 @@ fn report_fails_on_market_state_active() { ScoringRule::CPMM )); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4856,7 +4856,7 @@ fn report_fails_on_market_state_active() { fn report_fails_on_market_state_suspended() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -4872,7 +4872,7 @@ fn report_fails_on_market_state_suspended() { Ok(()) }); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4882,7 +4882,7 @@ fn report_fails_on_market_state_suspended() { fn report_fails_on_market_state_resolved() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -4898,7 +4898,7 @@ fn report_fails_on_market_state_resolved() { Ok(()) }); assert_noop!( - PredictionMarkets::report(Origin::signed(BOB), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Categorical(1)), Error::::MarketIsNotClosed, ); }); @@ -4908,7 +4908,7 @@ fn report_fails_on_market_state_resolved() { fn report_fails_if_reporter_is_not_the_oracle() { ExtBuilder::default().build().execute_with(|| { assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(0..100_000_000), @@ -4926,7 +4926,7 @@ fn report_fails_if_reporter_is_not_the_oracle() { let grace_period: u64 = market.deadlines.grace_period * MILLISECS_PER_BLOCK as u64; set_timestamp_for_on_initialize(100_000_000 + grace_period + MILLISECS_PER_BLOCK as u64); assert_noop!( - PredictionMarkets::report(Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), Error::::ReporterNotOracle, ); }); @@ -4944,7 +4944,7 @@ fn create_market_succeeds_if_market_duration_is_maximal_in_blocks() { "Test failed due to misconfiguration: `MaxMarketLifetime` is too small" ); assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(start..end), @@ -4971,7 +4971,7 @@ fn create_market_suceeds_if_market_duration_is_maximal_in_moments() { "Test failed due to misconfiguration: `MaxMarketLifetime` is too small" ); assert_ok!(PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(start..end), @@ -4998,7 +4998,7 @@ fn create_market_fails_if_market_duration_is_too_long_in_blocks() { ); assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Block(start..end), @@ -5028,7 +5028,7 @@ fn create_market_fails_if_market_duration_is_too_long_in_moments() { ); assert_noop!( PredictionMarkets::create_market( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), Asset::Ztg, BOB, MarketPeriod::Timestamp(start..end), @@ -5084,7 +5084,7 @@ fn create_market_sets_the_correct_market_parameters_and_reserves_the_correct_amo let market_type = MarketType::Categorical(7); let dispute_mechanism = MarketDisputeMechanism::Authorized; assert_ok!(PredictionMarkets::create_market( - Origin::signed(creator), + RuntimeOrigin::signed(creator), Asset::Ztg, oracle, period.clone(), @@ -5117,15 +5117,15 @@ fn deploy_swap_pool( market: Market>, market_id: u128, ) -> DispatchResultWithPostInfo { - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(FRED), 0, 100 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(FRED), 0, 100 * BASE)); assert_ok!(Balances::transfer( - Origin::signed(FRED), + RuntimeOrigin::signed(FRED), ::PalletId::get().into_account_truncating(), 100 * BASE )); let outcome_assets_len = PredictionMarkets::outcome_assets(market_id, &market).len(); PredictionMarkets::deploy_swap_pool_for_market( - Origin::signed(FRED), + RuntimeOrigin::signed(FRED), 0, ::MaxSwapFee::get(), ::MinLiquidity::get(), @@ -5142,9 +5142,9 @@ fn scalar_market_correctly_resolves_common(base_asset: Asset, reported 0..end, ScoringRule::CPMM, ); - assert_ok!(PredictionMarkets::buy_complete_set(Origin::signed(CHARLIE), 0, 100 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, 100 * BASE)); assert_ok!(Tokens::transfer( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), EVE, Asset::ScalarOutcome(0, ScalarPosition::Short), 100 * BASE @@ -5155,7 +5155,7 @@ fn scalar_market_correctly_resolves_common(base_asset: Asset, reported let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(reported_value) )); @@ -5175,8 +5175,8 @@ fn scalar_market_correctly_resolves_common(base_asset: Asset, reported assert_eq!(AssetManager::free_balance(base_asset, &CHARLIE), 900 * BASE); assert_eq!(AssetManager::free_balance(base_asset, &EVE), 1000 * BASE); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); - assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(EVE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(CHARLIE), 0)); + assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(EVE), 0)); let assets = PredictionMarkets::outcome_assets(0, &MarketCommons::market(&0).unwrap()); for asset in assets.iter() { assert_eq!(AssetManager::free_balance(*asset, &CHARLIE), 0); diff --git a/zrml/rikiddo/Cargo.toml b/zrml/rikiddo/Cargo.toml index 3946c36d8..cd0f49627 100644 --- a/zrml/rikiddo/Cargo.toml +++ b/zrml/rikiddo/Cargo.toml @@ -1,16 +1,16 @@ [dependencies] arbitrary = { version = "1.0.1", features = ["derive"], optional = true } cfg-if = { version = "1.0.0", default-features = false } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } hashbrown = { default-features = true, version = "0.11" } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-core = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-core = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } substrate-fixed = { default-features = false, features = ["serde"], git = "https://github.com/encointer/substrate-fixed" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } diff --git a/zrml/rikiddo/fuzz/Cargo.toml b/zrml/rikiddo/fuzz/Cargo.toml index a01f8a121..5c28dfedf 100644 --- a/zrml/rikiddo/fuzz/Cargo.toml +++ b/zrml/rikiddo/fuzz/Cargo.toml @@ -72,8 +72,8 @@ test = false [dependencies] arbitrary = { features = ["derive"], version = "1.0" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } libfuzzer-sys = "0.4" substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed" } zrml-rikiddo = { features = ["arbitrary", "mock"], path = ".." } diff --git a/zrml/rikiddo/src/mock.rs b/zrml/rikiddo/src/mock.rs index 3b951a497..d6459020c 100644 --- a/zrml/rikiddo/src/mock.rs +++ b/zrml/rikiddo/src/mock.rs @@ -59,7 +59,7 @@ construct_runtime!( { Balances: pallet_balances::{Call, Config, Event, Pallet, Storage}, Rikiddo: crate::{Pallet, Storage}, - System: frame_system::{Config, Event, Pallet, Storage}, + System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Call, Pallet, Storage, Inherent}, } ); @@ -87,9 +87,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -99,7 +99,7 @@ impl frame_system::Config for Runtime { type OnKilledAccount = (); type OnNewAccount = (); type OnSetCode = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -110,7 +110,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MaxReserves = MaxReserves; type ExistentialDeposit = ExistentialDeposit; type MaxLocks = (); diff --git a/zrml/simple-disputes/Cargo.toml b/zrml/simple-disputes/Cargo.toml index d6b6ede2b..80aa46782 100644 --- a/zrml/simple-disputes/Cargo.toml +++ b/zrml/simple-disputes/Cargo.toml @@ -1,17 +1,17 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } [features] diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index f0e7a5f5c..37faf0a13 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -67,7 +67,7 @@ mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// Event - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; type DisputeResolution: DisputeResolutionApi< AccountId = Self::AccountId, @@ -140,7 +140,7 @@ mod pallet { type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; type Moment = MomentOf; - type Origin = T::Origin; + type Origin = T::RuntimeOrigin; fn on_dispute( disputes: &[MarketDispute], diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index a127cf5a8..5e9178ee0 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -101,7 +101,7 @@ impl DisputeResolutionApi for NoopResolution { } impl crate::Config for Runtime { - type Event = (); + type RuntimeEvent = (); type DisputeResolution = NoopResolution; type MarketCommons = MarketCommons; type PalletId = SimpleDisputesPalletId; @@ -115,9 +115,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = (); + type RuntimeEvent = (); type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -126,7 +126,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -138,7 +138,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = (); + type RuntimeEvent = (); type ExistentialDeposit = (); type MaxLocks = (); type MaxReserves = MaxReserves; diff --git a/zrml/styx/Cargo.toml b/zrml/styx/Cargo.toml index ee233d4ff..70873adf2 100644 --- a/zrml/styx/Cargo.toml +++ b/zrml/styx/Cargo.toml @@ -1,16 +1,16 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } [dev-dependencies] -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate" } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } [features] diff --git a/zrml/styx/src/lib.rs b/zrml/styx/src/lib.rs index d1a6164e0..e00713303 100644 --- a/zrml/styx/src/lib.rs +++ b/zrml/styx/src/lib.rs @@ -38,9 +38,9 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// The origin that is allowed to set the amount burned when crossing Styx. - type SetBurnAmountOrigin: EnsureOrigin; + type SetBurnAmountOrigin: EnsureOrigin; - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; type Currency: Currency; diff --git a/zrml/styx/src/mock.rs b/zrml/styx/src/mock.rs index b147fe247..80dd2a2f8 100644 --- a/zrml/styx/src/mock.rs +++ b/zrml/styx/src/mock.rs @@ -53,7 +53,7 @@ construct_runtime!( impl crate::Config for Runtime { type Currency = Balances; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type SetBurnAmountOrigin = EnsureSignedBy; type WeightInfo = zrml_styx::weights::WeightInfo; } @@ -66,9 +66,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -77,7 +77,7 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); type OnNewAccount = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -89,7 +89,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = (); type MaxLocks = (); type MaxReserves = MaxReserves; diff --git a/zrml/styx/src/tests.rs b/zrml/styx/src/tests.rs index 32b1fb1e1..44323b632 100644 --- a/zrml/styx/src/tests.rs +++ b/zrml/styx/src/tests.rs @@ -26,7 +26,7 @@ fn cross_slashes_funds_and_stores_crossing() { frame_system::Pallet::::set_block_number(1); let burn_amount = crate::BurnAmount::::get(); let original_balance = Balances::free_balance(&ALICE); - assert_ok!(Styx::cross(Origin::signed(ALICE))); + assert_ok!(Styx::cross(RuntimeOrigin::signed(ALICE))); let balance_after_crossing = Balances::free_balance(&ALICE); let diff = original_balance - balance_after_crossing; assert!(Crossings::::contains_key(ALICE)); @@ -38,8 +38,8 @@ fn cross_slashes_funds_and_stores_crossing() { fn account_should_only_be_able_to_cross_once() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_ok!(Styx::cross(Origin::signed(ALICE))); - assert_noop!(Styx::cross(Origin::signed(ALICE)), Error::::HasAlreadyCrossed); + assert_ok!(Styx::cross(RuntimeOrigin::signed(ALICE))); + assert_noop!(Styx::cross(RuntimeOrigin::signed(ALICE)), Error::::HasAlreadyCrossed); }); } @@ -47,7 +47,7 @@ fn account_should_only_be_able_to_cross_once() { fn should_set_burn_amount() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_ok!(Styx::set_burn_amount(Origin::signed(SUDO), 144u128)); + assert_ok!(Styx::set_burn_amount(RuntimeOrigin::signed(SUDO), 144u128)); System::assert_last_event(Event::CrossingFeeChanged(144u128).into()); assert_eq!(crate::BurnAmount::::get(), 144u128); }); @@ -57,7 +57,7 @@ fn should_set_burn_amount() { fn set_burn_amount_should_fail_with_unathorized_caller() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_noop!(Styx::set_burn_amount(Origin::signed(9999), 144u128), BadOrigin); + assert_noop!(Styx::set_burn_amount(RuntimeOrigin::signed(9999), 144u128), BadOrigin); }); } @@ -65,9 +65,9 @@ fn set_burn_amount_should_fail_with_unathorized_caller() { fn account_should_not_cross_without_sufficient_funds() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_ok!(Balances::set_balance(Origin::root(), ALICE, 0, 0)); + assert_ok!(Balances::set_balance(RuntimeOrigin::root(), ALICE, 0, 0)); assert_noop!( - Styx::cross(Origin::signed(ALICE)), + Styx::cross(RuntimeOrigin::signed(ALICE)), Error::::FundDoesNotHaveEnoughFreeBalance ); }); @@ -77,7 +77,7 @@ fn account_should_not_cross_without_sufficient_funds() { fn should_emit_account_crossed_event_with_correct_value() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); - assert_ok!(Styx::cross(Origin::signed(ALICE))); + assert_ok!(Styx::cross(RuntimeOrigin::signed(ALICE))); System::assert_last_event( Event::AccountCrossed(ALICE, crate::BurnAmount::::get()).into(), ); diff --git a/zrml/swaps/Cargo.toml b/zrml/swaps/Cargo.toml index 051aca111..5ddf3aae3 100644 --- a/zrml/swaps/Cargo.toml +++ b/zrml/swaps/Cargo.toml @@ -1,11 +1,11 @@ [dependencies] -frame-benchmarking = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, optional = true, git = "https://github.com/zeitgeistpm/substrate" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -frame-system = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } +frame-benchmarking = { branch = "polkadot-v0.9.32", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-liquidity-mining = { default-features = false, path = "../liquidity-mining" } @@ -14,12 +14,12 @@ zrml-rikiddo = { default-features = false, path = "../rikiddo" } # Mock -orml-currencies = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -orml-tokens = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/open-runtime-module-library", optional = true } -pallet-balances = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -pallet-timestamp = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } -sp-io = { branch = "moonbeam-polkadot-v0.9.29", git = "https://github.com/zeitgeistpm/substrate", optional = true } +orml-currencies = { branch = "polkadot-v0.9.32", git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +orml-tokens = { branch = "polkadot-v0.9.32", git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } +pallet-balances = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +pallet-timestamp = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sp-api = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } +sp-io = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } zrml-swaps-runtime-api = { optional = true, path = "./runtime-api" } [dev-dependencies] diff --git a/zrml/swaps/fuzz/Cargo.toml b/zrml/swaps/fuzz/Cargo.toml index 430efcd92..900ff87a3 100644 --- a/zrml/swaps/fuzz/Cargo.toml +++ b/zrml/swaps/fuzz/Cargo.toml @@ -54,11 +54,11 @@ test = false [dependencies] arbitrary = { features = ["derive"], version = "1.0" } -frame-support = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } libfuzzer-sys = "0.4" -orml-traits = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/open-runtime-module-library" } +orml-traits = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } rand = "0.8.4" -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { features = ["mock"], path = "../../../primitives" } zrml-swaps = { features = ["mock"], path = ".." } diff --git a/zrml/swaps/fuzz/pool_exit.rs b/zrml/swaps/fuzz/pool_exit.rs index 20489be31..5b0c6e7be 100644 --- a/zrml/swaps/fuzz/pool_exit.rs +++ b/zrml/swaps/fuzz/pool_exit.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{ExtBuilder, RuntimeOrigin, Swaps}; mod utils; use orml_traits::currency::MultiCurrency; @@ -47,7 +47,7 @@ fuzz_target!(|data: GeneralPoolData| { data.pool_amount, ); let _ = Swaps::pool_exit( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, data.pool_amount, data.asset_bounds, diff --git a/zrml/swaps/fuzz/pool_exit_with_exact_asset_amount.rs b/zrml/swaps/fuzz/pool_exit_with_exact_asset_amount.rs index b57329429..9f983b131 100644 --- a/zrml/swaps/fuzz/pool_exit_with_exact_asset_amount.rs +++ b/zrml/swaps/fuzz/pool_exit_with_exact_asset_amount.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{ExtBuilder, RuntimeOrigin, Swaps}; mod utils; use orml_traits::currency::MultiCurrency; @@ -49,7 +49,7 @@ fuzz_target!(|data: ExactAssetAmountData| { data.pool_amount, ); let _ = Swaps::pool_exit_with_exact_asset_amount( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, construct_asset(data.asset), data.asset_amount, diff --git a/zrml/swaps/fuzz/pool_exit_with_exact_pool_amount.rs b/zrml/swaps/fuzz/pool_exit_with_exact_pool_amount.rs index 3de0eb4b7..a583da30e 100644 --- a/zrml/swaps/fuzz/pool_exit_with_exact_pool_amount.rs +++ b/zrml/swaps/fuzz/pool_exit_with_exact_pool_amount.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{ExtBuilder, RuntimeOrigin, Swaps}; mod utils; use orml_traits::currency::MultiCurrency; @@ -48,7 +48,7 @@ fuzz_target!(|data: ExactAmountData| { data.pool_amount, ); let _ = Swaps::pool_exit_with_exact_pool_amount( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, construct_asset(data.asset), data.pool_amount, diff --git a/zrml/swaps/fuzz/pool_join.rs b/zrml/swaps/fuzz/pool_join.rs index 18d28234d..76a1bf87c 100644 --- a/zrml/swaps/fuzz/pool_join.rs +++ b/zrml/swaps/fuzz/pool_join.rs @@ -21,7 +21,7 @@ use libfuzzer_sys::fuzz_target; use orml_traits::currency::MultiCurrency; use utils::GeneralPoolData; -use zrml_swaps::mock::{ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{ExtBuilder, RuntimeOrigin, Swaps}; mod utils; use utils::construct_asset; use zrml_swaps::mock::AssetManager; @@ -41,7 +41,7 @@ fuzz_target!(|data: GeneralPoolData| { let pool_id = data.pool_creation.create_pool(); // join a pool with a valid pool id let _ = Swaps::pool_join( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, data.pool_amount, data.asset_bounds, diff --git a/zrml/swaps/fuzz/pool_join_with_exact_asset_amount.rs b/zrml/swaps/fuzz/pool_join_with_exact_asset_amount.rs index 3b317472b..91f1808d6 100644 --- a/zrml/swaps/fuzz/pool_join_with_exact_asset_amount.rs +++ b/zrml/swaps/fuzz/pool_join_with_exact_asset_amount.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{ExtBuilder, RuntimeOrigin, Swaps}; use utils::ExactAssetAmountData; mod utils; @@ -41,7 +41,7 @@ fuzz_target!(|data: ExactAssetAmountData| { } let pool_id = data.pool_creation.create_pool(); let _ = Swaps::pool_join_with_exact_asset_amount( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, construct_asset(data.asset), data.asset_amount, diff --git a/zrml/swaps/fuzz/pool_join_with_exact_pool_amount.rs b/zrml/swaps/fuzz/pool_join_with_exact_pool_amount.rs index 6da473ee4..f480592dd 100644 --- a/zrml/swaps/fuzz/pool_join_with_exact_pool_amount.rs +++ b/zrml/swaps/fuzz/pool_join_with_exact_pool_amount.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{ExtBuilder, RuntimeOrigin, Swaps}; use utils::ExactAmountData; mod utils; @@ -41,7 +41,7 @@ fuzz_target!(|data: ExactAmountData| { } let pool_id = data.pool_creation.create_pool(); let _ = Swaps::pool_join_with_exact_pool_amount( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, construct_asset(data.asset), data.pool_amount, diff --git a/zrml/swaps/fuzz/swap_exact_amount_in.rs b/zrml/swaps/fuzz/swap_exact_amount_in.rs index 40d7a92c9..4aba80d2f 100644 --- a/zrml/swaps/fuzz/swap_exact_amount_in.rs +++ b/zrml/swaps/fuzz/swap_exact_amount_in.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{AssetManager, ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{AssetManager, ExtBuilder, RuntimeOrigin, Swaps}; use utils::SwapExactAmountInData; mod utils; @@ -44,7 +44,7 @@ fuzz_target!(|data: SwapExactAmountInData| { data.asset_amount_in, ); let _ = Swaps::swap_exact_amount_in( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, construct_asset(data.asset_in), data.asset_amount_in, diff --git a/zrml/swaps/fuzz/swap_exact_amount_out.rs b/zrml/swaps/fuzz/swap_exact_amount_out.rs index 32e9162b5..93eab4325 100644 --- a/zrml/swaps/fuzz/swap_exact_amount_out.rs +++ b/zrml/swaps/fuzz/swap_exact_amount_out.rs @@ -18,7 +18,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use zrml_swaps::mock::{AssetManager, ExtBuilder, Origin, Swaps}; +use zrml_swaps::mock::{AssetManager, ExtBuilder, RuntimeOrigin, Swaps}; mod utils; use orml_traits::currency::MultiCurrency; @@ -43,7 +43,7 @@ fuzz_target!(|data: SwapExactAmountOutData| { } let _ = Swaps::swap_exact_amount_out( - Origin::signed(data.origin), + RuntimeOrigin::signed(data.origin), pool_id, construct_asset(data.asset_in), data.asset_amount_in, diff --git a/zrml/swaps/rpc/Cargo.toml b/zrml/swaps/rpc/Cargo.toml index 640a11a10..dcb0ce1d5 100644 --- a/zrml/swaps/rpc/Cargo.toml +++ b/zrml/swaps/rpc/Cargo.toml @@ -1,9 +1,9 @@ [dependencies] jsonrpsee = { version = "0.15.1", features = ["server", "macros"] } parity-scale-codec = { default-features = false, version = "3.0.0" } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-blockchain = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-blockchain = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../../primitives" } zrml-swaps-runtime-api = { default-features = false, features = ["std"], path = "../runtime-api" } diff --git a/zrml/swaps/runtime-api/Cargo.toml b/zrml/swaps/runtime-api/Cargo.toml index 78023b6cf..67f337c10 100644 --- a/zrml/swaps/runtime-api/Cargo.toml +++ b/zrml/swaps/runtime-api/Cargo.toml @@ -1,7 +1,7 @@ [dependencies] parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } -sp-api = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } -sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } +sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } +sp-runtime = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../../primitives" } [features] diff --git a/zrml/swaps/src/benchmarks.rs b/zrml/swaps/src/benchmarks.rs index 7698325d5..e7a5b5178 100644 --- a/zrml/swaps/src/benchmarks.rs +++ b/zrml/swaps/src/benchmarks.rs @@ -47,7 +47,7 @@ use zeitgeist_primitives::{ }; use zrml_market_commons::MarketCommonsPalletApi; -fn assert_last_event(generic_event: ::Event) { +fn assert_last_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_last_event(generic_event.into()); } diff --git a/zrml/swaps/src/lib.rs b/zrml/swaps/src/lib.rs index 2b14990c7..12f712ab7 100644 --- a/zrml/swaps/src/lib.rs +++ b/zrml/swaps/src/lib.rs @@ -756,7 +756,7 @@ mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The fee for exiting a pool. #[pallet::constant] @@ -1097,7 +1097,7 @@ mod pallet { #[pallet::hooks] impl Hooks for Pallet { fn on_idle(_: T::BlockNumber, remaining_weight: Weight) -> Weight { - if remaining_weight < ON_IDLE_MIN_WEIGHT { + if remaining_weight.all_lt(ON_IDLE_MIN_WEIGHT) { return Weight::zero(); } Self::execute_arbitrage_all(remaining_weight / 2) diff --git a/zrml/swaps/src/mock.rs b/zrml/swaps/src/mock.rs index 527f311da..77f51bce4 100644 --- a/zrml/swaps/src/mock.rs +++ b/zrml/swaps/src/mock.rs @@ -84,7 +84,7 @@ construct_runtime!( pub type AssetManager = Currencies; impl crate::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExitFee = ExitFeeMock; type FixedTypeU = ::FixedTypeU; type FixedTypeS = ::FixedTypeS; @@ -115,9 +115,9 @@ impl frame_system::Config for Runtime { type BlockLength = (); type BlockNumber = BlockNumber; type BlockWeights = (); - type Call = Call; + type RuntimeCall = RuntimeCall; type DbWeight = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Hash = Hash; type Hashing = BlakeTwo256; type Header = Header; @@ -127,7 +127,7 @@ impl frame_system::Config for Runtime { type OnKilledAccount = (); type OnNewAccount = (); type OnSetCode = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = (); type SystemWeightInfo = (); @@ -146,13 +146,11 @@ impl orml_tokens::Config for Runtime { type Balance = Balance; type CurrencyId = CurrencyId; type DustRemovalWhitelist = Everything; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposits = ExistentialDeposits; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; - type OnDust = (); - type OnKilledTokenAccount = (); - type OnNewTokenAccount = (); + type CurrencyHooks = (); type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } @@ -161,7 +159,7 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; @@ -170,7 +168,7 @@ impl pallet_balances::Config for Runtime { } impl zrml_liquidity_mining::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type MarketCommons = MarketCommons; type MarketId = MarketId; type PalletId = LiquidityMiningPalletId; diff --git a/zrml/swaps/src/tests.rs b/zrml/swaps/src/tests.rs index f6976cd3b..a5d8a2967 100644 --- a/zrml/swaps/src/tests.rs +++ b/zrml/swaps/src/tests.rs @@ -403,7 +403,7 @@ fn destroy_pool_in_subsidy_phase_returns_subsidy_and_closes_pool() { // Reserve some funds for subsidy assert_ok!(Swaps::pool_join_subsidy(alice_signed(), pool_id, _25)); assert_ok!(Currencies::deposit(ASSET_D, &BOB, _26)); - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(BOB), pool_id, _26)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(BOB), pool_id, _26)); assert_eq!(Currencies::reserved_balance(ASSET_D, &ALICE), _25); assert_eq!(Currencies::reserved_balance(ASSET_D, &BOB), _26); @@ -435,7 +435,7 @@ fn distribute_pool_share_rewards() { subsidy_providers.iter().for_each(|provider| { assert_ok!(Currencies::deposit(base_asset, provider, subsidy_per_acc)); assert_ok!(Swaps::pool_join_subsidy( - Origin::signed(*provider), + RuntimeOrigin::signed(*provider), pool_id, subsidy_per_acc )); @@ -449,7 +449,7 @@ fn distribute_pool_share_rewards() { asset_holders.iter().for_each(|asset_holder| { assert_ok!(Currencies::deposit(base_asset, asset_holder, asset_per_acc + 20)); assert_ok!(Swaps::swap_exact_amount_out( - Origin::signed(*asset_holder), + RuntimeOrigin::signed(*asset_holder), pool_id, base_asset, Some(asset_per_acc + 20), @@ -511,8 +511,8 @@ fn end_subsidy_phase_distributes_shares_and_outcome_assets() { let subsidy_bob = min_subsidy + _25; assert_ok!(Currencies::deposit(ASSET_D, &ALICE, subsidy_alice)); assert_ok!(Currencies::deposit(ASSET_D, &BOB, subsidy_bob)); - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(ALICE), pool_id, min_subsidy)); - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(BOB), pool_id, subsidy_bob)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(ALICE), pool_id, min_subsidy)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(BOB), pool_id, subsidy_bob)); assert!(Swaps::end_subsidy_phase(pool_id).unwrap().result); // Check that subsidy was deposited, shares were distributed in exchange, the initial @@ -618,7 +618,7 @@ fn pool_join_fails_if_pool_is_closed() { let pool_id = 0; assert_ok!(Swaps::close_pool(pool_id)); assert_noop!( - Swaps::pool_join(Origin::signed(ALICE), pool_id, _1, vec![_1, _1, _1, _1]), + Swaps::pool_join(RuntimeOrigin::signed(ALICE), pool_id, _1, vec![_1, _1, _1, _1]), crate::Error::::InvalidPoolStatus, ); }); @@ -642,7 +642,7 @@ fn most_operations_fail_if_pool_is_clean() { )); assert_noop!( - Swaps::pool_join(Origin::signed(ALICE), pool_id, _1, vec![_10]), + Swaps::pool_join(RuntimeOrigin::signed(ALICE), pool_id, _1, vec![_10]), crate::Error::::InvalidPoolStatus, ); assert_noop!( @@ -821,7 +821,7 @@ fn pool_exit_with_exact_asset_amount_satisfies_max_out_ratio_constraints() { assert_noop!( Swaps::pool_exit_with_exact_asset_amount( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), pool_id, ASSET_A, _50, @@ -855,7 +855,7 @@ fn pool_exit_with_exact_pool_amount_satisfies_max_in_ratio_constraints() { assert_noop!( Swaps::pool_exit_with_exact_pool_amount( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), pool_id, ASSET_A, _50, @@ -1048,7 +1048,7 @@ fn pool_exit_emits_correct_events() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); create_initial_pool_with_funds_for_alice(ScoringRule::CPMM, Some(0), true); - assert_ok!(Swaps::pool_exit(Origin::signed(BOB), 0, _1, vec!(1, 2, 3, 4),)); + assert_ok!(Swaps::pool_exit(RuntimeOrigin::signed(BOB), 0, _1, vec!(1, 2, 3, 4),)); let amount = _1 - BASE / 10; // Subtract 10% fees! System::assert_last_event( Event::PoolExit(PoolAssetsEvent { @@ -1069,7 +1069,7 @@ fn pool_exit_decreases_correct_pool_parameters_with_exit_fee() { frame_system::Pallet::::set_block_number(1); create_initial_pool_with_funds_for_alice(ScoringRule::CPMM, Some(0), true); - assert_ok!(Swaps::pool_exit(Origin::signed(BOB), 0, _10, vec!(_1, _1, _1, _1),)); + assert_ok!(Swaps::pool_exit(RuntimeOrigin::signed(BOB), 0, _10, vec!(_1, _1, _1, _1),)); let pool_account = Swaps::pool_account_id(&0); let pool_shares_id = Swaps::pool_shares_id(0); @@ -1108,7 +1108,7 @@ fn pool_exit_decreases_correct_pool_parameters_on_cleaned_up_pool() { assert_ok!(Swaps::pool_join(alice_signed(), 0, _1, vec!(_1, _1, _1, _1),)); assert_ok!(Swaps::close_pool(0)); - assert_ok!(Swaps::admin_clean_up_pool(Origin::root(), 0, OutcomeReport::Categorical(65),)); + assert_ok!(Swaps::admin_clean_up_pool(RuntimeOrigin::root(), 0, OutcomeReport::Categorical(65),)); assert_ok!(Swaps::pool_exit(alice_signed(), 0, _1, vec!(_1, _1),)); System::assert_last_event( @@ -2273,12 +2273,12 @@ fn join_pool_exit_pool_does_not_create_extra_tokens() { let amount = 123_456_789_123; // Strange number to force rounding errors! assert_ok!(Swaps::pool_join( - Origin::signed(CHARLIE), + RuntimeOrigin::signed(CHARLIE), 0, amount, vec![_10000, _10000, _10000, _10000] )); - assert_ok!(Swaps::pool_exit(Origin::signed(CHARLIE), 0, amount, vec![0, 0, 0, 0])); + assert_ok!(Swaps::pool_exit(RuntimeOrigin::signed(CHARLIE), 0, amount, vec![0, 0, 0, 0])); // Check that the pool retains more tokens than before, and that Charlie loses some tokens // due to fees. @@ -2641,7 +2641,7 @@ fn single_asset_join_and_exit_are_inverse() { let pool_id = 0; assert_ok!(Currencies::deposit(asset, &ALICE, amount_in)); assert_ok!(Swaps::pool_join_with_exact_asset_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, asset, amount_in, @@ -2649,7 +2649,7 @@ fn single_asset_join_and_exit_are_inverse() { )); let pool_amount = Currencies::free_balance(Swaps::pool_shares_id(pool_id), &ALICE); assert_ok!(Swaps::pool_exit_with_exact_pool_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, asset, pool_amount, @@ -2678,7 +2678,7 @@ fn single_asset_operations_are_equivalent_to_swaps() { let pool_id = 0; assert_ok!(Currencies::deposit(asset_in, &ALICE, amount_in)); assert_ok!(Swaps::pool_join_with_exact_asset_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, asset_in, amount_in, @@ -2686,7 +2686,7 @@ fn single_asset_operations_are_equivalent_to_swaps() { )); let pool_amount = Currencies::free_balance(Swaps::pool_shares_id(pool_id), &ALICE); assert_ok!(Swaps::pool_exit_with_exact_pool_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, asset_out, pool_amount, @@ -2700,7 +2700,7 @@ fn single_asset_operations_are_equivalent_to_swaps() { let pool_id = 0; assert_ok!(Currencies::deposit(asset_in, &ALICE, amount_in)); assert_ok!(Swaps::swap_exact_amount_in( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, asset_in, amount_in, @@ -2723,7 +2723,7 @@ fn pool_join_with_uneven_balances() { let pool_id = 0; let pool_account_id = Swaps::pool_account_id(&pool_id); assert_ok!(Currencies::deposit(ASSET_A, &pool_account_id, _50)); - assert_ok!(Swaps::pool_join(Origin::signed(ALICE), pool_id, _10, vec![_100; 4])); + assert_ok!(Swaps::pool_join(RuntimeOrigin::signed(ALICE), pool_id, _10, vec![_100; 4])); assert_eq!(Currencies::free_balance(ASSET_A, &pool_account_id), _165); assert_eq!(Currencies::free_balance(ASSET_B, &pool_account_id), _110); assert_eq!(Currencies::free_balance(ASSET_C, &pool_account_id), _110); @@ -2764,7 +2764,7 @@ fn pool_exit_fails_if_balances_drop_too_low() { // We withdraw 99% of it, leaving 0.01 of each asset, which is below minimum balance. assert_noop!( - Swaps::pool_exit(Origin::signed(BOB), pool_id, _10, vec![0; 4]), + Swaps::pool_exit(RuntimeOrigin::signed(BOB), pool_id, _10, vec![0; 4]), crate::Error::::PoolDrain, ); }); @@ -2789,7 +2789,7 @@ fn pool_exit_fails_if_liquidity_drops_too_low() { // We withdraw too much liquidity but leave enough of each asset. assert_noop!( Swaps::pool_exit( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), pool_id, _100 - Swaps::min_balance(Swaps::pool_shares_id(pool_id)) + 1, vec![0; 4] @@ -2831,7 +2831,7 @@ fn swap_exact_amount_in_fails_if_balances_drop_too_low() { assert_noop!( Swaps::swap_exact_amount_in( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, Swaps::min_balance(ASSET_A) / 10, @@ -2876,7 +2876,7 @@ fn swap_exact_amount_out_fails_if_balances_drop_too_low() { assert_noop!( Swaps::swap_exact_amount_out( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, Some(u128::MAX), @@ -2920,7 +2920,7 @@ fn pool_exit_with_exact_pool_amount_fails_if_balances_drop_too_low() { )); assert_noop!( - Swaps::pool_exit_with_exact_pool_amount(Origin::signed(BOB), pool_id, ASSET_A, _1, 0), + Swaps::pool_exit_with_exact_pool_amount(RuntimeOrigin::signed(BOB), pool_id, ASSET_A, _1, 0), crate::Error::::PoolDrain, ); }); @@ -2947,7 +2947,7 @@ fn pool_exit_with_exact_pool_amount_fails_if_liquidity_drops_too_low() { let ten_percent_of_pool = Swaps::min_balance(pool_shares_id) / 10; assert_noop!( Swaps::pool_exit_with_exact_pool_amount( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), pool_id, ASSET_A, ten_percent_of_pool, @@ -2991,7 +2991,7 @@ fn pool_exit_with_exact_asset_amount_fails_if_balances_drop_too_low() { let ten_percent_of_balance = Swaps::min_balance(ASSET_A) / 10; assert_noop!( Swaps::pool_exit_with_exact_asset_amount( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), pool_id, ASSET_A, ten_percent_of_balance, @@ -3016,7 +3016,7 @@ fn pool_exit_with_exact_asset_amount_fails_if_liquidity_drops_too_low() { assert_noop!( Swaps::pool_exit_with_exact_asset_amount( - Origin::signed(BOB), + RuntimeOrigin::signed(BOB), pool_id, ASSET_A, _25, @@ -3034,7 +3034,7 @@ fn trading_functions_cache_pool_ids() { let pool_id = 0; assert_ok!(Swaps::pool_join_with_exact_pool_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, _2, @@ -3044,7 +3044,7 @@ fn trading_functions_cache_pool_ids() { PoolsCachedForArbitrage::::remove(pool_id); assert_ok!(Swaps::pool_join_with_exact_asset_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, _2, @@ -3054,7 +3054,7 @@ fn trading_functions_cache_pool_ids() { PoolsCachedForArbitrage::::remove(pool_id); assert_ok!(Swaps::pool_exit_with_exact_asset_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, _1, @@ -3064,7 +3064,7 @@ fn trading_functions_cache_pool_ids() { PoolsCachedForArbitrage::::remove(pool_id); assert_ok!(Swaps::pool_exit_with_exact_pool_amount( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, _1, @@ -3074,7 +3074,7 @@ fn trading_functions_cache_pool_ids() { PoolsCachedForArbitrage::::remove(pool_id); assert_ok!(Swaps::swap_exact_amount_in( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, _1, @@ -3086,7 +3086,7 @@ fn trading_functions_cache_pool_ids() { PoolsCachedForArbitrage::::remove(pool_id); assert_ok!(Swaps::swap_exact_amount_out( - Origin::signed(ALICE), + RuntimeOrigin::signed(ALICE), pool_id, ASSET_A, Some(u128::MAX), @@ -3379,8 +3379,8 @@ fn execute_arbitrage_observes_min_balances_mint_sell() { }); } -fn alice_signed() -> Origin { - Origin::signed(ALICE) +fn alice_signed() -> RuntimeOrigin { + RuntimeOrigin::signed(ALICE) } fn create_initial_pool( @@ -3457,7 +3457,7 @@ fn subsidize_and_start_rikiddo_pool( ) { let min_subsidy = ::MinSubsidy::get(); assert_ok!(Currencies::deposit(ASSET_D, who, min_subsidy + extra)); - assert_ok!(Swaps::pool_join_subsidy(Origin::signed(*who), pool_id, min_subsidy)); + assert_ok!(Swaps::pool_join_subsidy(RuntimeOrigin::signed(*who), pool_id, min_subsidy)); assert!(Swaps::end_subsidy_phase(pool_id).unwrap().result); } From 88ab0b6eb3e9df4b24601ea8245be770a8de3183 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Tue, 7 Feb 2023 17:46:37 +0530 Subject: [PATCH 03/22] clippy + fmt --- external/nimbus-consensus/Cargo.toml | 8 +- external/nimbus-consensus/src/import_queue.rs | 384 +- external/nimbus-consensus/src/lib.rs | 662 +- external/nimbus-consensus/src/manual_seal.rs | 183 +- external/nimbus-primitives/Cargo.toml | 50 +- external/nimbus-primitives/src/digests.rs | 80 +- external/nimbus-primitives/src/inherents.rs | 44 +- external/nimbus-primitives/src/lib.rs | 117 +- external/pallets/author-inherent/Cargo.toml | 66 +- .../pallets/author-inherent/src/benchmarks.rs | 13 +- external/pallets/author-inherent/src/exec.rs | 105 +- external/pallets/author-inherent/src/lib.rs | 376 +- external/pallets/author-inherent/src/mock.rs | 117 +- external/pallets/author-inherent/src/tests.rs | 71 +- .../pallets/author-inherent/src/weights.rs | 46 +- external/pallets/author-mapping/Cargo.toml | 42 +- .../pallets/author-mapping/src/benchmarks.rs | 230 +- external/pallets/author-mapping/src/lib.rs | 681 +- .../pallets/author-mapping/src/migrations.rs | 276 +- external/pallets/author-mapping/src/mock.rs | 243 +- external/pallets/author-mapping/src/tests.rs | 702 +- .../pallets/author-mapping/src/weights.rs | 146 +- .../pallets/author-slot-filter/Cargo.toml | 52 +- .../author-slot-filter/src/benchmarks.rs | 37 +- .../pallets/author-slot-filter/src/lib.rs | 362 +- .../author-slot-filter/src/migration.rs | 105 +- .../pallets/author-slot-filter/src/mock.rs | 98 +- .../pallets/author-slot-filter/src/num.rs | 155 +- .../pallets/author-slot-filter/src/tests.rs | 115 +- .../pallets/author-slot-filter/src/weights.rs | 19 +- external/pallets/parachain-staking/Cargo.toml | 32 +- .../parachain-staking/src/auto_compound.rs | 627 +- .../parachain-staking/src/benchmarks.rs | 2839 ++-- .../src/delegation_requests.rs | 1247 +- .../parachain-staking/src/inflation.rs | 304 +- external/pallets/parachain-staking/src/lib.rs | 3616 ++-- .../parachain-staking/src/migrations.rs | 279 +- .../pallets/parachain-staking/src/mock.rs | 1450 +- external/pallets/parachain-staking/src/set.rs | 98 +- .../pallets/parachain-staking/src/tests.rs | 13766 +++++++--------- .../pallets/parachain-staking/src/traits.rs | 56 +- .../pallets/parachain-staking/src/types.rs | 3001 ++-- .../pallets/parachain-staking/src/weights.rs | 1684 +- external/session-keys/Cargo.toml | 40 +- external/session-keys/src/digest.rs | 48 +- external/session-keys/src/inherent.rs | 64 +- external/session-keys/src/lib.rs | 24 +- external/session-keys/src/vrf.rs | 60 +- external/vrf/Cargo.toml | 6 +- external/vrf/src/lib.rs | 70 +- node/Cargo.toml | 2 +- node/src/command.rs | 7 +- node/src/service/service_parachain.rs | 4 +- .../src/integration_tests/xcm/setup.rs | 9 +- .../src/integration_tests/xcm/test_net.rs | 2 +- .../integration_tests/xcm/tests/transfers.rs | 10 +- .../battery-station/src/parachain_params.rs | 2 +- runtime/battery-station/src/parameters.rs | 7 +- .../battery-station/src/xcm_config/config.rs | 6 +- runtime/common/src/lib.rs | 2 +- .../src/integration_tests/xcm/setup.rs | 9 +- .../src/integration_tests/xcm/test_net.rs | 2 +- .../integration_tests/xcm/tests/transfers.rs | 10 +- runtime/zeitgeist/src/parachain_params.rs | 2 +- runtime/zeitgeist/src/parameters.rs | 7 +- runtime/zeitgeist/src/xcm_config/config.rs | 6 +- zrml/authorized/src/tests.rs | 8 +- zrml/court/src/tests.rs | 4 +- zrml/liquidity-mining/src/tests.rs | 2 +- .../fuzz/orderbook_v1_full_workflow.rs | 3 +- zrml/orderbook-v1/src/tests.rs | 8 +- .../fuzz/pm_full_workflow.rs | 2 +- zrml/prediction-markets/src/lib.rs | 3 +- zrml/prediction-markets/src/migrations.rs | 3 +- zrml/prediction-markets/src/tests.rs | 90 +- zrml/styx/src/tests.rs | 5 +- zrml/swaps/src/tests.rs | 14 +- 77 files changed, 16239 insertions(+), 18886 deletions(-) diff --git a/external/nimbus-consensus/Cargo.toml b/external/nimbus-consensus/Cargo.toml index f81859551..783b1f44d 100644 --- a/external/nimbus-consensus/Cargo.toml +++ b/external/nimbus-consensus/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "nimbus-consensus" description = "Client-side worker for the Nimbus family of consensus algorithms" edition = "2021" +name = "nimbus-consensus" version = "0.9.0" [dependencies] # Substrate deps @@ -20,7 +20,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkad substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } # Polkadot dependencies -polkadot-client = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "release-v0.9.32" } +polkadot-client = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.32" } # Cumulus dependencies cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } @@ -32,8 +32,8 @@ nimbus-primitives = { path = "../nimbus-primitives" } # Other deps async-trait = "0.1" -codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } -futures = { version = "0.3.24", features = [ "compat" ] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +futures = { version = "0.3.24", features = ["compat"] } log = "0.4.17" parking_lot = "0.12" tracing = "0.1.22" diff --git a/external/nimbus-consensus/src/import_queue.rs b/external/nimbus-consensus/src/import_queue.rs index 54c407104..09560669a 100644 --- a/external/nimbus-consensus/src/import_queue.rs +++ b/external/nimbus-consensus/src/import_queue.rs @@ -19,8 +19,8 @@ use std::{marker::PhantomData, sync::Arc}; use log::debug; use nimbus_primitives::{digests::CompatibleDigestItem, NimbusId, NimbusPair, NIMBUS_ENGINE_ID}; use sc_consensus::{ - import_queue::{BasicQueue, Verifier as VerifierT}, - BlockImport, BlockImportParams, + import_queue::{BasicQueue, Verifier as VerifierT}, + BlockImport, BlockImportParams, }; use sp_api::ProvideRuntimeApi; use sp_application_crypto::{ByteArray, Pair as _}; @@ -29,9 +29,9 @@ use sp_blockchain::Result as ClientResult; use sp_consensus::{error::Error as ConsensusError, CacheKeyId}; use sp_inherents::{CreateInherentDataProviders, InherentDataProvider}; use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT}, - DigestItem, + generic::BlockId, + traits::{Block as BlockT, Header as HeaderT}, + DigestItem, }; /// The Nimbus verifier strips the seal digest, and checks that it is a valid signature by @@ -40,180 +40,161 @@ use sp_runtime::{ /// is valid. The intention is that the runtime itself may then put further restrictions on /// the identity of the author. struct Verifier { - client: Arc, - create_inherent_data_providers: CIDP, - _marker: PhantomData, + client: Arc, + create_inherent_data_providers: CIDP, + _marker: PhantomData, } #[async_trait::async_trait] impl VerifierT for Verifier where - Block: BlockT, - Client: ProvideRuntimeApi + Send + Sync, - >::Api: BlockBuilderApi, - CIDP: CreateInherentDataProviders, + Block: BlockT, + Client: ProvideRuntimeApi + Send + Sync, + >::Api: BlockBuilderApi, + CIDP: CreateInherentDataProviders, { - async fn verify( - &mut self, - mut block_params: BlockImportParams, - ) -> Result< - ( - BlockImportParams, - Option)>>, - ), - String, - > { - debug!( - target: crate::LOG_TARGET, - "🪲 Header hash before popping digest {:?}", - block_params.header.hash() - ); - // Grab the seal digest. Assume it is last (since it is a seal after-all). - let seal = block_params - .header - .digest_mut() - .pop() - .expect("Block should have at least one digest on it"); - - let signature = seal - .as_nimbus_seal() - .ok_or_else(|| String::from("HeaderUnsealed"))?; - - debug!( - target: crate::LOG_TARGET, - "🪲 Header hash after popping digest {:?}", - block_params.header.hash() - ); - - debug!( - target: crate::LOG_TARGET, - "🪲 Signature according to verifier is {:?}", signature - ); - - // Grab the author information from either the preruntime digest or the consensus digest - //TODO use the trait - let claimed_author = block_params - .header - .digest() - .logs - .iter() - .find_map(|digest| match *digest { - DigestItem::Consensus(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - _ => None, - }) - .expect("Expected one consensus or pre-runtime digest that contains author id bytes"); - - debug!( - target: crate::LOG_TARGET, - "🪲 Claimed Author according to verifier is {:?}", claimed_author - ); - - // Verify the signature - let valid_signature = NimbusPair::verify( - &signature, - block_params.header.hash(), - &NimbusId::from_slice(&claimed_author) - .map_err(|_| "Invalid Nimbus ID (wrong length)")?, - ); - - debug!( - target: crate::LOG_TARGET, - "🪲 Valid signature? {:?}", valid_signature - ); - - if !valid_signature { - return Err("Block signature invalid".into()); - } - - // This part copied from RelayChainConsensus. I guess this is the inherent checking. - if let Some(inner_body) = block_params.body.take() { - let inherent_data_providers = self - .create_inherent_data_providers - .create_inherent_data_providers(*block_params.header.parent_hash(), ()) - .await - .map_err(|e| e.to_string())?; - - let inherent_data = inherent_data_providers - .create_inherent_data() - .map_err(|e| format!("{:?}", e))?; - - let block = Block::new(block_params.header.clone(), inner_body); - - let inherent_res = self - .client - .runtime_api() - .check_inherents( - &BlockId::Hash(*block_params.header.parent_hash()), - block.clone(), - inherent_data, - ) - .map_err(|e| format!("{:?}", e))?; - - if !inherent_res.ok() { - for (i, e) in inherent_res.into_errors() { - match inherent_data_providers.try_handle_error(&i, &e).await { - Some(r) => r.map_err(|e| format!("{:?}", e))?, - None => Err(format!( - "Unhandled inherent error from `{}`.", - String::from_utf8_lossy(&i) - ))?, - } - } - } - - let (_, inner_body) = block.deconstruct(); - block_params.body = Some(inner_body); - } - - block_params.post_digests.push(seal); - - // The standard is to use the longest chain rule. This is overridden by the `NimbusBlockImport` in the parachain context. - block_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::LongestChain); - - debug!( - target: crate::LOG_TARGET, - "🪲 Just finished verifier. posthash from params is {:?}", - &block_params.post_hash() - ); - - Ok((block_params, None)) - } + async fn verify( + &mut self, + mut block_params: BlockImportParams, + ) -> Result<(BlockImportParams, Option)>>), String> { + debug!( + target: crate::LOG_TARGET, + "🪲 Header hash before popping digest {:?}", + block_params.header.hash() + ); + // Grab the seal digest. Assume it is last (since it is a seal after-all). + let seal = block_params + .header + .digest_mut() + .pop() + .expect("Block should have at least one digest on it"); + + let signature = seal.as_nimbus_seal().ok_or_else(|| String::from("HeaderUnsealed"))?; + + debug!( + target: crate::LOG_TARGET, + "🪲 Header hash after popping digest {:?}", + block_params.header.hash() + ); + + debug!(target: crate::LOG_TARGET, "🪲 Signature according to verifier is {:?}", signature); + + // Grab the author information from either the preruntime digest or the consensus digest + //TODO use the trait + let claimed_author = block_params + .header + .digest() + .logs + .iter() + .find_map(|digest| match *digest { + DigestItem::Consensus(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + _ => None, + }) + .expect("Expected one consensus or pre-runtime digest that contains author id bytes"); + + debug!( + target: crate::LOG_TARGET, + "🪲 Claimed Author according to verifier is {:?}", claimed_author + ); + + // Verify the signature + let valid_signature = NimbusPair::verify( + &signature, + block_params.header.hash(), + &NimbusId::from_slice(&claimed_author) + .map_err(|_| "Invalid Nimbus ID (wrong length)")?, + ); + + debug!(target: crate::LOG_TARGET, "🪲 Valid signature? {:?}", valid_signature); + + if !valid_signature { + return Err("Block signature invalid".into()); + } + + // This part copied from RelayChainConsensus. I guess this is the inherent checking. + if let Some(inner_body) = block_params.body.take() { + let inherent_data_providers = self + .create_inherent_data_providers + .create_inherent_data_providers(*block_params.header.parent_hash(), ()) + .await + .map_err(|e| e.to_string())?; + + let inherent_data = + inherent_data_providers.create_inherent_data().map_err(|e| format!("{:?}", e))?; + + let block = Block::new(block_params.header.clone(), inner_body); + + let inherent_res = self + .client + .runtime_api() + .check_inherents( + &BlockId::Hash(*block_params.header.parent_hash()), + block.clone(), + inherent_data, + ) + .map_err(|e| format!("{:?}", e))?; + + if !inherent_res.ok() { + for (i, e) in inherent_res.into_errors() { + match inherent_data_providers.try_handle_error(&i, &e).await { + Some(r) => r.map_err(|e| format!("{:?}", e))?, + None => Err(format!( + "Unhandled inherent error from `{}`.", + String::from_utf8_lossy(&i) + ))?, + } + } + } + + let (_, inner_body) = block.deconstruct(); + block_params.body = Some(inner_body); + } + + block_params.post_digests.push(seal); + + // The standard is to use the longest chain rule. This is overridden by the `NimbusBlockImport` in the parachain context. + block_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::LongestChain); + + debug!( + target: crate::LOG_TARGET, + "🪲 Just finished verifier. posthash from params is {:?}", + &block_params.post_hash() + ); + + Ok((block_params, None)) + } } /// Start an import queue for a Cumulus collator that does not uses any special authoring logic. pub fn import_queue( - client: Arc, - block_import: I, - create_inherent_data_providers: CIDP, - spawner: &impl sp_core::traits::SpawnEssentialNamed, - registry: Option<&substrate_prometheus_endpoint::Registry>, - parachain: bool, + client: Arc, + block_import: I, + create_inherent_data_providers: CIDP, + spawner: &impl sp_core::traits::SpawnEssentialNamed, + registry: Option<&substrate_prometheus_endpoint::Registry>, + parachain: bool, ) -> ClientResult> where - I: BlockImport + Send + Sync + 'static, - I::Transaction: Send, - Client: ProvideRuntimeApi + Send + Sync + 'static, - >::Api: BlockBuilderApi, - CIDP: CreateInherentDataProviders + 'static, + I: BlockImport + Send + Sync + 'static, + I::Transaction: Send, + Client: ProvideRuntimeApi + Send + Sync + 'static, + >::Api: BlockBuilderApi, + CIDP: CreateInherentDataProviders + 'static, { - let verifier = Verifier { - client, - create_inherent_data_providers, - _marker: PhantomData, - }; - - Ok(BasicQueue::new( - verifier, - Box::new(NimbusBlockImport::new(block_import, parachain)), - None, - spawner, - registry, - )) + let verifier = Verifier { client, create_inherent_data_providers, _marker: PhantomData }; + + Ok(BasicQueue::new( + verifier, + Box::new(NimbusBlockImport::new(block_import, parachain)), + None, + spawner, + registry, + )) } /// Nimbus specific block import. @@ -226,50 +207,47 @@ where /// There may be additional nimbus-specific logic here in the future, but for now it is /// only the conditional parachain logic pub struct NimbusBlockImport { - inner: I, - parachain_context: bool, + inner: I, + parachain_context: bool, } impl NimbusBlockImport { - /// Create a new instance. - pub fn new(inner: I, parachain_context: bool) -> Self { - Self { - inner, - parachain_context, - } - } + /// Create a new instance. + pub fn new(inner: I, parachain_context: bool) -> Self { + Self { inner, parachain_context } + } } #[async_trait::async_trait] impl BlockImport for NimbusBlockImport where - Block: BlockT, - I: BlockImport + Send, + Block: BlockT, + I: BlockImport + Send, { - type Error = I::Error; - type Transaction = I::Transaction; - - async fn check_block( - &mut self, - block: sc_consensus::BlockCheckParams, - ) -> Result { - self.inner.check_block(block).await - } - - async fn import_block( - &mut self, - mut block_import_params: sc_consensus::BlockImportParams, - cache: std::collections::HashMap>, - ) -> Result { - // If we are in the parachain context, best block is determined by the relay chain - // except during initial sync - if self.parachain_context { - block_import_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::Custom( - block_import_params.origin == sp_consensus::BlockOrigin::NetworkInitialSync, - )); - } - - // Now continue on to the rest of the import pipeline. - self.inner.import_block(block_import_params, cache).await - } + type Error = I::Error; + type Transaction = I::Transaction; + + async fn check_block( + &mut self, + block: sc_consensus::BlockCheckParams, + ) -> Result { + self.inner.check_block(block).await + } + + async fn import_block( + &mut self, + mut block_import_params: sc_consensus::BlockImportParams, + cache: std::collections::HashMap>, + ) -> Result { + // If we are in the parachain context, best block is determined by the relay chain + // except during initial sync + if self.parachain_context { + block_import_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::Custom( + block_import_params.origin == sp_consensus::BlockOrigin::NetworkInitialSync, + )); + } + + // Now continue on to the rest of the import pipeline. + self.inner.import_block(block_import_params, cache).await + } } diff --git a/external/nimbus-consensus/src/lib.rs b/external/nimbus-consensus/src/lib.rs index 8392f3056..e4a711fee 100644 --- a/external/nimbus-consensus/src/lib.rs +++ b/external/nimbus-consensus/src/lib.rs @@ -21,29 +21,28 @@ //! key it authors. use cumulus_client_consensus_common::{ - ParachainBlockImport, ParachainCandidate, ParachainConsensus, + ParachainBlockImport, ParachainCandidate, ParachainConsensus, }; use cumulus_primitives_core::{relay_chain::v2::Hash as PHash, ParaId, PersistedValidationData}; pub use import_queue::import_queue; use log::{debug, info, warn}; use nimbus_primitives::{ - CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_KEY_ID, + CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_KEY_ID, }; use parking_lot::Mutex; use sc_consensus::{BlockImport, BlockImportParams}; use sp_api::{BlockId, ProvideRuntimeApi}; use sp_application_crypto::{ByteArray, CryptoTypePublicPair}; use sp_consensus::{ - BlockOrigin, EnableProofRecording, Environment, ProofRecording, Proposal, Proposer, + BlockOrigin, EnableProofRecording, Environment, ProofRecording, Proposal, Proposer, }; use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ - traits::{Block as BlockT, Header as HeaderT}, - DigestItem, + traits::{Block as BlockT, Header as HeaderT}, + DigestItem, }; -use std::convert::TryInto; -use std::{marker::PhantomData, sync::Arc, time::Duration}; +use std::{convert::TryInto, marker::PhantomData, sync::Arc, time::Duration}; use tracing::error; mod import_queue; mod manual_seal; @@ -53,109 +52,109 @@ const LOG_TARGET: &str = "filtering-consensus"; /// The implementation of the relay-chain provided consensus for parachains. pub struct NimbusConsensus { - para_id: ParaId, - proposer_factory: Arc>, - create_inherent_data_providers: Arc, - block_import: Arc>>, - parachain_client: Arc, - keystore: SyncCryptoStorePtr, - skip_prediction: bool, - additional_digests_provider: Arc, - _phantom: PhantomData, + para_id: ParaId, + proposer_factory: Arc>, + create_inherent_data_providers: Arc, + block_import: Arc>>, + parachain_client: Arc, + keystore: SyncCryptoStorePtr, + skip_prediction: bool, + additional_digests_provider: Arc, + _phantom: PhantomData, } impl Clone for NimbusConsensus { - fn clone(&self) -> Self { - Self { - para_id: self.para_id, - proposer_factory: self.proposer_factory.clone(), - create_inherent_data_providers: self.create_inherent_data_providers.clone(), - block_import: self.block_import.clone(), - parachain_client: self.parachain_client.clone(), - keystore: self.keystore.clone(), - skip_prediction: self.skip_prediction, - additional_digests_provider: self.additional_digests_provider.clone(), - _phantom: PhantomData, - } - } + fn clone(&self) -> Self { + Self { + para_id: self.para_id, + proposer_factory: self.proposer_factory.clone(), + create_inherent_data_providers: self.create_inherent_data_providers.clone(), + block_import: self.block_import.clone(), + parachain_client: self.parachain_client.clone(), + keystore: self.keystore.clone(), + skip_prediction: self.skip_prediction, + additional_digests_provider: self.additional_digests_provider.clone(), + _phantom: PhantomData, + } + } } impl NimbusConsensus where - B: BlockT, - PF: 'static, - BI: 'static, - ParaClient: ProvideRuntimeApi + 'static, - CIDP: CreateInherentDataProviders + 'static, - DP: DigestsProvider::Hash> + 'static, + B: BlockT, + PF: 'static, + BI: 'static, + ParaClient: ProvideRuntimeApi + 'static, + CIDP: CreateInherentDataProviders + 'static, + DP: DigestsProvider::Hash> + 'static, { - /// Create a new instance of nimbus consensus. - pub fn build( - BuildNimbusConsensusParams { - para_id, - proposer_factory, - create_inherent_data_providers, - block_import, - parachain_client, - keystore, - skip_prediction, - additional_digests_provider, - }: BuildNimbusConsensusParams, - ) -> Box> - where - Self: ParachainConsensus, - { - Box::new(Self { - para_id, - proposer_factory: Arc::new(Mutex::new(proposer_factory)), - create_inherent_data_providers: Arc::new(create_inherent_data_providers), - block_import: Arc::new(futures::lock::Mutex::new(ParachainBlockImport::new( - block_import, - ))), - parachain_client, - keystore, - skip_prediction, - additional_digests_provider: Arc::new(additional_digests_provider), - _phantom: PhantomData, - }) - } - - //TODO Could this be a provided implementation now that we have this async inherent stuff? - /// Create the data. - async fn inherent_data( - &self, - parent: B::Hash, - validation_data: &PersistedValidationData, - relay_parent: PHash, - author_id: NimbusId, - ) -> Option { - let inherent_data_providers = self - .create_inherent_data_providers - .create_inherent_data_providers( - parent, - (relay_parent, validation_data.clone(), author_id), - ) - .await - .map_err(|e| { - tracing::error!( - target: LOG_TARGET, - error = ?e, - "Failed to create inherent data providers.", - ) - }) - .ok()?; - - inherent_data_providers - .create_inherent_data() - .map_err(|e| { - tracing::error!( - target: LOG_TARGET, - error = ?e, - "Failed to create inherent data.", - ) - }) - .ok() - } + /// Create a new instance of nimbus consensus. + pub fn build( + BuildNimbusConsensusParams { + para_id, + proposer_factory, + create_inherent_data_providers, + block_import, + parachain_client, + keystore, + skip_prediction, + additional_digests_provider, + }: BuildNimbusConsensusParams, + ) -> Box> + where + Self: ParachainConsensus, + { + Box::new(Self { + para_id, + proposer_factory: Arc::new(Mutex::new(proposer_factory)), + create_inherent_data_providers: Arc::new(create_inherent_data_providers), + block_import: Arc::new(futures::lock::Mutex::new(ParachainBlockImport::new( + block_import, + ))), + parachain_client, + keystore, + skip_prediction, + additional_digests_provider: Arc::new(additional_digests_provider), + _phantom: PhantomData, + }) + } + + //TODO Could this be a provided implementation now that we have this async inherent stuff? + /// Create the data. + async fn inherent_data( + &self, + parent: B::Hash, + validation_data: &PersistedValidationData, + relay_parent: PHash, + author_id: NimbusId, + ) -> Option { + let inherent_data_providers = self + .create_inherent_data_providers + .create_inherent_data_providers( + parent, + (relay_parent, validation_data.clone(), author_id), + ) + .await + .map_err(|e| { + tracing::error!( + target: LOG_TARGET, + error = ?e, + "Failed to create inherent data providers.", + ) + }) + .ok()?; + + inherent_data_providers + .create_inherent_data() + .map_err(|e| { + tracing::error!( + target: LOG_TARGET, + error = ?e, + "Failed to create inherent data.", + ) + }) + .ok() + } } /// Grabs any available nimbus key from the keystore. @@ -164,20 +163,17 @@ where /// expected to be eligible. Concretely, this is used in the consensus worker /// to implement the `skip_prediction` feature. pub(crate) fn first_available_key(keystore: &dyn SyncCryptoStore) -> Option { - // Get all the available keys - let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) - .expect("keystore should return the keys it has"); - - // Print a more helpful message than "not eligible" when there are no keys at all. - if available_keys.is_empty() { - warn!( - target: LOG_TARGET, - "🔏 No Nimbus keys available. We will not be able to author." - ); - return None; - } - - Some(available_keys[0].clone()) + // Get all the available keys + let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) + .expect("keystore should return the keys it has"); + + // Print a more helpful message than "not eligible" when there are no keys at all. + if available_keys.is_empty() { + warn!(target: LOG_TARGET, "🔏 No Nimbus keys available. We will not be able to author."); + return None; + } + + Some(available_keys[0].clone()) } /// Grab the first eligible nimbus key from the keystore @@ -185,246 +181,222 @@ pub(crate) fn first_available_key(keystore: &dyn SyncCryptoStore) -> Option( - client: Arc, - keystore: &dyn SyncCryptoStore, - parent: &B::Header, - slot_number: u32, + client: Arc, + keystore: &dyn SyncCryptoStore, + parent: &B::Header, + slot_number: u32, ) -> Option where - C: ProvideRuntimeApi, - C::Api: NimbusApi, + C: ProvideRuntimeApi, + C::Api: NimbusApi, { - // Get all the available keys - let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) - .expect("keystore should return the keys it has"); - - // Print a more helpful message than "not eligible" when there are no keys at all. - if available_keys.is_empty() { - warn!( - target: LOG_TARGET, - "🔏 No Nimbus keys available. We will not be able to author." - ); - return None; - } - - let at = BlockId::Hash(parent.hash()); - - // Iterate keys until we find an eligible one, or run out of candidates. - // If we are skipping prediction, then we author with the first key we find. - // prediction skipping only really makes sense when there is a single key in the keystore. - let maybe_key = available_keys.into_iter().find(|type_public_pair| { - // Have to convert to a typed NimbusId to pass to the runtime API. Maybe this is a clue - // That I should be passing Vec across the wasm boundary? - NimbusApi::can_author( - &*client.runtime_api(), - &at, - NimbusId::from_slice(&type_public_pair.1).expect("Provided keys should be valid"), - slot_number, - parent, - ) - .expect("NimbusAPI should not return error") - }); - - // If there are no eligible keys, print the log, and exit early. - if maybe_key.is_none() { - info!( - target: LOG_TARGET, - "🔮 Skipping candidate production because we are not eligible for slot {}", slot_number - ); - } - - maybe_key + // Get all the available keys + let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) + .expect("keystore should return the keys it has"); + + // Print a more helpful message than "not eligible" when there are no keys at all. + if available_keys.is_empty() { + warn!(target: LOG_TARGET, "🔏 No Nimbus keys available. We will not be able to author."); + return None; + } + + let at = BlockId::Hash(parent.hash()); + + // Iterate keys until we find an eligible one, or run out of candidates. + // If we are skipping prediction, then we author with the first key we find. + // prediction skipping only really makes sense when there is a single key in the keystore. + let maybe_key = available_keys.into_iter().find(|type_public_pair| { + // Have to convert to a typed NimbusId to pass to the runtime API. Maybe this is a clue + // That I should be passing Vec across the wasm boundary? + NimbusApi::can_author( + &*client.runtime_api(), + &at, + NimbusId::from_slice(&type_public_pair.1).expect("Provided keys should be valid"), + slot_number, + parent, + ) + .expect("NimbusAPI should not return error") + }); + + // If there are no eligible keys, print the log, and exit early. + if maybe_key.is_none() { + info!( + target: LOG_TARGET, + "🔮 Skipping candidate production because we are not eligible for slot {}", slot_number + ); + } + + maybe_key } pub(crate) fn seal_header( - header: &B::Header, - keystore: &dyn SyncCryptoStore, - type_public_pair: &CryptoTypePublicPair, + header: &B::Header, + keystore: &dyn SyncCryptoStore, + type_public_pair: &CryptoTypePublicPair, ) -> DigestItem where - B: BlockT, + B: BlockT, { - let pre_hash = header.hash(); + let pre_hash = header.hash(); - let raw_sig = SyncCryptoStore::sign_with( - &*keystore, - NIMBUS_KEY_ID, - type_public_pair, - pre_hash.as_ref(), - ) - .expect("Keystore should be able to sign") - .expect("We already checked that the key was present"); + let raw_sig = + SyncCryptoStore::sign_with(keystore, NIMBUS_KEY_ID, type_public_pair, pre_hash.as_ref()) + .expect("Keystore should be able to sign") + .expect("We already checked that the key was present"); - debug!(target: LOG_TARGET, "The signature is \n{:?}", raw_sig); + debug!(target: LOG_TARGET, "The signature is \n{:?}", raw_sig); - let signature = raw_sig - .clone() - .try_into() - .expect("signature bytes produced by keystore should be right length"); + let signature = + raw_sig.try_into().expect("signature bytes produced by keystore should be right length"); - ::nimbus_seal(signature) + ::nimbus_seal(signature) } #[async_trait::async_trait] impl ParachainConsensus - for NimbusConsensus + for NimbusConsensus where - B: BlockT, - BI: BlockImport + Send + Sync + 'static, - PF: Environment + Send + Sync + 'static, - PF::Proposer: Proposer< - B, - Transaction = BI::Transaction, - ProofRecording = EnableProofRecording, - Proof = ::Proof, - >, - ParaClient: ProvideRuntimeApi + Send + Sync + 'static, - ParaClient::Api: NimbusApi, - CIDP: CreateInherentDataProviders + 'static, - DP: DigestsProvider::Hash> + 'static + Send + Sync, + B: BlockT, + BI: BlockImport + Send + Sync + 'static, + PF: Environment + Send + Sync + 'static, + PF::Proposer: Proposer< + B, + Transaction = BI::Transaction, + ProofRecording = EnableProofRecording, + Proof = ::Proof, + >, + ParaClient: ProvideRuntimeApi + Send + Sync + 'static, + ParaClient::Api: NimbusApi, + CIDP: CreateInherentDataProviders + 'static, + DP: DigestsProvider::Hash> + 'static + Send + Sync, { - async fn produce_candidate( - &mut self, - parent: &B::Header, - relay_parent: PHash, - validation_data: &PersistedValidationData, - ) -> Option> { - // Determine if runtime change - let runtime_upgraded = if *parent.number() > sp_runtime::traits::Zero::zero() { - let at = BlockId::Hash(parent.hash()); - let parent_at = BlockId::::Hash(*parent.parent_hash()); - use sp_api::Core as _; - let previous_runtime_version: sp_api::RuntimeVersion = self - .parachain_client - .runtime_api() - .version(&parent_at) - .expect("Runtime api access to not error."); - let runtime_version: sp_api::RuntimeVersion = self - .parachain_client - .runtime_api() - .version(&at) - .expect("Runtime api access to not error."); - - previous_runtime_version != runtime_version - } else { - false - }; - - let maybe_key = if self.skip_prediction || runtime_upgraded { - first_available_key(&*self.keystore) - } else { - first_eligible_key::( - self.parachain_client.clone(), - &*self.keystore, - parent, - validation_data.relay_parent_number, - ) - }; - - // If there are no eligible keys, print the log, and exit early. - let type_public_pair = match maybe_key { - Some(p) => p, - None => { - return None; - } - }; - - let proposer_future = self.proposer_factory.lock().init(&parent); - - let proposer = proposer_future - .await - .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Could not create proposer.")) - .ok()?; - - let nimbus_id = NimbusId::from_slice(&type_public_pair.1) - .map_err( - |e| error!(target: LOG_TARGET, error = ?e, "Invalid Nimbus ID (wrong length)."), - ) - .ok()?; - - let inherent_data = self - .inherent_data( - parent.hash(), - &validation_data, - relay_parent, - nimbus_id.clone(), - ) - .await?; - - let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; - logs.extend( - self.additional_digests_provider - .provide_digests(nimbus_id, parent.hash()), - ); - let inherent_digests = sp_runtime::generic::Digest { logs }; - - let Proposal { - block, - storage_changes, - proof, - } = proposer - .propose( - inherent_data, - inherent_digests, - //TODO: Fix this. - Duration::from_millis(500), - // Set the block limit to 50% of the maximum PoV size. - // - // TODO: If we got benchmarking that includes that encapsulates the proof size, - // we should be able to use the maximum pov size. - Some((validation_data.max_pov_size / 2) as usize), - ) - .await - .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Proposing failed.")) - .ok()?; - - let (header, extrinsics) = block.clone().deconstruct(); - - let sig_digest = seal_header::(&header, &*self.keystore, &type_public_pair); - - let mut block_import_params = BlockImportParams::new(BlockOrigin::Own, header.clone()); - block_import_params.post_digests.push(sig_digest.clone()); - block_import_params.body = Some(extrinsics.clone()); - block_import_params.state_action = sc_consensus::StateAction::ApplyChanges( - sc_consensus::StorageChanges::Changes(storage_changes), - ); - - // Print the same log line as slots (aura and babe) - info!( - "🔖 Sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - *header.number(), - block_import_params.post_hash(), - header.hash(), - ); - - if let Err(err) = self - .block_import - .lock() - .await - .import_block(block_import_params, Default::default()) - .await - { - error!( - target: LOG_TARGET, - at = ?parent.hash(), - error = ?err, - "Error importing built block.", - ); - - return None; - } - - // Compute info about the block after the digest is added - let mut post_header = header.clone(); - post_header.digest_mut().logs.push(sig_digest.clone()); - let post_block = B::new(post_header, extrinsics); - - // Returning the block WITH the seal for distribution around the network. - Some(ParachainCandidate { - block: post_block, - proof, - }) - } + async fn produce_candidate( + &mut self, + parent: &B::Header, + relay_parent: PHash, + validation_data: &PersistedValidationData, + ) -> Option> { + // Determine if runtime change + let runtime_upgraded = if *parent.number() > sp_runtime::traits::Zero::zero() { + let at = BlockId::Hash(parent.hash()); + let parent_at = BlockId::::Hash(*parent.parent_hash()); + use sp_api::Core as _; + let previous_runtime_version: sp_api::RuntimeVersion = self + .parachain_client + .runtime_api() + .version(&parent_at) + .expect("Runtime api access to not error."); + let runtime_version: sp_api::RuntimeVersion = self + .parachain_client + .runtime_api() + .version(&at) + .expect("Runtime api access to not error."); + + previous_runtime_version != runtime_version + } else { + false + }; + + let maybe_key = if self.skip_prediction || runtime_upgraded { + first_available_key(&*self.keystore) + } else { + first_eligible_key::( + self.parachain_client.clone(), + &*self.keystore, + parent, + validation_data.relay_parent_number, + ) + }; + + // If there are no eligible keys, print the log, and exit early. + let type_public_pair = match maybe_key { + Some(p) => p, + None => { + return None; + } + }; + + let proposer_future = self.proposer_factory.lock().init(parent); + + let proposer = proposer_future + .await + .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Could not create proposer.")) + .ok()?; + + let nimbus_id = NimbusId::from_slice(&type_public_pair.1) + .map_err( + |e| error!(target: LOG_TARGET, error = ?e, "Invalid Nimbus ID (wrong length)."), + ) + .ok()?; + + let inherent_data = self + .inherent_data(parent.hash(), validation_data, relay_parent, nimbus_id.clone()) + .await?; + + let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; + logs.extend(self.additional_digests_provider.provide_digests(nimbus_id, parent.hash())); + let inherent_digests = sp_runtime::generic::Digest { logs }; + + let Proposal { block, storage_changes, proof } = proposer + .propose( + inherent_data, + inherent_digests, + //TODO: Fix this. + Duration::from_millis(500), + // Set the block limit to 50% of the maximum PoV size. + // + // TODO: If we got benchmarking that includes that encapsulates the proof size, + // we should be able to use the maximum pov size. + Some((validation_data.max_pov_size / 2) as usize), + ) + .await + .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Proposing failed.")) + .ok()?; + + let (header, extrinsics) = block.clone().deconstruct(); + + let sig_digest = seal_header::(&header, &*self.keystore, &type_public_pair); + + let mut block_import_params = BlockImportParams::new(BlockOrigin::Own, header.clone()); + block_import_params.post_digests.push(sig_digest.clone()); + block_import_params.body = Some(extrinsics.clone()); + block_import_params.state_action = sc_consensus::StateAction::ApplyChanges( + sc_consensus::StorageChanges::Changes(storage_changes), + ); + + // Print the same log line as slots (aura and babe) + info!( + "🔖 Sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + *header.number(), + block_import_params.post_hash(), + header.hash(), + ); + + if let Err(err) = self + .block_import + .lock() + .await + .import_block(block_import_params, Default::default()) + .await + { + error!( + target: LOG_TARGET, + at = ?parent.hash(), + error = ?err, + "Error importing built block.", + ); + + return None; + } + + // Compute info about the block after the digest is added + let mut post_header = header.clone(); + post_header.digest_mut().logs.push(sig_digest.clone()); + let post_block = B::new(post_header, extrinsics); + + // Returning the block WITH the seal for distribution around the network. + Some(ParachainCandidate { block: post_block, proof }) + } } /// Paramaters of [`build_relay_chain_consensus`]. @@ -432,12 +404,12 @@ where /// I briefly tried the async keystore approach, but decided to go sync so I can copy /// code from Aura. Maybe after it is working, Jeremy can help me go async. pub struct BuildNimbusConsensusParams { - pub para_id: ParaId, - pub proposer_factory: PF, - pub create_inherent_data_providers: CIDP, - pub block_import: BI, - pub parachain_client: Arc, - pub keystore: SyncCryptoStorePtr, - pub skip_prediction: bool, - pub additional_digests_provider: DP, + pub para_id: ParaId, + pub proposer_factory: PF, + pub create_inherent_data_providers: CIDP, + pub block_import: BI, + pub parachain_client: Arc, + pub keystore: SyncCryptoStorePtr, + pub skip_prediction: bool, + pub additional_digests_provider: DP, } diff --git a/external/nimbus-consensus/src/manual_seal.rs b/external/nimbus-consensus/src/manual_seal.rs index 27ca5856c..e104eac7f 100644 --- a/external/nimbus-consensus/src/manual_seal.rs +++ b/external/nimbus-consensus/src/manual_seal.rs @@ -15,10 +15,10 @@ // along with Nimbus. If not, see . use cumulus_primitives_parachain_inherent::{ - ParachainInherentData, INHERENT_IDENTIFIER as PARACHAIN_INHERENT_IDENTIFIER, + ParachainInherentData, INHERENT_IDENTIFIER as PARACHAIN_INHERENT_IDENTIFIER, }; use nimbus_primitives::{ - CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_ENGINE_ID, + CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_ENGINE_ID, }; use sc_consensus::BlockImportParams; use sc_consensus_manual_seal::{ConsensusDataProvider, Error}; @@ -31,101 +31,100 @@ use std::{marker::PhantomData, sync::Arc}; /// Provides nimbus-compatible pre-runtime digests for use with manual seal consensus pub struct NimbusManualSealConsensusDataProvider { - /// Shared reference to keystore - pub keystore: SyncCryptoStorePtr, + /// Shared reference to keystore + pub keystore: SyncCryptoStorePtr, - /// Shared reference to the client - pub client: Arc, - // Could have a skip_prediction field here if it becomes desireable - /// Additional digests provider - pub additional_digests_provider: DP, + /// Shared reference to the client + pub client: Arc, + // Could have a skip_prediction field here if it becomes desireable + /// Additional digests provider + pub additional_digests_provider: DP, - pub _phantom: PhantomData

, + pub _phantom: PhantomData

, } impl ConsensusDataProvider for NimbusManualSealConsensusDataProvider where - B: BlockT, - C: ProvideRuntimeApi + Send + Sync, - C::Api: NimbusApi, - DP: DigestsProvider::Hash> + Send + Sync, - P: Send + Sync, + B: BlockT, + C: ProvideRuntimeApi + Send + Sync, + C::Api: NimbusApi, + DP: DigestsProvider::Hash> + Send + Sync, + P: Send + Sync, { - type Transaction = TransactionFor; - type Proof = P; - - fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result { - // Retrieve the relay chain block number to use as the slot number from the parachain inherent - let slot_number = inherents - .get_data::(&PARACHAIN_INHERENT_IDENTIFIER) - .expect("Parachain inherent should decode correctly") - .expect("Parachain inherent should be present because we are mocking it") - .validation_data - .relay_parent_number; - - // Fetch first eligible key from keystore - let maybe_key = crate::first_eligible_key::( - self.client.clone(), - &*self.keystore, - parent, - // For now we author all blocks in slot zero, which is consistent with how we are - // mocking the relay chain height which the runtime uses for slot beacon. - // This should improve. See https://github.com/PureStake/nimbus/issues/3 - slot_number, - ); - - // If we aren't eligible, return an appropriate error - match maybe_key { - Some(key) => { - let nimbus_id = NimbusId::from_slice(&key.1).map_err(|_| { - Error::StringError(String::from("invalid nimbus id (wrong length)")) - })?; - let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; - logs.extend( - self.additional_digests_provider - .provide_digests(nimbus_id, parent.hash()), - ); - Ok(Digest { logs }) - } - None => Err(Error::StringError(String::from( - "no nimbus keys available to manual seal", - ))), - } - } - - // This is where we actually sign with the nimbus key and attach the seal - fn append_block_import( - &self, - _parent: &B::Header, - params: &mut BlockImportParams, - _inherents: &InherentData, - _proof: Self::Proof, - ) -> Result<(), Error> { - // We have to reconstruct the type-public pair which is only communicated through the pre-runtime digest - let claimed_author = params - .header - .digest() - .logs - .iter() - .find_map(|digest| { - match *digest { - // We do not support the older author inherent in manual seal - DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - _ => None, - } - }) - .expect("Expected one pre-runtime digest that contains author id bytes"); - - let nimbus_public = NimbusId::from_slice(&claimed_author) - .map_err(|_| Error::StringError(String::from("invalid nimbus id (wrong length)")))?; - - let sig_digest = - crate::seal_header::(¶ms.header, &*self.keystore, &nimbus_public.into()); - - params.post_digests.push(sig_digest); - - Ok(()) - } + type Transaction = TransactionFor; + type Proof = P; + + fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result { + // Retrieve the relay chain block number to use as the slot number from the parachain inherent + let slot_number = inherents + .get_data::(&PARACHAIN_INHERENT_IDENTIFIER) + .expect("Parachain inherent should decode correctly") + .expect("Parachain inherent should be present because we are mocking it") + .validation_data + .relay_parent_number; + + // Fetch first eligible key from keystore + let maybe_key = crate::first_eligible_key::( + self.client.clone(), + &*self.keystore, + parent, + // For now we author all blocks in slot zero, which is consistent with how we are + // mocking the relay chain height which the runtime uses for slot beacon. + // This should improve. See https://github.com/PureStake/nimbus/issues/3 + slot_number, + ); + + // If we aren't eligible, return an appropriate error + match maybe_key { + Some(key) => { + let nimbus_id = NimbusId::from_slice(&key.1).map_err(|_| { + Error::StringError(String::from("invalid nimbus id (wrong length)")) + })?; + let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; + logs.extend( + self.additional_digests_provider.provide_digests(nimbus_id, parent.hash()), + ); + Ok(Digest { logs }) + } + None => { + Err(Error::StringError(String::from("no nimbus keys available to manual seal"))) + } + } + } + + // This is where we actually sign with the nimbus key and attach the seal + fn append_block_import( + &self, + _parent: &B::Header, + params: &mut BlockImportParams, + _inherents: &InherentData, + _proof: Self::Proof, + ) -> Result<(), Error> { + // We have to reconstruct the type-public pair which is only communicated through the pre-runtime digest + let claimed_author = params + .header + .digest() + .logs + .iter() + .find_map(|digest| { + match *digest { + // We do not support the older author inherent in manual seal + DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + _ => None, + } + }) + .expect("Expected one pre-runtime digest that contains author id bytes"); + + let nimbus_public = NimbusId::from_slice(&claimed_author) + .map_err(|_| Error::StringError(String::from("invalid nimbus id (wrong length)")))?; + + let sig_digest = + crate::seal_header::(¶ms.header, &*self.keystore, &nimbus_public.into()); + + params.post_digests.push(sig_digest); + + Ok(()) + } } diff --git a/external/nimbus-primitives/Cargo.toml b/external/nimbus-primitives/Cargo.toml index 3ad573737..76f4d69f1 100644 --- a/external/nimbus-primitives/Cargo.toml +++ b/external/nimbus-primitives/Cargo.toml @@ -1,40 +1,40 @@ [package] -name = "nimbus-primitives" -authors = [ "PureStake" ] +authors = ["PureStake"] description = "Primitive types and traits used in the Nimbus consensus framework" edition = "2021" +name = "nimbus-primitives" version = "0.9.0" [dependencies] async-trait = { version = "0.1", optional = true } -parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false , branch = "polkadot-v0.9.32" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.32" } [features] -default = [ "std" ] +default = ["std"] std = [ - "async-trait", - "frame-support/std", - "frame-system/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-api/std", - "sp-application-crypto/std", - "sp-inherents/std", - "sp-runtime/std", - "sp-std/std", + "async-trait", + "frame-support/std", + "frame-system/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-api/std", + "sp-application-crypto/std", + "sp-inherents/std", + "sp-runtime/std", + "sp-std/std", ] -runtime-benchmarks = [ "frame-benchmarking", "sp-runtime/runtime-benchmarks" ] +runtime-benchmarks = ["frame-benchmarking", "sp-runtime/runtime-benchmarks"] -try-runtime = [ "frame-support/try-runtime" ] +try-runtime = ["frame-support/try-runtime"] diff --git a/external/nimbus-primitives/src/digests.rs b/external/nimbus-primitives/src/digests.rs index a6fb82789..7364f05a7 100644 --- a/external/nimbus-primitives/src/digests.rs +++ b/external/nimbus-primitives/src/digests.rs @@ -29,52 +29,52 @@ use sp_runtime::generic::DigestItem; /// A digest item which is usable with aura consensus. pub trait CompatibleDigestItem: Sized { - /// Construct a pre-runtime digest from the given AuthorId - fn nimbus_pre_digest(author: NimbusId) -> Self; + /// Construct a pre-runtime digest from the given AuthorId + fn nimbus_pre_digest(author: NimbusId) -> Self; - /// If this item is a nimbus pre-runtime digest, return the author - fn as_nimbus_pre_digest(&self) -> Option; + /// If this item is a nimbus pre-runtime digest, return the author + fn as_nimbus_pre_digest(&self) -> Option; - /// Construct a seal digest item from the given signature - fn nimbus_seal(signature: NimbusSignature) -> Self; + /// Construct a seal digest item from the given signature + fn nimbus_seal(signature: NimbusSignature) -> Self; - /// If this item is a nimbus seal, return the signature. - fn as_nimbus_seal(&self) -> Option; + /// If this item is a nimbus seal, return the signature. + fn as_nimbus_seal(&self) -> Option; - /// This will be deprecated in the future - /// Construct a consensus digest from the given AuthorId - fn nimbus_consensus_digest(author: NimbusId) -> Self; + /// This will be deprecated in the future + /// Construct a consensus digest from the given AuthorId + fn nimbus_consensus_digest(author: NimbusId) -> Self; - /// This will be deprecated in the future - /// If this item is a nimbus consensus digest, return the author - fn as_nimbus_consensus_digest(&self) -> Option; + /// This will be deprecated in the future + /// If this item is a nimbus consensus digest, return the author + fn as_nimbus_consensus_digest(&self) -> Option; } impl CompatibleDigestItem for DigestItem { - fn nimbus_pre_digest(author: NimbusId) -> Self { - DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode()) - } - - fn as_nimbus_pre_digest(&self) -> Option { - self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) - } - - fn nimbus_seal(signature: NimbusSignature) -> Self { - DigestItem::Seal(NIMBUS_ENGINE_ID, signature.encode()) - } - - fn as_nimbus_seal(&self) -> Option { - self.seal_try_to(&NIMBUS_ENGINE_ID) - } - - // Remove this once deprecated - fn nimbus_consensus_digest(author: NimbusId) -> Self { - DigestItem::Consensus(NIMBUS_ENGINE_ID, author.encode()) - } - - // Remove this once deprecated. I don't think it is used anyway. - // Notice that it calls the pre_runtime helper function. - fn as_nimbus_consensus_digest(&self) -> Option { - self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) - } + fn nimbus_pre_digest(author: NimbusId) -> Self { + DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode()) + } + + fn as_nimbus_pre_digest(&self) -> Option { + self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) + } + + fn nimbus_seal(signature: NimbusSignature) -> Self { + DigestItem::Seal(NIMBUS_ENGINE_ID, signature.encode()) + } + + fn as_nimbus_seal(&self) -> Option { + self.seal_try_to(&NIMBUS_ENGINE_ID) + } + + // Remove this once deprecated + fn nimbus_consensus_digest(author: NimbusId) -> Self { + DigestItem::Consensus(NIMBUS_ENGINE_ID, author.encode()) + } + + // Remove this once deprecated. I don't think it is used anyway. + // Notice that it calls the pre_runtime helper function. + fn as_nimbus_consensus_digest(&self) -> Option { + self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) + } } diff --git a/external/nimbus-primitives/src/inherents.rs b/external/nimbus-primitives/src/inherents.rs index 426b4d993..e5e5023f1 100644 --- a/external/nimbus-primitives/src/inherents.rs +++ b/external/nimbus-primitives/src/inherents.rs @@ -27,26 +27,26 @@ pub struct InherentDataProvider; #[cfg(feature = "std")] #[async_trait::async_trait] impl sp_inherents::InherentDataProvider for InherentDataProvider { - fn provide_inherent_data( - &self, - inherent_data: &mut InherentData, - ) -> Result<(), sp_inherents::Error> { - inherent_data.put_data(INHERENT_IDENTIFIER, &()) - } - - async fn try_handle_error( - &self, - identifier: &InherentIdentifier, - _error: &[u8], - ) -> Option> { - // Dont' process modules from other inherents - if *identifier != INHERENT_IDENTIFIER { - return None; - } - - // All errors with the author inehrent are fatal - Some(Err(sp_inherents::Error::Application(Box::from( - String::from("Error processing dummy nimbus inherent"), - )))) - } + fn provide_inherent_data( + &self, + inherent_data: &mut InherentData, + ) -> Result<(), sp_inherents::Error> { + inherent_data.put_data(INHERENT_IDENTIFIER, &()) + } + + async fn try_handle_error( + &self, + identifier: &InherentIdentifier, + _error: &[u8], + ) -> Option> { + // Dont' process modules from other inherents + if *identifier != INHERENT_IDENTIFIER { + return None; + } + + // All errors with the author inehrent are fatal + Some(Err(sp_inherents::Error::Application(Box::from(String::from( + "Error processing dummy nimbus inherent", + ))))) + } } diff --git a/external/nimbus-primitives/src/lib.rs b/external/nimbus-primitives/src/lib.rs index e543d04ef..365e3b606 100644 --- a/external/nimbus-primitives/src/lib.rs +++ b/external/nimbus-primitives/src/lib.rs @@ -22,11 +22,10 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_application_crypto::KeyTypeId; -use sp_runtime::generic::DigestItem; -use sp_runtime::traits::BlockNumberProvider; -use sp_runtime::ConsensusEngineId; +use sp_runtime::{generic::DigestItem, traits::BlockNumberProvider, ConsensusEngineId}; #[cfg(feature = "runtime-benchmarks")] use sp_std::vec; +#[cfg(feature = "runtime-benchmarks")] use sp_std::vec::Vec; pub mod digests; @@ -37,45 +36,45 @@ pub use digests::CompatibleDigestItem; pub use inherents::{InherentDataProvider, INHERENT_IDENTIFIER}; pub trait DigestsProvider { - type Digests: IntoIterator; - fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests; + type Digests: IntoIterator; + fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests; } impl DigestsProvider for () { - type Digests = [DigestItem; 0]; - fn provide_digests(&self, _id: Id, _parent: BlockHash) -> Self::Digests { - [] - } + type Digests = [DigestItem; 0]; + fn provide_digests(&self, _id: Id, _parent: BlockHash) -> Self::Digests { + [] + } } impl DigestsProvider for F where - F: Fn(Id, BlockHash) -> D, - D: IntoIterator, + F: Fn(Id, BlockHash) -> D, + D: IntoIterator, { - type Digests = D; + type Digests = D; - fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests { - (*self)(id, parent) - } + fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests { + (*self)(id, parent) + } } /// The given account ID is the author of the current block. pub trait EventHandler { - //TODO should we be tking ownership here? - fn note_author(author: Author); + //TODO should we be tking ownership here? + fn note_author(author: Author); } impl EventHandler for () { - fn note_author(_author: T) {} + fn note_author(_author: T) {} } /// A mechanism for determining the current slot. /// For now we use u32 as the slot type everywhere. Let's see how long we can get away with that. pub trait SlotBeacon { - fn slot() -> u32; - #[cfg(feature = "runtime-benchmarks")] - fn set_slot(_slot: u32) {} + fn slot() -> u32; + #[cfg(feature = "runtime-benchmarks")] + fn set_slot(_slot: u32) {} } /// Anything that can provide a block height can be used as a slot beacon. This could be @@ -83,13 +82,13 @@ pub trait SlotBeacon { /// 1. Use your own chain's height as the slot number /// 2. If you're a parachain, use the relay chain's height as the slot number. impl> SlotBeacon for T { - fn slot() -> u32 { - Self::current_block_number() - } - #[cfg(feature = "runtime-benchmarks")] - fn set_slot(slot: u32) { - Self::set_block_number(slot); - } + fn slot() -> u32 { + Self::current_block_number() + } + #[cfg(feature = "runtime-benchmarks")] + fn set_slot(slot: u32) { + Self::set_block_number(slot); + } } /// PLANNED: A SlotBeacon that starts a new slot based on the timestamp. Behaviorally, this is @@ -98,9 +97,9 @@ impl> SlotBeacon for T { pub struct IntervalBeacon; impl SlotBeacon for IntervalBeacon { - fn slot() -> u32 { - todo!() - } + fn slot() -> u32 { + todo!() + } } /// Trait to determine whether this author is eligible to author in this slot. @@ -113,27 +112,27 @@ impl SlotBeacon for IntervalBeacon { /// There may be another variant where the caller only supplies a slot and the /// implementation replies with a complete set of eligible authors. pub trait CanAuthor { - #[cfg(feature = "try-runtime")] - // With `try-runtime` the local author should always be able to author a block. - fn can_author(author: &AuthorId, slot: &u32) -> bool { - true - } - #[cfg(not(feature = "try-runtime"))] - fn can_author(author: &AuthorId, slot: &u32) -> bool; - #[cfg(feature = "runtime-benchmarks")] - fn get_authors(_slot: &u32) -> Vec { - vec![] - } - #[cfg(feature = "runtime-benchmarks")] - fn set_eligible_author(_slot: &u32) {} + #[cfg(feature = "try-runtime")] + // With `try-runtime` the local author should always be able to author a block. + fn can_author(_author: &AuthorId, _slot: &u32) -> bool { + true + } + #[cfg(not(feature = "try-runtime"))] + fn can_author(author: &AuthorId, slot: &u32) -> bool; + #[cfg(feature = "runtime-benchmarks")] + fn get_authors(_slot: &u32) -> Vec { + vec![] + } + #[cfg(feature = "runtime-benchmarks")] + fn set_eligible_author(_slot: &u32) {} } /// Default implementation where anyone can author. /// /// This is identical to Cumulus's RelayChainConsensus impl CanAuthor for () { - fn can_author(_: &T, _: &u32) -> bool { - true - } + fn can_author(_: &T, _: &u32) -> bool { + true + } } /// A Trait to lookup runtime AccountIds from AuthorIds (probably NimbusIds) @@ -142,14 +141,14 @@ impl CanAuthor for () { /// support the usecase where the author inherent is used for beneficiary info /// and contains an AccountId directly. pub trait AccountLookup { - fn lookup_account(author: &NimbusId) -> Option; + fn lookup_account(author: &NimbusId) -> Option; } // A dummy impl used in simple tests impl AccountLookup for () { - fn lookup_account(_: &NimbusId) -> Option { - None - } + fn lookup_account(_: &NimbusId) -> Option { + None + } } /// The ConsensusEngineId for nimbus consensus @@ -162,8 +161,8 @@ pub const NIMBUS_KEY_ID: KeyTypeId = KeyTypeId(*b"nmbs"); // The strongly-typed crypto wrappers to be used by Nimbus in the keystore mod nimbus_crypto { - use sp_application_crypto::{app_crypto, sr25519}; - app_crypto!(sr25519, crate::NIMBUS_KEY_ID); + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, crate::NIMBUS_KEY_ID); } /// A nimbus author identifier (A public key). @@ -173,13 +172,13 @@ pub type NimbusId = nimbus_crypto::Public; pub type NimbusSignature = nimbus_crypto::Signature; sp_application_crypto::with_pair! { - /// A nimbus keypair - pub type NimbusPair = nimbus_crypto::Pair; + /// A nimbus keypair + pub type NimbusPair = nimbus_crypto::Pair; } sp_api::decl_runtime_apis! { - /// The runtime api used to predict whether a Nimbus author will be eligible in the given slot - pub trait NimbusApi { - fn can_author(author: NimbusId, relay_parent: u32, parent_header: &Block::Header) -> bool; - } + /// The runtime api used to predict whether a Nimbus author will be eligible in the given slot + pub trait NimbusApi { + fn can_author(author: NimbusId, relay_parent: u32, parent_header: &Block::Header) -> bool; + } } diff --git a/external/pallets/author-inherent/Cargo.toml b/external/pallets/author-inherent/Cargo.toml index 6221db389..c35a6a2f8 100644 --- a/external/pallets/author-inherent/Cargo.toml +++ b/external/pallets/author-inherent/Cargo.toml @@ -1,53 +1,53 @@ [package] -name = "pallet-author-inherent" -authors = [ "PureStake" ] +authors = ["PureStake"] description = "This pallet is the core of the in-runtime portion of Nimbus." edition = "2021" license = "GPL-3.0-only" +name = "pallet-author-inherent" version = "0.9.0" [dependencies] -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } log = { version = "0.4.17", default-features = false } nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } # Benchmarks -frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false , branch = "polkadot-v0.9.32" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.32" } [dev-dependencies] -frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0" , branch = "polkadot-v0.9.32" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0", branch = "polkadot-v0.9.32" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } [features] -default = [ "std" ] +default = ["std"] std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-api/std", - "sp-application-crypto/std", - "sp-authorship/std", - "sp-inherents/std", - "sp-runtime/std", - "sp-std/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-api/std", + "sp-application-crypto/std", + "sp-authorship/std", + "sp-inherents/std", + "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "nimbus-primitives/runtime-benchmarks", + "frame-benchmarking", + "nimbus-primitives/runtime-benchmarks", ] -try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] +try-runtime = ["frame-support/try-runtime", "frame-system/try-runtime"] diff --git a/external/pallets/author-inherent/src/benchmarks.rs b/external/pallets/author-inherent/src/benchmarks.rs index 4235fca8f..7a988f901 100644 --- a/external/pallets/author-inherent/src/benchmarks.rs +++ b/external/pallets/author-inherent/src/benchmarks.rs @@ -19,12 +19,11 @@ use crate::{Call, Config, Pallet}; use frame_benchmarking::benchmarks; use frame_system::RawOrigin; -use nimbus_primitives::CanAuthor; -use nimbus_primitives::SlotBeacon; +use nimbus_primitives::{CanAuthor, SlotBeacon}; benchmarks! { - kick_off_authorship_validation { - // The slot inserted needs to be higher than that already in storage - T::SlotBeacon::set_slot(100); - Pallet::::set_eligible_author(&T::SlotBeacon::slot()); - }: _(RawOrigin::None) + kick_off_authorship_validation { + // The slot inserted needs to be higher than that already in storage + T::SlotBeacon::set_slot(100); + Pallet::::set_eligible_author(&T::SlotBeacon::slot()); + }: _(RawOrigin::None) } diff --git a/external/pallets/author-inherent/src/exec.rs b/external/pallets/author-inherent/src/exec.rs index bd4f3bb99..b9fb50d7b 100644 --- a/external/pallets/author-inherent/src/exec.rs +++ b/external/pallets/author-inherent/src/exec.rs @@ -40,60 +40,55 @@ pub struct BlockExecutor(sp_std::marker::PhantomData<(T, I)>); impl ExecuteBlock for BlockExecutor where - Block: BlockT, - I: ExecuteBlock, + Block: BlockT, + I: ExecuteBlock, { - fn execute_block(block: Block) { - let (mut header, extrinsics) = block.deconstruct(); - - debug!(target: "executive", "In hacked Executive. Initial digests are {:?}", header.digest()); - - // Set the seal aside for checking. - let seal = header - .digest_mut() - .pop() - .expect("Seal digest is present and is last item"); - - debug!(target: "executive", "In hacked Executive. digests after stripping {:?}", header.digest()); - debug!(target: "executive", "The seal we got {:?}", seal); - - let signature = seal - .as_nimbus_seal() - .unwrap_or_else(|| panic!("HeaderUnsealed")); - - debug!(target: "executive", "🪲 Header hash after popping digest {:?}", header.hash()); - - debug!(target: "executive", "🪲 Signature according to executive is {:?}", signature); - - // Grab the author information from the preruntime digest - //TODO use the trait - let claimed_author = header - .digest() - .logs - .iter() - .find_map(|digest| match *digest { - DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - _ => None, - }) - .expect("Expected pre-runtime digest that contains author id bytes"); - - debug!(target: "executive", "🪲 Claimed Author according to executive is {:?}", claimed_author); - - // Verify the signature - let valid_signature = NimbusId::from_slice(&claimed_author) - .expect("Expected claimed author to be a valid NimbusId.") - .verify(&header.hash(), &signature); - - debug!(target: "executive", "🪲 Valid signature? {:?}", valid_signature); - - if !valid_signature { - panic!("Block signature invalid"); - } - - // Now that we've verified the signature, hand execution off to the inner executor - // which is probably the normal frame executive. - I::execute_block(Block::new(header, extrinsics)); - } + fn execute_block(block: Block) { + let (mut header, extrinsics) = block.deconstruct(); + + debug!(target: "executive", "In hacked Executive. Initial digests are {:?}", header.digest()); + + // Set the seal aside for checking. + let seal = header.digest_mut().pop().expect("Seal digest is present and is last item"); + + debug!(target: "executive", "In hacked Executive. digests after stripping {:?}", header.digest()); + debug!(target: "executive", "The seal we got {:?}", seal); + + let signature = seal.as_nimbus_seal().unwrap_or_else(|| panic!("HeaderUnsealed")); + + debug!(target: "executive", "🪲 Header hash after popping digest {:?}", header.hash()); + + debug!(target: "executive", "🪲 Signature according to executive is {:?}", signature); + + // Grab the author information from the preruntime digest + //TODO use the trait + let claimed_author = header + .digest() + .logs + .iter() + .find_map(|digest| match *digest { + DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { + Some(author_id.clone()) + } + _ => None, + }) + .expect("Expected pre-runtime digest that contains author id bytes"); + + debug!(target: "executive", "🪲 Claimed Author according to executive is {:?}", claimed_author); + + // Verify the signature + let valid_signature = NimbusId::from_slice(&claimed_author) + .expect("Expected claimed author to be a valid NimbusId.") + .verify(&header.hash(), &signature); + + debug!(target: "executive", "🪲 Valid signature? {:?}", valid_signature); + + if !valid_signature { + panic!("Block signature invalid"); + } + + // Now that we've verified the signature, hand execution off to the inner executor + // which is probably the normal frame executive. + I::execute_block(Block::new(header, extrinsics)); + } } diff --git a/external/pallets/author-inherent/src/lib.rs b/external/pallets/author-inherent/src/lib.rs index 1d3004172..745387cb0 100644 --- a/external/pallets/author-inherent/src/lib.rs +++ b/external/pallets/author-inherent/src/lib.rs @@ -22,7 +22,7 @@ use frame_support::traits::{FindAuthor, Get}; use nimbus_primitives::{ - AccountLookup, CanAuthor, NimbusId, SlotBeacon, INHERENT_IDENTIFIER, NIMBUS_ENGINE_ID, + AccountLookup, CanAuthor, NimbusId, SlotBeacon, INHERENT_IDENTIFIER, NIMBUS_ENGINE_ID, }; use parity_scale_codec::{Decode, Encode}; use sp_inherents::{InherentIdentifier, IsFatalError}; @@ -45,203 +45,201 @@ mod tests; #[frame_support::pallet] pub mod pallet { - use super::*; - use crate::weights::WeightInfo; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - /// The Author Inherent pallet. The core of the nimbus consensus framework's runtime presence. - #[pallet::pallet] - pub struct Pallet(PhantomData); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// A type to convert between AuthorId and AccountId. This is useful when you want to associate - /// Block authoring behavior with an AccoutId for rewards or slashing. If you do not need to - /// hold an AccountID responsible for authoring use `()` which acts as an identity mapping. - type AccountLookup: AccountLookup; - - /// The final word on whether the reported author can author at this height. - /// This will be used when executing the inherent. This check is often stricter than the - /// Preliminary check, because it can use more data. - /// If the pallet that implements this trait depends on an inherent, that inherent **must** - /// be included before this one. - type CanAuthor: CanAuthor; - - /// Some way of determining the current slot for purposes of verifying the author's eligibility - type SlotBeacon: SlotBeacon; - - type WeightInfo: WeightInfo; - } - - impl sp_runtime::BoundToRuntimeAppPublic for Pallet { - type Public = NimbusId; - } - - #[pallet::error] - pub enum Error { - /// Author already set in block. - AuthorAlreadySet, - /// No AccountId was found to be associated with this author - NoAccountId, - /// The author in the inherent is not an eligible author. - CannotBeAuthor, - } - - /// Author of current block. - #[pallet::storage] - pub type Author = StorageValue<_, T::AccountId, OptionQuery>; - - /// The highest slot that has been seen in the history of this chain. - /// This is a strictly-increasing value. - #[pallet::storage] - pub type HighestSlotSeen = StorageValue<_, u32, ValueQuery>; - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(_: T::BlockNumber) -> Weight { - // Now extract the author from the digest - let digest = >::digest(); - let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - if let Some(author) = Self::find_author(pre_runtime_digests) { - // Store the author so we can confirm eligibility after the inherents have executed - >::put(&author); - } - - T::DbWeight::get().writes(1) - } - } - - #[pallet::call] - impl Pallet { - /// This inherent is a workaround to run code after the "real" inherents have executed, - /// but before transactions are executed. - // This should go into on_post_inherents when it is ready https://github.com/paritytech/substrate/pull/10128 - // TODO better weight. For now we just set a somewhat conservative fudge factor - #[pallet::weight((T::WeightInfo::kick_off_authorship_validation(), DispatchClass::Mandatory))] - pub fn kick_off_authorship_validation(origin: OriginFor) -> DispatchResultWithPostInfo { - ensure_none(origin)?; - - // First check that the slot number is valid (greater than the previous highest) - let slot = T::SlotBeacon::slot(); - assert!( - slot > HighestSlotSeen::::get(), - "Block invalid; Supplied slot number is not high enough" - ); - - // Now check that the author is valid in this slot - assert!( - T::CanAuthor::can_author(&Self::get(), &slot), - "Block invalid, supplied author is not eligible." - ); - - // Once that is validated, update the stored slot number - HighestSlotSeen::::put(slot); - - Ok(Pays::No.into()) - } - } - - #[pallet::inherent] - impl ProvideInherent for Pallet { - type Call = Call; - type Error = InherentError; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - fn is_inherent_required(_: &InherentData) -> Result, Self::Error> { - // Return Ok(Some(_)) unconditionally because this inherent is required in every block - // If it is not found, throw an AuthorInherentRequired error. - Ok(Some(InherentError::Other( - sp_runtime::RuntimeString::Borrowed( - "Inherent required to manually initiate author validation", - ), - ))) - } - - // Regardless of whether the client is still supplying the author id, - // we will create the new empty-payload inherent extrinsic. - fn create_inherent(_data: &InherentData) -> Option { - Some(Call::kick_off_authorship_validation {}) - } - - fn is_inherent(call: &Self::Call) -> bool { - matches!(call, Call::kick_off_authorship_validation { .. }) - } - } - - impl FindAuthor for Pallet { - fn find_author<'a, I>(digests: I) -> Option - where - I: 'a + IntoIterator, - { - for (id, mut data) in digests.into_iter() { - if id == NIMBUS_ENGINE_ID { - let author_id = NimbusId::decode(&mut data) - .expect("NimbusId encoded in preruntime digest must be valid"); - - let author_account = T::AccountLookup::lookup_account(&author_id) - .expect("No Account Mapped to this NimbusId"); - - return Some(author_account); - } - } - - None - } - } - - impl Get for Pallet { - fn get() -> T::AccountId { - Author::::get().expect("Block author not inserted into Author Inherent Pallet") - } - } - - /// To learn whether a given NimbusId can author, as opposed to an account id, you - /// can ask this pallet directly. It will do the mapping for you. - impl CanAuthor for Pallet { - fn can_author(author: &NimbusId, slot: &u32) -> bool { - let account = match T::AccountLookup::lookup_account(author) { - Some(account) => account, - // Authors whose account lookups fail will not be eligible - None => { - return false; - } - }; - - T::CanAuthor::can_author(&account, slot) - } - #[cfg(feature = "runtime-benchmarks")] - fn set_eligible_author(slot: &u32) { - let eligible_authors = T::CanAuthor::get_authors(slot); - if let Some(author) = eligible_authors.first() { - Author::::put(author) - } - } - } + use super::*; + use crate::weights::WeightInfo; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + /// The Author Inherent pallet. The core of the nimbus consensus framework's runtime presence. + #[pallet::pallet] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// A type to convert between AuthorId and AccountId. This is useful when you want to associate + /// Block authoring behavior with an AccoutId for rewards or slashing. If you do not need to + /// hold an AccountID responsible for authoring use `()` which acts as an identity mapping. + type AccountLookup: AccountLookup; + + /// The final word on whether the reported author can author at this height. + /// This will be used when executing the inherent. This check is often stricter than the + /// Preliminary check, because it can use more data. + /// If the pallet that implements this trait depends on an inherent, that inherent **must** + /// be included before this one. + type CanAuthor: CanAuthor; + + /// Some way of determining the current slot for purposes of verifying the author's eligibility + type SlotBeacon: SlotBeacon; + + type WeightInfo: WeightInfo; + } + + impl sp_runtime::BoundToRuntimeAppPublic for Pallet { + type Public = NimbusId; + } + + #[pallet::error] + pub enum Error { + /// Author already set in block. + AuthorAlreadySet, + /// No AccountId was found to be associated with this author + NoAccountId, + /// The author in the inherent is not an eligible author. + CannotBeAuthor, + } + + /// Author of current block. + #[pallet::storage] + pub type Author = StorageValue<_, T::AccountId, OptionQuery>; + + /// The highest slot that has been seen in the history of this chain. + /// This is a strictly-increasing value. + #[pallet::storage] + pub type HighestSlotSeen = StorageValue<_, u32, ValueQuery>; + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_: T::BlockNumber) -> Weight { + // Now extract the author from the digest + let digest = >::digest(); + let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + if let Some(author) = Self::find_author(pre_runtime_digests) { + // Store the author so we can confirm eligibility after the inherents have executed + >::put(&author); + } + + T::DbWeight::get().writes(1) + } + } + + #[pallet::call] + impl Pallet { + /// This inherent is a workaround to run code after the "real" inherents have executed, + /// but before transactions are executed. + // This should go into on_post_inherents when it is ready https://github.com/paritytech/substrate/pull/10128 + // TODO better weight. For now we just set a somewhat conservative fudge factor + #[pallet::weight((T::WeightInfo::kick_off_authorship_validation(), DispatchClass::Mandatory))] + pub fn kick_off_authorship_validation(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure_none(origin)?; + + // First check that the slot number is valid (greater than the previous highest) + let slot = T::SlotBeacon::slot(); + assert!( + slot > HighestSlotSeen::::get(), + "Block invalid; Supplied slot number is not high enough" + ); + + // Now check that the author is valid in this slot + assert!( + T::CanAuthor::can_author(&Self::get(), &slot), + "Block invalid, supplied author is not eligible." + ); + + // Once that is validated, update the stored slot number + HighestSlotSeen::::put(slot); + + Ok(Pays::No.into()) + } + } + + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + type Error = InherentError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn is_inherent_required(_: &InherentData) -> Result, Self::Error> { + // Return Ok(Some(_)) unconditionally because this inherent is required in every block + // If it is not found, throw an AuthorInherentRequired error. + Ok(Some(InherentError::Other(sp_runtime::RuntimeString::Borrowed( + "Inherent required to manually initiate author validation", + )))) + } + + // Regardless of whether the client is still supplying the author id, + // we will create the new empty-payload inherent extrinsic. + fn create_inherent(_data: &InherentData) -> Option { + Some(Call::kick_off_authorship_validation {}) + } + + fn is_inherent(call: &Self::Call) -> bool { + matches!(call, Call::kick_off_authorship_validation { .. }) + } + } + + impl FindAuthor for Pallet { + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + for (id, mut data) in digests.into_iter() { + if id == NIMBUS_ENGINE_ID { + let author_id = NimbusId::decode(&mut data) + .expect("NimbusId encoded in preruntime digest must be valid"); + + let author_account = T::AccountLookup::lookup_account(&author_id) + .expect("No Account Mapped to this NimbusId"); + + return Some(author_account); + } + } + + None + } + } + + impl Get for Pallet { + fn get() -> T::AccountId { + Author::::get().expect("Block author not inserted into Author Inherent Pallet") + } + } + + /// To learn whether a given NimbusId can author, as opposed to an account id, you + /// can ask this pallet directly. It will do the mapping for you. + impl CanAuthor for Pallet { + fn can_author(author: &NimbusId, slot: &u32) -> bool { + let account = match T::AccountLookup::lookup_account(author) { + Some(account) => account, + // Authors whose account lookups fail will not be eligible + None => { + return false; + } + }; + + T::CanAuthor::can_author(&account, slot) + } + #[cfg(feature = "runtime-benchmarks")] + fn set_eligible_author(slot: &u32) { + let eligible_authors = T::CanAuthor::get_authors(slot); + if let Some(author) = eligible_authors.first() { + Author::::put(author) + } + } + } } #[derive(Encode)] #[cfg_attr(feature = "std", derive(Debug, Decode))] pub enum InherentError { - Other(RuntimeString), + Other(RuntimeString), } impl IsFatalError for InherentError { - fn is_fatal_error(&self) -> bool { - match *self { - InherentError::Other(_) => true, - } - } + fn is_fatal_error(&self) -> bool { + match *self { + InherentError::Other(_) => true, + } + } } impl InherentError { - /// Try to create an instance ouf of the given identifier and data. - #[cfg(feature = "std")] - pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { - if id == &INHERENT_IDENTIFIER { - ::decode(&mut &data[..]).ok() - } else { - None - } - } + /// Try to create an instance ouf of the given identifier and data. + #[cfg(feature = "std")] + pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { + if id == &INHERENT_IDENTIFIER { + ::decode(&mut &data[..]).ok() + } else { + None + } + } } diff --git a/external/pallets/author-inherent/src/mock.rs b/external/pallets/author-inherent/src/mock.rs index df37a07af..adf8af605 100644 --- a/external/pallets/author-inherent/src/mock.rs +++ b/external/pallets/author-inherent/src/mock.rs @@ -15,99 +15,90 @@ // along with Nimbus. If not, see . use crate::{self as pallet_testing, AccountLookup, NimbusId}; -use frame_support::parameter_types; -use frame_support::traits::ConstU32; -use frame_support::weights::RuntimeDbWeight; -use frame_system; +use frame_support::{parameter_types, traits::ConstU32, weights::RuntimeDbWeight}; +// use frame_system; use sp_core::H256; use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, }; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - AuthorInherent: pallet_testing::{Pallet, Call, Storage}, - } + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + AuthorInherent: pallet_testing::{Pallet, Call, Storage}, + } ); parameter_types! { - pub const BlockHashCount: u64 = 250; - pub Authors: Vec = vec![1, 2, 3, 4, 5]; - pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 1, - write: 10, - }; + pub const BlockHashCount: u64 = 250; + pub Authors: Vec = vec![1, 2, 3, 4, 5]; + pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 1, + write: 10, + }; } impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = TestDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = TestDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; } pub struct DummyBeacon {} impl nimbus_primitives::SlotBeacon for DummyBeacon { - fn slot() -> u32 { - 0 - } + fn slot() -> u32 { + 0 + } } pub const ALICE: u64 = 1; pub const ALICE_NIMBUS: [u8; 32] = [1; 32]; pub struct MockAccountLookup; impl AccountLookup for MockAccountLookup { - fn lookup_account(nimbus_id: &NimbusId) -> Option { - let nimbus_id_bytes: &[u8] = nimbus_id.as_ref(); + fn lookup_account(nimbus_id: &NimbusId) -> Option { + let nimbus_id_bytes: &[u8] = nimbus_id.as_ref(); - if nimbus_id_bytes == &ALICE_NIMBUS { - Some(ALICE) - } else { - None - } - } + if *nimbus_id_bytes == ALICE_NIMBUS { Some(ALICE) } else { None } + } } impl pallet_testing::Config for Test { - type AccountLookup = MockAccountLookup; - type CanAuthor = (); - type SlotBeacon = DummyBeacon; - type WeightInfo = (); + type AccountLookup = MockAccountLookup; + type CanAuthor = (); + type SlotBeacon = DummyBeacon; + type WeightInfo = (); } /// Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::default() - .build_storage::() - .unwrap() - .into() + frame_system::GenesisConfig::default().build_storage::().unwrap().into() } diff --git a/external/pallets/author-inherent/src/tests.rs b/external/pallets/author-inherent/src/tests.rs index affa2e042..26b6e87e4 100644 --- a/external/pallets/author-inherent/src/tests.rs +++ b/external/pallets/author-inherent/src/tests.rs @@ -14,8 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Nimbus. If not, see . -use crate::mock::*; -use crate::pallet::Author; +use crate::{mock::*, pallet::Author}; use frame_support::traits::{OnFinalize, OnInitialize}; use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID}; use parity_scale_codec::Encode; @@ -24,49 +23,49 @@ use sp_runtime::{Digest, DigestItem}; #[test] fn kick_off_authorship_validation_is_mandatory() { - use frame_support::dispatch::{DispatchClass, GetDispatchInfo}; + use frame_support::dispatch::{DispatchClass, GetDispatchInfo}; - let info = crate::Call::::kick_off_authorship_validation {}.get_dispatch_info(); - assert_eq!(info.class, DispatchClass::Mandatory); + let info = crate::Call::::kick_off_authorship_validation {}.get_dispatch_info(); + assert_eq!(info.class, DispatchClass::Mandatory); } #[test] fn test_author_is_available_after_on_initialize() { - new_test_ext().execute_with(|| { - let block_number = 1; - System::initialize( - &block_number, - &H256::default(), - &Digest { - logs: vec![DigestItem::PreRuntime( - NIMBUS_ENGINE_ID, - NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), - )], - }, - ); + new_test_ext().execute_with(|| { + let block_number = 1; + System::initialize( + &block_number, + &H256::default(), + &Digest { + logs: vec![DigestItem::PreRuntime( + NIMBUS_ENGINE_ID, + NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), + )], + }, + ); - AuthorInherent::on_initialize(block_number); - assert_eq!(Some(ALICE), >::get()); - }); + AuthorInherent::on_initialize(block_number); + assert_eq!(Some(ALICE), >::get()); + }); } #[test] fn test_author_is_still_available_after_on_finalize() { - new_test_ext().execute_with(|| { - let block_number = 1; - System::initialize( - &block_number, - &H256::default(), - &Digest { - logs: vec![DigestItem::PreRuntime( - NIMBUS_ENGINE_ID, - NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), - )], - }, - ); + new_test_ext().execute_with(|| { + let block_number = 1; + System::initialize( + &block_number, + &H256::default(), + &Digest { + logs: vec![DigestItem::PreRuntime( + NIMBUS_ENGINE_ID, + NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), + )], + }, + ); - AuthorInherent::on_initialize(block_number); - AuthorInherent::on_finalize(block_number); - assert_eq!(Some(ALICE), >::get()); - }); + AuthorInherent::on_initialize(block_number); + AuthorInherent::on_finalize(block_number); + assert_eq!(Some(ALICE), >::get()); + }); } diff --git a/external/pallets/author-inherent/src/weights.rs b/external/pallets/author-inherent/src/weights.rs index 420fbdb8f..045ef4675 100644 --- a/external/pallets/author-inherent/src/weights.rs +++ b/external/pallets/author-inherent/src/weights.rs @@ -46,46 +46,46 @@ #![allow(unused_imports)] use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, + traits::Get, + weights::{constants::RocksDbWeight, Weight}, }; use sp_std::marker::PhantomData; /// Weight functions needed for pallet_author_inherent. pub trait WeightInfo { - #[rustfmt::skip] + #[rustfmt::skip] fn kick_off_authorship_validation() -> Weight; } /// Weights for pallet_author_inherent using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: ParachainSystem ValidationData (r:1 w:0) - // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) - // Storage: AuthorInherent Author (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:1 w:0) - // Storage: AuthorFilter EligibleCount (r:1 w:0) - // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) + // Storage: AuthorInherent Author (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:1 w:0) + // Storage: AuthorFilter EligibleCount (r:1 w:0) + // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) #[rustfmt::skip] - fn kick_off_authorship_validation() -> Weight { - Weight::from_ref_time(20_862_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + fn kick_off_authorship_validation() -> Weight { + Weight::from_ref_time(20_862_000_u64) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { - // Storage: ParachainSystem ValidationData (r:1 w:0) - // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) - // Storage: AuthorInherent Author (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:1 w:0) - // Storage: AuthorFilter EligibleCount (r:1 w:0) - // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) + // Storage: AuthorInherent Author (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:1 w:0) + // Storage: AuthorFilter EligibleCount (r:1 w:0) + // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) #[rustfmt::skip] - fn kick_off_authorship_validation() -> Weight { - Weight::from_ref_time(20_862_000 as u64) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) + fn kick_off_authorship_validation() -> Weight { + Weight::from_ref_time(20_862_000_u64) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/external/pallets/author-mapping/Cargo.toml b/external/pallets/author-mapping/Cargo.toml index 79fd56e11..9727abba7 100644 --- a/external/pallets/author-mapping/Cargo.toml +++ b/external/pallets/author-mapping/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "pallet-author-mapping" -authors = [ "PureStake" ] +authors = ["PureStake"] description = "Maps AuthorIds to AccountIds Useful for associating consensus authors with in-runtime accounts" edition = "2021" +name = "pallet-author-mapping" version = "2.0.5" [dependencies] @@ -13,8 +13,8 @@ serde = { version = "1.0.124", optional = true } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0", default-features = false, features = ["derive"] } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } @@ -29,22 +29,22 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot- sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } [features] -default = [ "std" ] -std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "serde", - "session-keys-primitives/std", - "sp-runtime/std", - "sp-std/std", -] +default = ["std"] runtime-benchmarks = [ - "frame-benchmarking", - "session-keys-primitives/runtime-benchmarks", + "frame-benchmarking", + "session-keys-primitives/runtime-benchmarks", +] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde", + "session-keys-primitives/std", + "sp-runtime/std", + "sp-std/std", ] -try-runtime = [ "frame-support/try-runtime" ] +try-runtime = ["frame-support/try-runtime"] diff --git a/external/pallets/author-mapping/src/benchmarks.rs b/external/pallets/author-mapping/src/benchmarks.rs index 21faae3a0..b38957a65 100644 --- a/external/pallets/author-mapping/src/benchmarks.rs +++ b/external/pallets/author-mapping/src/benchmarks.rs @@ -20,8 +20,8 @@ use crate::{keys_wrapper, BalanceOf, Call, Config, Pallet}; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; use frame_support::{ - assert_ok, - traits::{Currency, Get}, + assert_ok, + traits::{Currency, Get}, }; use frame_system::RawOrigin; use nimbus_primitives::NimbusId; @@ -29,132 +29,126 @@ use parity_scale_codec::Decode; /// Create a funded user. fn create_funded_user() -> T::AccountId { - let user = account("account id", 0u32, 0u32); - T::DepositCurrency::make_free_balance_be( - &user, - <::DepositAmount as Get>>::get(), - ); - T::DepositCurrency::issue(<::DepositAmount as Get>>::get()); - user + let user = account("account id", 0u32, 0u32); + T::DepositCurrency::make_free_balance_be( + &user, + <::DepositAmount as Get>>::get(), + ); + T::DepositCurrency::issue(<::DepositAmount as Get>>::get()); + user } /// Create a valid nimbus id from a simple u8 seed pub fn nimbus_id(seed: u8) -> NimbusId { - let id = [seed; 32]; - NimbusId::decode(&mut &id[..]).expect("valid input") + let id = [seed; 32]; + NimbusId::decode(&mut &id[..]).expect("valid input") } benchmarks! { - add_association { - let caller = create_funded_user::(); - let id = nimbus_id(1u8); - }: _(RawOrigin::Signed(caller.clone()), id.clone()) - verify { - assert_eq!(Pallet::::account_id_of(&id), Some(caller)); - } - - update_association { - let caller = create_funded_user::(); - let first_id = nimbus_id(1u8); - let second_id = nimbus_id(2u8); - assert_ok!(Pallet::::add_association( - RawOrigin::Signed(caller.clone()).into(), - first_id.clone()) - ); - }: _(RawOrigin::Signed(caller.clone()), first_id.clone(), second_id.clone()) - verify { - assert_eq!(Pallet::::account_id_of(&first_id), None); - assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); - } - - clear_association { - let caller = create_funded_user::(); - let first_id = nimbus_id(1u8); - assert_ok!(Pallet::::add_association( - RawOrigin::Signed(caller.clone()).into(), - first_id.clone()) - ); - }: _(RawOrigin::Signed(caller.clone()), first_id.clone()) - verify { - assert_eq!(Pallet::::account_id_of(&first_id), None); - } - - remove_keys { - let caller = create_funded_user::(); - let id = nimbus_id(1u8); - let keys: T::Keys = nimbus_id(3u8).into(); - assert_ok!(Pallet::::set_keys( - RawOrigin::Signed(caller.clone()).into(), - keys_wrapper::(id.clone(), keys.clone()), - ) - ); - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert_eq!(Pallet::::account_id_of(&id), None); - assert_eq!(Pallet::::nimbus_id_of(&caller), None); - } - - set_keys { - let caller = create_funded_user::(); - let first_id = nimbus_id(1u8); - let first_keys: T::Keys = nimbus_id(3u8).into(); - let second_id = nimbus_id(2u8); - let second_keys: T::Keys = nimbus_id(3u8).into(); - // we benchmark set_keys after already calling set_keys because - // key rotation is more common than initially setting them - assert_ok!(Pallet::::set_keys( - RawOrigin::Signed(caller.clone()).into(), - keys_wrapper::(first_id.clone(), - first_keys.clone()), - ) - ); - }: _(RawOrigin::Signed(caller.clone()), keys_wrapper::(second_id.clone(), second_keys.clone()) - ) verify { - assert_eq!(Pallet::::account_id_of(&first_id), None); - assert_eq!(Pallet::::keys_of(&first_id), None); - assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); - assert_eq!(Pallet::::keys_of(&second_id), Some(second_keys)); - } + add_association { + let caller = create_funded_user::(); + let id = nimbus_id(1u8); + }: _(RawOrigin::Signed(caller.clone()), id.clone()) + verify { + assert_eq!(Pallet::::account_id_of(&id), Some(caller)); + } + + update_association { + let caller = create_funded_user::(); + let first_id = nimbus_id(1u8); + let second_id = nimbus_id(2u8); + assert_ok!(Pallet::::add_association( + RawOrigin::Signed(caller.clone()).into(), + first_id.clone()) + ); + }: _(RawOrigin::Signed(caller.clone()), first_id.clone(), second_id.clone()) + verify { + assert_eq!(Pallet::::account_id_of(&first_id), None); + assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); + } + + clear_association { + let caller = create_funded_user::(); + let first_id = nimbus_id(1u8); + assert_ok!(Pallet::::add_association( + RawOrigin::Signed(caller.clone()).into(), + first_id.clone()) + ); + }: _(RawOrigin::Signed(caller.clone()), first_id.clone()) + verify { + assert_eq!(Pallet::::account_id_of(&first_id), None); + } + + remove_keys { + let caller = create_funded_user::(); + let id = nimbus_id(1u8); + let keys: T::Keys = nimbus_id(3u8).into(); + assert_ok!(Pallet::::set_keys( + RawOrigin::Signed(caller.clone()).into(), + keys_wrapper::(id.clone(), keys), + ) + ); + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert_eq!(Pallet::::account_id_of(&id), None); + assert_eq!(Pallet::::nimbus_id_of(&caller), None); + } + + set_keys { + let caller = create_funded_user::(); + let first_id = nimbus_id(1u8); + let first_keys: T::Keys = nimbus_id(3u8).into(); + let second_id = nimbus_id(2u8); + let second_keys: T::Keys = nimbus_id(3u8).into(); + // we benchmark set_keys after already calling set_keys because + // key rotation is more common than initially setting them + assert_ok!(Pallet::::set_keys( + RawOrigin::Signed(caller.clone()).into(), + keys_wrapper::(first_id.clone(), + first_keys), + ) + ); + }: _(RawOrigin::Signed(caller.clone()), keys_wrapper::(second_id.clone(), second_keys.clone()) + ) verify { + assert_eq!(Pallet::::account_id_of(&first_id), None); + assert_eq!(Pallet::::keys_of(&first_id), None); + assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); + assert_eq!(Pallet::::keys_of(&second_id), Some(second_keys)); + } } #[cfg(test)] mod tests { - use super::*; - use crate::mock::Runtime; - use frame_support::assert_ok; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - TestExternalities::new(t) - } - - #[test] - fn bench_add_association() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_add_association()); - }); - } - - #[test] - fn bench_update_association() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_update_association()); - }); - } - - #[test] - fn bench_clear_association() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_clear_association()); - }); - } + use super::*; + use crate::mock::Runtime; + use frame_support::assert_ok; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t) + } + + #[test] + fn bench_add_association() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_add_association()); + }); + } + + #[test] + fn bench_update_association() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_update_association()); + }); + } + + #[test] + fn bench_clear_association() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_clear_association()); + }); + } } -impl_benchmark_test_suite!( - Pallet, - crate::benchmarks::tests::new_test_ext(), - crate::mock::Runtime -); +impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Runtime); diff --git a/external/pallets/author-mapping/src/lib.rs b/external/pallets/author-mapping/src/lib.rs index 73fb20778..aa002ce3e 100644 --- a/external/pallets/author-mapping/src/lib.rs +++ b/external/pallets/author-mapping/src/lib.rs @@ -41,363 +41,326 @@ pub mod migrations; #[pallet] pub mod pallet { - use crate::WeightInfo; - use frame_support::pallet_prelude::*; - use frame_support::traits::{Currency, ReservableCurrency}; - use frame_system::pallet_prelude::*; - use nimbus_primitives::{AccountLookup, NimbusId}; - use session_keys_primitives::KeysLookup; - use sp_std::{mem::size_of, vec::Vec}; - - pub type BalanceOf = <::DepositCurrency as Currency< - ::AccountId, - >>::Balance; - - #[derive(Clone, Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] - #[scale_info(skip_type_params(T))] - pub struct RegistrationInfo { - pub(crate) account: T::AccountId, - pub(crate) deposit: BalanceOf, - pub(crate) keys: T::Keys, - } - - /// Wrapper to form the input to `set_keys` from NimbusId + keys - pub fn keys_wrapper(nimbus_id: NimbusId, keys: T::Keys) -> Vec { - let mut r = nimbus_id.encode(); - r.extend(&keys.encode()); - r - } - - /// Size of NimbusId + T::Keys to check size of `set_keys` input before trying to decode - pub fn keys_size() -> usize { - size_of::() as usize + size_of::() as usize - } - - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - /// Configuration trait of this pallet - #[pallet::config] - pub trait Config: frame_system::Config { - /// Overarching event type - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// Currency in which the security deposit will be taken. - type DepositCurrency: Currency + ReservableCurrency; - /// The amount that should be taken as a security deposit when registering a NimbusId. - type DepositAmount: Get<>::Balance>; - /// Additional keys - /// Convertible From to get default keys for each mapping (for the migration) - type Keys: Parameter + Member + MaybeSerializeDeserialize + From; - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - } - - /// An error that can occur while executing the mapping pallet's logic. - #[pallet::error] - pub enum Error { - /// The association can't be cleared because it is not found. - AssociationNotFound, - /// The association can't be cleared because it belongs to another account. - NotYourAssociation, - /// This account cannot set an author because it cannon afford the security deposit - CannotAffordSecurityDeposit, - /// The NimbusId in question is already associated and cannot be overwritten - AlreadyAssociated, - /// No existing NimbusId can be found for the account - OldAuthorIdNotFound, - /// Keys have wrong size - WrongKeySize, - /// Failed to decode NimbusId for `set_keys` - DecodeNimbusFailed, - /// Failed to decode T::Keys for `set_keys` - DecodeKeysFailed, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// A NimbusId has been registered and mapped to an AccountId. - KeysRegistered { - nimbus_id: NimbusId, - account_id: T::AccountId, - keys: T::Keys, - }, - /// An NimbusId has been de-registered, and its AccountId mapping removed. - KeysRemoved { - nimbus_id: NimbusId, - account_id: T::AccountId, - keys: T::Keys, - }, - /// An NimbusId has been registered, replacing a previous registration and its mapping. - KeysRotated { - new_nimbus_id: NimbusId, - account_id: T::AccountId, - new_keys: T::Keys, - }, - } - - #[pallet::call] - impl Pallet { - /// Register your NimbusId onchain so blocks you author are associated with your account. - /// - /// Users who have been (or will soon be) elected active collators in staking, - /// should submit this extrinsic to have their blocks accepted and earn rewards. - #[pallet::weight(::WeightInfo::add_association())] - pub fn add_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { - let account_id = ensure_signed(origin)?; - - Self::register_keys(nimbus_id.clone(), account_id, nimbus_id.into()) - } - - /// Change your Mapping. - /// - /// This is useful for normal key rotation or for when switching from one physical collator - /// machine to another. No new security deposit is required. - /// This sets keys to new_nimbus_id.into() by default. - #[pallet::weight(::WeightInfo::update_association())] - pub fn update_association( - origin: OriginFor, - old_nimbus_id: NimbusId, - new_nimbus_id: NimbusId, - ) -> DispatchResult { - let account_id = ensure_signed(origin)?; - - Self::rotate_keys( - old_nimbus_id, - new_nimbus_id.clone(), - account_id, - new_nimbus_id.into(), - ) - } - - /// Clear your Mapping. - /// - /// This is useful when you are no longer an author and would like to re-claim your security - /// deposit. - #[pallet::weight(::WeightInfo::clear_association())] - pub fn clear_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { - let account_id = ensure_signed(origin)?; - - Self::rm_keys(nimbus_id, account_id) - } - - /// Remove your Mapping. - /// - /// This is useful when you are no longer an author and would like to re-claim your security - /// deposit. - #[pallet::weight(::WeightInfo::remove_keys())] - pub fn remove_keys(origin: OriginFor) -> DispatchResult { - let account_id = ensure_signed(origin)?; - let nimbus_id = - Self::nimbus_id_of(&account_id).ok_or(Error::::OldAuthorIdNotFound)?; - - Self::rm_keys(nimbus_id, account_id) - } - - /// Set association and session keys at once. - /// - /// This is useful for key rotation to update Nimbus and VRF keys in one call. - /// No new security deposit is required. Will replace `update_association` which is kept - /// now for backwards compatibility reasons. - #[pallet::weight(::WeightInfo::set_keys())] - pub fn set_keys(origin: OriginFor, keys: Vec) -> DispatchResult { - let account_id = ensure_signed(origin)?; - ensure!(keys.len() == keys_size::(), Error::::WrongKeySize); - let encoded = &mut keys.as_slice(); - let new_nimbus_id = - NimbusId::decode(encoded).map_err(|_| Error::::DecodeNimbusFailed)?; - let keys = T::Keys::decode(encoded).map_err(|_| Error::::DecodeKeysFailed)?; - - if let Some(old_nimbus_id) = Self::nimbus_id_of(&account_id) { - Self::rotate_keys(old_nimbus_id, new_nimbus_id, account_id, keys) - } else { - Self::register_keys(new_nimbus_id, account_id, keys) - } - } - } - - impl Pallet { - fn rm_keys(nimbus_id: NimbusId, account_id: T::AccountId) -> DispatchResult { - let stored_info = MappingWithDeposit::::try_get(&nimbus_id) - .map_err(|_| Error::::AssociationNotFound)?; - - ensure!( - account_id == stored_info.account, - Error::::NotYourAssociation - ); - - MappingWithDeposit::::remove(&nimbus_id); - NimbusLookup::::remove(&account_id); - - T::DepositCurrency::unreserve(&account_id, stored_info.deposit); - - >::deposit_event(Event::KeysRemoved { - nimbus_id, - account_id, - keys: stored_info.keys, - }); - Ok(()) - } - fn register_keys( - nimbus_id: NimbusId, - account_id: T::AccountId, - keys: T::Keys, - ) -> DispatchResult { - ensure!( - MappingWithDeposit::::get(&nimbus_id).is_none(), - Error::::AlreadyAssociated - ); - Self::enact_registration(&nimbus_id, &account_id, keys.clone())?; - - >::deposit_event(Event::KeysRegistered { - nimbus_id, - account_id, - keys, - }); - Ok(()) - } - fn rotate_keys( - old_nimbus_id: NimbusId, - new_nimbus_id: NimbusId, - account_id: T::AccountId, - new_keys: T::Keys, - ) -> DispatchResult { - let stored_info = MappingWithDeposit::::try_get(&old_nimbus_id) - .map_err(|_| Error::::AssociationNotFound)?; - - ensure!( - account_id == stored_info.account, - Error::::NotYourAssociation - ); - if old_nimbus_id != new_nimbus_id { - // cannot overwrite a NimbusId if it is not yours - ensure!( - MappingWithDeposit::::get(&new_nimbus_id).is_none(), - Error::::AlreadyAssociated - ); - } - - MappingWithDeposit::::remove(&old_nimbus_id); - let new_stored_info = RegistrationInfo { - keys: new_keys.clone(), - ..stored_info - }; - MappingWithDeposit::::insert(&new_nimbus_id, &new_stored_info); - NimbusLookup::::insert(&account_id, &new_nimbus_id); - - >::deposit_event(Event::KeysRotated { - new_nimbus_id, - account_id, - new_keys, - }); - Ok(()) - } - pub fn enact_registration( - nimbus_id: &NimbusId, - account_id: &T::AccountId, - keys: T::Keys, - ) -> DispatchResult { - let deposit = T::DepositAmount::get(); - - T::DepositCurrency::reserve(account_id, deposit) - .map_err(|_| Error::::CannotAffordSecurityDeposit)?; - - let info = RegistrationInfo { - account: account_id.clone(), - deposit, - keys, - }; - - MappingWithDeposit::::insert(nimbus_id, info); - NimbusLookup::::insert(account_id, nimbus_id); - - Ok(()) - } - } - - #[pallet::storage] - #[pallet::getter(fn account_and_deposit_of)] - /// We maintain a mapping from the NimbusIds used in the consensus layer - /// to the AccountIds runtime. - pub type MappingWithDeposit = - StorageMap<_, Blake2_128Concat, NimbusId, RegistrationInfo, OptionQuery>; - - #[pallet::storage] - #[pallet::getter(fn nimbus_lookup)] - /// We maintain a reverse mapping from AccountIds to NimbusIDS - pub type NimbusLookup = - StorageMap<_, Blake2_128Concat, T::AccountId, NimbusId, OptionQuery>; - - #[pallet::genesis_config] - /// Genesis config for author mapping pallet - pub struct GenesisConfig { - /// The associations that should exist at chain genesis - pub mappings: Vec<(NimbusId, T::AccountId)>, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { mappings: vec![] } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - for (nimbus_id, account_id) in &self.mappings { - if let Err(e) = Pallet::::enact_registration( - &nimbus_id, - &account_id, - nimbus_id.clone().into(), - ) { - log::warn!("Error with genesis author mapping registration: {:?}", e); - } - } - } - } - - impl AccountLookup for Pallet { - fn lookup_account(author: &NimbusId) -> Option { - Self::account_id_of(author) - } - } - - impl KeysLookup for Pallet { - #[cfg(feature = "runtime-benchmarks")] - type Account = T::AccountId; - fn lookup_keys(author: &NimbusId) -> Option { - Self::keys_of(author) - } - /// Sets keys WITHOUT reserving deposit, for benchmarking purposes only - #[cfg(feature = "runtime-benchmarks")] - fn set_keys(id: NimbusId, account: T::AccountId, keys: T::Keys) { - use sp_runtime::traits::Zero; - MappingWithDeposit::::insert( - id, - RegistrationInfo { - account, - deposit: Zero::zero(), - keys, - }, - ); - } - } - - impl Pallet { - /// A helper function to lookup the account id associated with the given author id. This is - /// the primary lookup that this pallet is responsible for. - pub fn account_id_of(nimbus_id: &NimbusId) -> Option { - Self::account_and_deposit_of(nimbus_id).map(|info| info.account) - } - /// A helper function to lookup the keys associated with the given author id. - pub fn keys_of(nimbus_id: &NimbusId) -> Option { - Self::account_and_deposit_of(nimbus_id).map(|info| info.keys) - } - /// A helper function to lookup NimbusId associated with a given AccountId - pub fn nimbus_id_of(account_id: &T::AccountId) -> Option { - NimbusLookup::::get(account_id) - } - } + use crate::WeightInfo; + use frame_support::{ + pallet_prelude::*, + traits::{Currency, ReservableCurrency}, + }; + use frame_system::pallet_prelude::*; + use nimbus_primitives::{AccountLookup, NimbusId}; + use session_keys_primitives::KeysLookup; + use sp_std::{mem::size_of, vec::Vec}; + + pub type BalanceOf = <::DepositCurrency as Currency< + ::AccountId, + >>::Balance; + + #[derive(Clone, Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] + #[scale_info(skip_type_params(T))] + pub struct RegistrationInfo { + pub(crate) account: T::AccountId, + pub(crate) deposit: BalanceOf, + pub(crate) keys: T::Keys, + } + + /// Wrapper to form the input to `set_keys` from NimbusId + keys + pub fn keys_wrapper(nimbus_id: NimbusId, keys: T::Keys) -> Vec { + let mut r = nimbus_id.encode(); + r.extend(&keys.encode()); + r + } + + /// Size of NimbusId + T::Keys to check size of `set_keys` input before trying to decode + pub fn keys_size() -> usize { + size_of::() as usize + size_of::() as usize + } + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + /// Configuration trait of this pallet + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// Currency in which the security deposit will be taken. + type DepositCurrency: Currency + ReservableCurrency; + /// The amount that should be taken as a security deposit when registering a NimbusId. + type DepositAmount: Get<>::Balance>; + /// Additional keys + /// Convertible From to get default keys for each mapping (for the migration) + type Keys: Parameter + Member + MaybeSerializeDeserialize + From; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + /// An error that can occur while executing the mapping pallet's logic. + #[pallet::error] + pub enum Error { + /// The association can't be cleared because it is not found. + AssociationNotFound, + /// The association can't be cleared because it belongs to another account. + NotYourAssociation, + /// This account cannot set an author because it cannon afford the security deposit + CannotAffordSecurityDeposit, + /// The NimbusId in question is already associated and cannot be overwritten + AlreadyAssociated, + /// No existing NimbusId can be found for the account + OldAuthorIdNotFound, + /// Keys have wrong size + WrongKeySize, + /// Failed to decode NimbusId for `set_keys` + DecodeNimbusFailed, + /// Failed to decode T::Keys for `set_keys` + DecodeKeysFailed, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// A NimbusId has been registered and mapped to an AccountId. + KeysRegistered { nimbus_id: NimbusId, account_id: T::AccountId, keys: T::Keys }, + /// An NimbusId has been de-registered, and its AccountId mapping removed. + KeysRemoved { nimbus_id: NimbusId, account_id: T::AccountId, keys: T::Keys }, + /// An NimbusId has been registered, replacing a previous registration and its mapping. + KeysRotated { new_nimbus_id: NimbusId, account_id: T::AccountId, new_keys: T::Keys }, + } + + #[pallet::call] + impl Pallet { + /// Register your NimbusId onchain so blocks you author are associated with your account. + /// + /// Users who have been (or will soon be) elected active collators in staking, + /// should submit this extrinsic to have their blocks accepted and earn rewards. + #[pallet::weight(::WeightInfo::add_association())] + pub fn add_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { + let account_id = ensure_signed(origin)?; + + Self::register_keys(nimbus_id.clone(), account_id, nimbus_id.into()) + } + + /// Change your Mapping. + /// + /// This is useful for normal key rotation or for when switching from one physical collator + /// machine to another. No new security deposit is required. + /// This sets keys to new_nimbus_id.into() by default. + #[pallet::weight(::WeightInfo::update_association())] + pub fn update_association( + origin: OriginFor, + old_nimbus_id: NimbusId, + new_nimbus_id: NimbusId, + ) -> DispatchResult { + let account_id = ensure_signed(origin)?; + + Self::rotate_keys( + old_nimbus_id, + new_nimbus_id.clone(), + account_id, + new_nimbus_id.into(), + ) + } + + /// Clear your Mapping. + /// + /// This is useful when you are no longer an author and would like to re-claim your security + /// deposit. + #[pallet::weight(::WeightInfo::clear_association())] + pub fn clear_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { + let account_id = ensure_signed(origin)?; + + Self::rm_keys(nimbus_id, account_id) + } + + /// Remove your Mapping. + /// + /// This is useful when you are no longer an author and would like to re-claim your security + /// deposit. + #[pallet::weight(::WeightInfo::remove_keys())] + pub fn remove_keys(origin: OriginFor) -> DispatchResult { + let account_id = ensure_signed(origin)?; + let nimbus_id = + Self::nimbus_id_of(&account_id).ok_or(Error::::OldAuthorIdNotFound)?; + + Self::rm_keys(nimbus_id, account_id) + } + + /// Set association and session keys at once. + /// + /// This is useful for key rotation to update Nimbus and VRF keys in one call. + /// No new security deposit is required. Will replace `update_association` which is kept + /// now for backwards compatibility reasons. + #[pallet::weight(::WeightInfo::set_keys())] + pub fn set_keys(origin: OriginFor, keys: Vec) -> DispatchResult { + let account_id = ensure_signed(origin)?; + ensure!(keys.len() == keys_size::(), Error::::WrongKeySize); + let encoded = &mut keys.as_slice(); + let new_nimbus_id = + NimbusId::decode(encoded).map_err(|_| Error::::DecodeNimbusFailed)?; + let keys = T::Keys::decode(encoded).map_err(|_| Error::::DecodeKeysFailed)?; + + if let Some(old_nimbus_id) = Self::nimbus_id_of(&account_id) { + Self::rotate_keys(old_nimbus_id, new_nimbus_id, account_id, keys) + } else { + Self::register_keys(new_nimbus_id, account_id, keys) + } + } + } + + impl Pallet { + fn rm_keys(nimbus_id: NimbusId, account_id: T::AccountId) -> DispatchResult { + let stored_info = MappingWithDeposit::::try_get(&nimbus_id) + .map_err(|_| Error::::AssociationNotFound)?; + + ensure!(account_id == stored_info.account, Error::::NotYourAssociation); + + MappingWithDeposit::::remove(&nimbus_id); + NimbusLookup::::remove(&account_id); + + T::DepositCurrency::unreserve(&account_id, stored_info.deposit); + + >::deposit_event(Event::KeysRemoved { + nimbus_id, + account_id, + keys: stored_info.keys, + }); + Ok(()) + } + fn register_keys( + nimbus_id: NimbusId, + account_id: T::AccountId, + keys: T::Keys, + ) -> DispatchResult { + ensure!( + MappingWithDeposit::::get(&nimbus_id).is_none(), + Error::::AlreadyAssociated + ); + Self::enact_registration(&nimbus_id, &account_id, keys.clone())?; + + >::deposit_event(Event::KeysRegistered { nimbus_id, account_id, keys }); + Ok(()) + } + fn rotate_keys( + old_nimbus_id: NimbusId, + new_nimbus_id: NimbusId, + account_id: T::AccountId, + new_keys: T::Keys, + ) -> DispatchResult { + let stored_info = MappingWithDeposit::::try_get(&old_nimbus_id) + .map_err(|_| Error::::AssociationNotFound)?; + + ensure!(account_id == stored_info.account, Error::::NotYourAssociation); + if old_nimbus_id != new_nimbus_id { + // cannot overwrite a NimbusId if it is not yours + ensure!( + MappingWithDeposit::::get(&new_nimbus_id).is_none(), + Error::::AlreadyAssociated + ); + } + + MappingWithDeposit::::remove(&old_nimbus_id); + let new_stored_info = RegistrationInfo { keys: new_keys.clone(), ..stored_info }; + MappingWithDeposit::::insert(&new_nimbus_id, &new_stored_info); + NimbusLookup::::insert(&account_id, &new_nimbus_id); + + >::deposit_event(Event::KeysRotated { new_nimbus_id, account_id, new_keys }); + Ok(()) + } + pub fn enact_registration( + nimbus_id: &NimbusId, + account_id: &T::AccountId, + keys: T::Keys, + ) -> DispatchResult { + let deposit = T::DepositAmount::get(); + + T::DepositCurrency::reserve(account_id, deposit) + .map_err(|_| Error::::CannotAffordSecurityDeposit)?; + + let info = RegistrationInfo { account: account_id.clone(), deposit, keys }; + + MappingWithDeposit::::insert(nimbus_id, info); + NimbusLookup::::insert(account_id, nimbus_id); + + Ok(()) + } + } + + #[pallet::storage] + #[pallet::getter(fn account_and_deposit_of)] + /// We maintain a mapping from the NimbusIds used in the consensus layer + /// to the AccountIds runtime. + pub type MappingWithDeposit = + StorageMap<_, Blake2_128Concat, NimbusId, RegistrationInfo, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn nimbus_lookup)] + /// We maintain a reverse mapping from AccountIds to NimbusIDS + pub type NimbusLookup = + StorageMap<_, Blake2_128Concat, T::AccountId, NimbusId, OptionQuery>; + + #[pallet::genesis_config] + /// Genesis config for author mapping pallet + pub struct GenesisConfig { + /// The associations that should exist at chain genesis + pub mappings: Vec<(NimbusId, T::AccountId)>, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { mappings: vec![] } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + for (nimbus_id, account_id) in &self.mappings { + if let Err(e) = + Pallet::::enact_registration(nimbus_id, account_id, nimbus_id.clone().into()) + { + log::warn!("Error with genesis author mapping registration: {:?}", e); + } + } + } + } + + impl AccountLookup for Pallet { + fn lookup_account(author: &NimbusId) -> Option { + Self::account_id_of(author) + } + } + + impl KeysLookup for Pallet { + #[cfg(feature = "runtime-benchmarks")] + type Account = T::AccountId; + fn lookup_keys(author: &NimbusId) -> Option { + Self::keys_of(author) + } + /// Sets keys WITHOUT reserving deposit, for benchmarking purposes only + #[cfg(feature = "runtime-benchmarks")] + fn set_keys(id: NimbusId, account: T::AccountId, keys: T::Keys) { + use sp_runtime::traits::Zero; + MappingWithDeposit::::insert( + id, + RegistrationInfo { account, deposit: Zero::zero(), keys }, + ); + } + } + + impl Pallet { + /// A helper function to lookup the account id associated with the given author id. This is + /// the primary lookup that this pallet is responsible for. + pub fn account_id_of(nimbus_id: &NimbusId) -> Option { + Self::account_and_deposit_of(nimbus_id).map(|info| info.account) + } + /// A helper function to lookup the keys associated with the given author id. + pub fn keys_of(nimbus_id: &NimbusId) -> Option { + Self::account_and_deposit_of(nimbus_id).map(|info| info.keys) + } + /// A helper function to lookup NimbusId associated with a given AccountId + pub fn nimbus_id_of(account_id: &T::AccountId) -> Option { + NimbusLookup::::get(account_id) + } + } } diff --git a/external/pallets/author-mapping/src/migrations.rs b/external/pallets/author-mapping/src/migrations.rs index 1b373dbce..fe07aafe7 100644 --- a/external/pallets/author-mapping/src/migrations.rs +++ b/external/pallets/author-mapping/src/migrations.rs @@ -16,9 +16,9 @@ use crate::{BalanceOf, Config, Event, MappingWithDeposit, NimbusLookup, Pallet, RegistrationInfo}; use frame_support::{ - pallet_prelude::PhantomData, - traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, - weights::Weight, + pallet_prelude::PhantomData, + traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, + weights::Weight, }; use nimbus_primitives::NimbusId; use parity_scale_codec::{Decode, Encode}; @@ -30,68 +30,68 @@ use sp_std::vec::Vec; /// via NimbusId. pub struct AddAccountIdToNimbusLookup(PhantomData); impl OnRuntimeUpgrade for AddAccountIdToNimbusLookup { - fn on_runtime_upgrade() -> Weight { - log::info!(target: "AddAccountIdToNimbusLookup", "running migration"); - - let mut read_write_count = 0u64; - >::translate(|nimbus_id, registration_info: RegistrationInfo| { - read_write_count += 2u64; - if NimbusLookup::::get(®istration_info.account).is_none() { - >::insert(®istration_info.account, nimbus_id); - Some(registration_info) - } else { - // revoke the additional association and return the funds - T::DepositCurrency::unreserve( - ®istration_info.account, - registration_info.deposit, - ); - - >::deposit_event(Event::KeysRemoved { - nimbus_id, - account_id: registration_info.account, - keys: registration_info.keys, - }); - None - } - }); - // return weight - - T::DbWeight::get() - .reads(read_write_count) - .saturating_add(T::DbWeight::get().writes(read_write_count)) - } - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let mut nimbus_set: Vec = Vec::new(); - let mut state_map: BTreeMap = BTreeMap::new(); - for (nimbus_id, info) in >::iter() { - if !nimbus_set.contains(&nimbus_id) { - state_map.insert(nimbus_id.clone(), info.account); - nimbus_set.push(nimbus_id); - } - } - Ok(state_map.encode()) - } - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let state_map: BTreeMap = - Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - for (nimbus_id, _) in >::iter() { - let old_account = state_map.get(&nimbus_id).expect("qed"); - let maybe_account_of_nimbus = >::get(old_account); - assert_eq!( - Some(nimbus_id), - maybe_account_of_nimbus, - "New NimbusLookup dne expected NimbusID" - ); - } - Ok(()) - } + fn on_runtime_upgrade() -> Weight { + log::info!(target: "AddAccountIdToNimbusLookup", "running migration"); + + let mut read_write_count = 0u64; + >::translate(|nimbus_id, registration_info: RegistrationInfo| { + read_write_count += 2u64; + if NimbusLookup::::get(®istration_info.account).is_none() { + >::insert(®istration_info.account, nimbus_id); + Some(registration_info) + } else { + // revoke the additional association and return the funds + T::DepositCurrency::unreserve( + ®istration_info.account, + registration_info.deposit, + ); + + >::deposit_event(Event::KeysRemoved { + nimbus_id, + account_id: registration_info.account, + keys: registration_info.keys, + }); + None + } + }); + // return weight + + T::DbWeight::get() + .reads(read_write_count) + .saturating_add(T::DbWeight::get().writes(read_write_count)) + } + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let mut nimbus_set: Vec = Vec::new(); + let mut state_map: BTreeMap = BTreeMap::new(); + for (nimbus_id, info) in >::iter() { + if !nimbus_set.contains(&nimbus_id) { + state_map.insert(nimbus_id.clone(), info.account); + nimbus_set.push(nimbus_id); + } + } + Ok(state_map.encode()) + } + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let state_map: BTreeMap = + Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + for (nimbus_id, _) in >::iter() { + let old_account = state_map.get(&nimbus_id).expect("qed"); + let maybe_account_of_nimbus = >::get(old_account); + assert_eq!( + Some(nimbus_id), + maybe_account_of_nimbus, + "New NimbusLookup dne expected NimbusID" + ); + } + Ok(()) + } } /// Migrates MappingWithDeposit map value from RegistrationInfo to RegistrationInformation, @@ -100,84 +100,80 @@ impl OnRuntimeUpgrade for AddAccountIdToNimbusLookup { pub struct AddKeysToRegistrationInfo(PhantomData); #[derive(Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] struct OldRegistrationInfo { - account: AccountId, - deposit: Balance, + account: AccountId, + deposit: Balance, } fn migrate_registration_info( - nimbus_id: NimbusId, - old: OldRegistrationInfo>, + nimbus_id: NimbusId, + old: OldRegistrationInfo>, ) -> RegistrationInfo { - RegistrationInfo { - account: old.account, - deposit: old.deposit, - keys: nimbus_id.into(), - } + RegistrationInfo { account: old.account, deposit: old.deposit, keys: nimbus_id.into() } } impl OnRuntimeUpgrade for AddKeysToRegistrationInfo { - fn on_runtime_upgrade() -> Weight { - log::info!(target: "AddKeysToRegistrationInfo", "running migration"); - - let mut read_write_count = 0u64; - >::translate( - |nimbus_id, old_registration_info: OldRegistrationInfo>| { - read_write_count = read_write_count.saturating_add(1u64); - Some(migrate_registration_info(nimbus_id, old_registration_info)) - }, - ); - // return weight - T::DbWeight::get() - .reads(read_write_count) - .saturating_add(T::DbWeight::get().writes(read_write_count)) - } - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let mut state_map: BTreeMap)> = BTreeMap::new(); - - // get total deposited and account for all nimbus_keys - for (nimbus_id, info) in >::iter() { - state_map.insert(nimbus_id, (info.account, info.deposit)); - } - Ok(state_map.encode()) - } - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let state_map: BTreeMap)> = - Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - // ensure new deposit and account are the same as the old ones - // ensure new keys are equal to nimbus_id - for (nimbus_id, info) in >::iter() { - let (old_account, old_deposit) = state_map.get(&nimbus_id).expect("qed"); - - let new_account = info.account; - assert_eq!( - old_account.clone(), - new_account, - "Old Account {:?} dne New Account {:?} for NimbusID {:?}", - old_account.clone(), - new_account, - nimbus_id - ); - let new_deposit = info.deposit; - assert_eq!( - old_deposit.clone(), - new_deposit, - "Old Deposit {:?} dne New Deposit {:?} for NimbusID {:?}", - old_deposit.clone(), - new_deposit, - nimbus_id - ); - let nimbus_id_as_keys: T::Keys = nimbus_id.into(); - assert_eq!( - nimbus_id_as_keys, info.keys, - "Old NimbusID {:?} dne New Keys {:?}", - nimbus_id_as_keys, info.keys, - ); - } - Ok(()) - } + fn on_runtime_upgrade() -> Weight { + log::info!(target: "AddKeysToRegistrationInfo", "running migration"); + + let mut read_write_count = 0u64; + >::translate( + |nimbus_id, old_registration_info: OldRegistrationInfo>| { + read_write_count = read_write_count.saturating_add(1u64); + Some(migrate_registration_info(nimbus_id, old_registration_info)) + }, + ); + // return weight + T::DbWeight::get() + .reads(read_write_count) + .saturating_add(T::DbWeight::get().writes(read_write_count)) + } + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let mut state_map: BTreeMap)> = BTreeMap::new(); + + // get total deposited and account for all nimbus_keys + for (nimbus_id, info) in >::iter() { + state_map.insert(nimbus_id, (info.account, info.deposit)); + } + Ok(state_map.encode()) + } + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let state_map: BTreeMap)> = + Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + // ensure new deposit and account are the same as the old ones + // ensure new keys are equal to nimbus_id + for (nimbus_id, info) in >::iter() { + let (old_account, old_deposit) = state_map.get(&nimbus_id).expect("qed"); + + let new_account = info.account; + assert_eq!( + old_account.clone(), + new_account, + "Old Account {:?} dne New Account {:?} for NimbusID {:?}", + old_account.clone(), + new_account, + nimbus_id + ); + let new_deposit = info.deposit; + assert_eq!( + old_deposit.clone(), + new_deposit, + "Old Deposit {:?} dne New Deposit {:?} for NimbusID {:?}", + old_deposit.clone(), + new_deposit, + nimbus_id + ); + let nimbus_id_as_keys: T::Keys = nimbus_id.into(); + assert_eq!( + nimbus_id_as_keys, info.keys, + "Old NimbusID {:?} dne New Keys {:?}", + nimbus_id_as_keys, info.keys, + ); + } + Ok(()) + } } diff --git a/external/pallets/author-mapping/src/mock.rs b/external/pallets/author-mapping/src/mock.rs index 619567c2c..dded03085 100644 --- a/external/pallets/author-mapping/src/mock.rs +++ b/external/pallets/author-mapping/src/mock.rs @@ -17,9 +17,9 @@ //! A minimal runtime including the author-mapping pallet use crate as pallet_author_mapping; use frame_support::{ - construct_runtime, parameter_types, - traits::{Everything, GenesisBuild}, - weights::Weight, + construct_runtime, parameter_types, + traits::{Everything, GenesisBuild}, + weights::Weight, }; use nimbus_primitives::NimbusId; use parity_scale_codec::{Decode, Encode}; @@ -27,33 +27,43 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_core::{ByteArray, H256}; -use sp_io; +// use sp_io; use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - Perbill, RuntimeDebug, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, RuntimeDebug, }; #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum TestAuthor { - Alice, - Bob, - Charlie, + Alice, + Bob, + Charlie, } impl Default for TestAuthor { - fn default() -> TestAuthor { - TestAuthor::Alice - } + fn default() -> TestAuthor { + TestAuthor::Alice + } } -impl Into for TestAuthor { - fn into(self) -> NimbusId { - match self { - Self::Alice => NimbusId::from_slice(&[0u8; 32]), - Self::Bob => NimbusId::from_slice(&[1u8; 32]), - Self::Charlie => NimbusId::from_slice(&[2u8; 32]), - } - .expect("valid ids") - } +// impl Into for TestAuthor { +// fn into(self) -> NimbusId { +// match self { +// Self::Alice => NimbusId::from_slice(&[0u8; 32]), +// Self::Bob => NimbusId::from_slice(&[1u8; 32]), +// Self::Charlie => NimbusId::from_slice(&[2u8; 32]), +// } +// .expect("valid ids") +// } +// } +impl From for NimbusId { + fn from(test_author: TestAuthor) -> Self { + match test_author { + TestAuthor::Alice => NimbusId::from_slice(&[0u8; 32]), + TestAuthor::Bob => NimbusId::from_slice(&[1u8; 32]), + TestAuthor::Charlie => NimbusId::from_slice(&[2u8; 32]), + } + .expect("valid ids") + } } pub type AccountId = u64; @@ -65,127 +75,124 @@ type Block = frame_system::mocking::MockBlock; // Configure a mock runtime to test the pallet. construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - AuthorMapping: pallet_author_mapping::{Pallet, Call, Storage, Config, Event}, - } + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + AuthorMapping: pallet_author_mapping::{Pallet, Call, Storage, Config, Event}, + } ); parameter_types! { - pub const BlockHashCount: u32 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const BlockHashCount: u32 = 250; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Config for Runtime { - type BaseCallFilter = Everything; - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = sp_runtime::generic::Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type BaseCallFilter = Everything; + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { - pub const ExistentialDeposit: u128 = 1; + pub const ExistentialDeposit: u128 = 1; } impl pallet_balances::Config for Runtime { - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type MaxLocks = (); - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); } parameter_types! { - pub const DepositAmount: Balance = 100; + pub const DepositAmount: Balance = 100; } impl pallet_author_mapping::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type DepositCurrency = Balances; - type DepositAmount = DepositAmount; - type Keys = NimbusId; - type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type DepositCurrency = Balances; + type DepositAmount = DepositAmount; + type Keys = NimbusId; + type WeightInfo = (); } /// Externality builder for pallet author mapping's mock runtime /// Allows configuring balances and initial mappings +#[derive(Default)] pub(crate) struct ExtBuilder { - /// Accounts endowed with balances - balances: Vec<(AccountId, Balance)>, - /// AuthorId -> AccoutId mappings - mappings: Vec<(NimbusId, AccountId)>, + /// Accounts endowed with balances + balances: Vec<(AccountId, Balance)>, + /// AuthorId -> AccoutId mappings + mappings: Vec<(NimbusId, AccountId)>, } -impl Default for ExtBuilder { - fn default() -> ExtBuilder { - ExtBuilder { - balances: vec![], - mappings: vec![], - } - } -} +// impl Default for ExtBuilder { +// fn default() -> ExtBuilder { +// ExtBuilder { +// balances: vec![], +// mappings: vec![], +// } +// } +// } impl ExtBuilder { - pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { - self.balances = balances; - self - } - - pub(crate) fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { - self.mappings = mappings; - self - } - - pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: self.balances, - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - pallet_author_mapping::GenesisConfig:: { - mappings: self.mappings, - } - .assimilate_storage(&mut t) - .expect("Pallet author mapping's storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub(crate) fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { + self.mappings = mappings; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { balances: self.balances } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + pallet_author_mapping::GenesisConfig:: { mappings: self.mappings } + .assimilate_storage(&mut t) + .expect("Pallet author mapping's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } } pub(crate) fn last_event() -> RuntimeEvent { - System::events().pop().expect("Event expected").event + System::events().pop().expect("Event expected").event } diff --git a/external/pallets/author-mapping/src/tests.rs b/external/pallets/author-mapping/src/tests.rs index 40fd4d01a..6bde4bf35 100644 --- a/external/pallets/author-mapping/src/tests.rs +++ b/external/pallets/author-mapping/src/tests.rs @@ -15,466 +15,418 @@ // along with Moonbeam. If not, see . //! Unit testing -use crate::mock::{ - last_event, AuthorMapping, Balances, DepositAmount, ExtBuilder, Runtime, - RuntimeEvent as MetaEvent, RuntimeOrigin, System, TestAuthor, +use crate::{ + keys_size, keys_wrapper, + mock::{ + last_event, AuthorMapping, Balances, DepositAmount, ExtBuilder, Runtime, + RuntimeEvent as MetaEvent, RuntimeOrigin, System, TestAuthor, + }, + Error, Event, MappingWithDeposit, RegistrationInfo, }; -use crate::{keys_size, keys_wrapper, Error, Event, MappingWithDeposit, RegistrationInfo}; use frame_support::{ - assert_noop, assert_ok, - traits::{OnRuntimeUpgrade, ReservableCurrency}, + assert_noop, assert_ok, + traits::{OnRuntimeUpgrade, ReservableCurrency}, }; use nimbus_primitives::NimbusId; #[test] fn check_key_size() { - // NimbusId (32) + NimbusId (32) - assert_eq!(keys_size::(), 64usize); + // NimbusId (32) + NimbusId (32) + assert_eq!(keys_size::(), 64usize); } #[test] fn genesis_builder_works() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - assert_eq!(Balances::free_balance(&1), 900); - assert_eq!(Balances::reserved_balance(&1), 100); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Alice.into()), - Some(1) - ); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + assert_eq!(Balances::free_balance(&1), 900); + assert_eq!(Balances::reserved_balance(&1), 100); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), Some(1)); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); + }) } #[test] fn eligible_account_can_register() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::add_association( - RuntimeOrigin::signed(2), - TestAuthor::Bob.into() - )); - - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Bob.into()), - Some(2) - ); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Bob.into(), - account_id: 2, - keys: TestAuthor::Bob.into(), - }) - ); - }) + ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { + assert_ok!(AuthorMapping::add_association( + RuntimeOrigin::signed(2), + TestAuthor::Bob.into() + )); + + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Bob.into(), + account_id: 2, + keys: TestAuthor::Bob.into(), + }) + ); + }) } #[test] fn cannot_add_association_without_deposit() { - ExtBuilder::default() - .with_balances(vec![(2, 10)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), - Error::::CannotAffordSecurityDeposit - ); - - assert_eq!(Balances::free_balance(&2), 10); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Alice.into()), - None - ); - }) + ExtBuilder::default().with_balances(vec![(2, 10)]).build().execute_with(|| { + assert_noop!( + AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), + Error::::CannotAffordSecurityDeposit + ); + + assert_eq!(Balances::free_balance(&2), 10); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), None); + }) } #[test] fn double_registration_costs_twice_as_much() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .build() - .execute_with(|| { - // Register once as Bob - assert_ok!(AuthorMapping::add_association( - RuntimeOrigin::signed(2), - TestAuthor::Bob.into() - )); - - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Bob.into()), - Some(2) - ); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Bob.into(), - account_id: 2, - keys: TestAuthor::Bob.into(), - }) - ); - - // Register again as Alice - assert_ok!(AuthorMapping::add_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into() - )); - - assert_eq!(Balances::free_balance(&2), 800); - assert_eq!(Balances::reserved_balance(&2), 200); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Alice.into()), - Some(2) - ); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Alice.into(), - account_id: 2, - keys: TestAuthor::Alice.into(), - }) - ); - - // Should still be registered as Bob as well - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Bob.into()), - Some(2) - ); - }) + ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { + // Register once as Bob + assert_ok!(AuthorMapping::add_association( + RuntimeOrigin::signed(2), + TestAuthor::Bob.into() + )); + + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Bob.into(), + account_id: 2, + keys: TestAuthor::Bob.into(), + }) + ); + + // Register again as Alice + assert_ok!(AuthorMapping::add_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into() + )); + + assert_eq!(Balances::free_balance(&2), 800); + assert_eq!(Balances::reserved_balance(&2), 200); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), Some(2)); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Alice.into(), + account_id: 2, + keys: TestAuthor::Alice.into(), + }) + ); + + // Should still be registered as Bob as well + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); + }) } #[test] fn registered_account_can_clear() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::remove_keys(RuntimeOrigin::signed(1))); - - assert_eq!(Balances::free_balance(&1), 1000); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Alice.into()), - None - ); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRemoved { - nimbus_id: TestAuthor::Alice.into(), - account_id: 1, - keys: TestAuthor::Alice.into(), - }) - ); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::remove_keys(RuntimeOrigin::signed(1))); + + assert_eq!(Balances::free_balance(&1), 1000); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), None); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRemoved { + nimbus_id: TestAuthor::Alice.into(), + account_id: 1, + keys: TestAuthor::Alice.into(), + }) + ); + }) } #[test] fn unregistered_author_cannot_be_cleared() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - AuthorMapping::remove_keys(RuntimeOrigin::signed(1)), - Error::::OldAuthorIdNotFound - ); - }) + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + AuthorMapping::remove_keys(RuntimeOrigin::signed(1)), + Error::::OldAuthorIdNotFound + ); + }) } #[test] fn registered_author_cannot_be_cleared_by_non_owner() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::clear_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into() - ), - Error::::NotYourAssociation - ); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::clear_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into() + ), + Error::::NotYourAssociation + ); + }) } #[test] fn registered_author_cannot_be_overwritten() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), - Error::::AlreadyAssociated - ); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), + Error::::AlreadyAssociated + ); + }) } #[test] fn registered_can_rotate() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::update_association( - RuntimeOrigin::signed(2), - TestAuthor::Bob.into(), - TestAuthor::Charlie.into() - )); - - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), - Some(2) - ); - - // Should still only have paid a single security deposit - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - }) + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::update_association( + RuntimeOrigin::signed(2), + TestAuthor::Bob.into(), + TestAuthor::Charlie.into() + )); + + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), Some(2)); + + // Should still only have paid a single security deposit + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + }) } #[test] fn unregistered_author_cannot_be_rotated() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - AuthorMapping::update_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into(), - TestAuthor::Bob.into() - ), - Error::::AssociationNotFound - ); - }) + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + AuthorMapping::update_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into(), + TestAuthor::Bob.into() + ), + Error::::AssociationNotFound + ); + }) } #[test] fn registered_author_cannot_be_rotated_by_non_owner() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::update_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into(), - TestAuthor::Bob.into() - ), - Error::::NotYourAssociation - ); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::update_association( + RuntimeOrigin::signed(2), + TestAuthor::Alice.into(), + TestAuthor::Bob.into() + ), + Error::::NotYourAssociation + ); + }) } #[test] fn rotating_to_the_same_nimbus_id_leaves_registration_in_tact() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::update_association( - RuntimeOrigin::signed(1), - TestAuthor::Alice.into(), - TestAuthor::Alice.into() - )); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::update_association( + RuntimeOrigin::signed(1), + TestAuthor::Alice.into(), + TestAuthor::Alice.into() + )); + }) } #[test] fn eligible_account_can_full_register() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Alice.into()), - )); - - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Bob.into()), - Some(2) - ); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Bob.into(), - account_id: 2, - keys: TestAuthor::Alice.into(), - }) - ); - }) + ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Alice.into()), + )); + + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); + + assert_eq!( + last_event(), + MetaEvent::AuthorMapping(Event::KeysRegistered { + nimbus_id: TestAuthor::Bob.into(), + account_id: 2, + keys: TestAuthor::Alice.into(), + }) + ); + }) } #[test] fn cannot_set_keys_without_deposit() { - ExtBuilder::default() - .with_balances(vec![(2, 10)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), - ), - Error::::CannotAffordSecurityDeposit - ); - - assert_eq!(Balances::free_balance(&2), 10); - assert_eq!(AuthorMapping::keys_of(&TestAuthor::Alice.into()), None); - }) + ExtBuilder::default().with_balances(vec![(2, 10)]).build().execute_with(|| { + assert_noop!( + AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), + ), + Error::::CannotAffordSecurityDeposit + ); + + assert_eq!(Balances::free_balance(&2), 10); + assert_eq!(AuthorMapping::keys_of(&TestAuthor::Alice.into()), None); + }) } #[test] fn full_registered_author_cannot_be_overwritten() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), - ), - Error::::AlreadyAssociated - ); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), + ), + Error::::AlreadyAssociated + ); + }) } #[test] fn registered_can_full_rotate() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Charlie.into(), TestAuthor::Charlie.into()) - )); - - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); - assert_eq!( - AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), - Some(2) - ); - assert_eq!( - AuthorMapping::keys_of(&TestAuthor::Charlie.into()), - Some(TestAuthor::Charlie.into()) - ); - - // Should still only have paid a single security deposit - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - }) + ExtBuilder::default() + .with_balances(vec![(2, 1000)]) + .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Charlie.into(), TestAuthor::Charlie.into()) + )); + + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); + assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), Some(2)); + assert_eq!( + AuthorMapping::keys_of(&TestAuthor::Charlie.into()), + Some(TestAuthor::Charlie.into()) + ); + + // Should still only have paid a single security deposit + assert_eq!(Balances::free_balance(&2), 900); + assert_eq!(Balances::reserved_balance(&2), 100); + }) } #[test] fn unregistered_author_can_be_full_rotated() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Bob.into()), - )); - }) + ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Bob.into()), + )); + }) } #[test] fn registered_author_cannot_be_full_rotated_by_non_owner() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()) - ), - Error::::AlreadyAssociated - ); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_noop!( + AuthorMapping::set_keys( + RuntimeOrigin::signed(2), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()) + ), + Error::::AlreadyAssociated + ); + }) } #[test] fn full_rotating_to_the_same_nimbus_id_leaves_registration_in_tact() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(1), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Alice.into()) - )); - }) + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) + .build() + .execute_with(|| { + assert_ok!(AuthorMapping::set_keys( + RuntimeOrigin::signed(1), + keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Alice.into()) + )); + }) } #[test] fn add_reverse_mapping_migration_works() { - ExtBuilder::default() - .with_balances(vec![(1, 300)]) - .build() - .execute_with(|| { - // register 3 NimbusId owned by 1 account - let alice_as_nimbus: NimbusId = TestAuthor::Alice.into(); - let bob_as_nimbus: NimbusId = TestAuthor::Bob.into(); - let charlie_as_nimbus: NimbusId = TestAuthor::Charlie.into(); - MappingWithDeposit::::insert( - alice_as_nimbus.clone(), - RegistrationInfo { - account: 1, - deposit: DepositAmount::get(), - keys: alice_as_nimbus.clone(), - }, - ); - MappingWithDeposit::::insert( - bob_as_nimbus.clone(), - RegistrationInfo { - account: 1, - deposit: DepositAmount::get(), - keys: bob_as_nimbus.clone(), - }, - ); - MappingWithDeposit::::insert( - charlie_as_nimbus.clone(), - RegistrationInfo { - account: 1, - deposit: DepositAmount::get(), - keys: charlie_as_nimbus.clone(), - }, - ); - assert_ok!(Balances::reserve(&1, DepositAmount::get() * 3)); - // run migration - crate::migrations::AddAccountIdToNimbusLookup::::on_runtime_upgrade(); - // ensure last 2 mappings revoked => 200 unreserved but still 100 reserved - assert_eq!(Balances::free_balance(&1), DepositAmount::get() * 2); - assert_eq!(Balances::reserved_balance(&1), DepositAmount::get() * 1); - assert!(MappingWithDeposit::::get(bob_as_nimbus).is_some()); - assert!(MappingWithDeposit::::get(alice_as_nimbus).is_none()); - assert!(MappingWithDeposit::::get(charlie_as_nimbus).is_none()); - }) + ExtBuilder::default().with_balances(vec![(1, 300)]).build().execute_with(|| { + // register 3 NimbusId owned by 1 account + let alice_as_nimbus: NimbusId = TestAuthor::Alice.into(); + let bob_as_nimbus: NimbusId = TestAuthor::Bob.into(); + let charlie_as_nimbus: NimbusId = TestAuthor::Charlie.into(); + MappingWithDeposit::::insert( + alice_as_nimbus.clone(), + RegistrationInfo { + account: 1, + deposit: DepositAmount::get(), + keys: alice_as_nimbus.clone(), + }, + ); + MappingWithDeposit::::insert( + bob_as_nimbus.clone(), + RegistrationInfo { + account: 1, + deposit: DepositAmount::get(), + keys: bob_as_nimbus.clone(), + }, + ); + MappingWithDeposit::::insert( + charlie_as_nimbus.clone(), + RegistrationInfo { + account: 1, + deposit: DepositAmount::get(), + keys: charlie_as_nimbus.clone(), + }, + ); + assert_ok!(Balances::reserve(&1, DepositAmount::get() * 3)); + // run migration + crate::migrations::AddAccountIdToNimbusLookup::::on_runtime_upgrade(); + // ensure last 2 mappings revoked => 200 unreserved but still 100 reserved + assert_eq!(Balances::free_balance(&1), DepositAmount::get() * 2); + assert_eq!(Balances::reserved_balance(&1), DepositAmount::get()); + assert!(MappingWithDeposit::::get(bob_as_nimbus).is_some()); + assert!(MappingWithDeposit::::get(alice_as_nimbus).is_none()); + assert!(MappingWithDeposit::::get(charlie_as_nimbus).is_none()); + }) } diff --git a/external/pallets/author-mapping/src/weights.rs b/external/pallets/author-mapping/src/weights.rs index 30fd8b6a6..7fc754f33 100644 --- a/external/pallets/author-mapping/src/weights.rs +++ b/external/pallets/author-mapping/src/weights.rs @@ -44,116 +44,116 @@ #![allow(unused_imports)] use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, + traits::Get, + weights::{constants::RocksDbWeight, Weight}, }; use sp_std::marker::PhantomData; /// Weight functions needed for pallet_author_mapping. pub trait WeightInfo { - #[rustfmt::skip] + #[rustfmt::skip] fn add_association() -> Weight; - #[rustfmt::skip] + #[rustfmt::skip] fn update_association() -> Weight; - #[rustfmt::skip] + #[rustfmt::skip] fn clear_association() -> Weight; - #[rustfmt::skip] + #[rustfmt::skip] fn remove_keys() -> Weight; - #[rustfmt::skip] + #[rustfmt::skip] fn set_keys() -> Weight; } /// Weights for pallet_author_mapping using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) #[rustfmt::skip] - fn add_association() -> Weight { - Weight::from_ref_time(50_753_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + fn add_association() -> Weight { + Weight::from_ref_time(50_753_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) #[rustfmt::skip] - fn update_association() -> Weight { - Weight::from_ref_time(41_499_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + fn update_association() -> Weight { + Weight::from_ref_time(41_499_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) #[rustfmt::skip] - fn clear_association() -> Weight { - Weight::from_ref_time(55_398_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + fn clear_association() -> Weight { + Weight::from_ref_time(55_398_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) #[rustfmt::skip] - fn remove_keys() -> Weight { - Weight::from_ref_time(60_757_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + fn remove_keys() -> Weight { + Weight::from_ref_time(60_757_000_u64) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) #[rustfmt::skip] - fn set_keys() -> Weight { - Weight::from_ref_time(45_388_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + fn set_keys() -> Weight { + Weight::from_ref_time(45_388_000_u64) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) #[rustfmt::skip] - fn add_association() -> Weight { - Weight::from_ref_time(50_753_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + fn add_association() -> Weight { + Weight::from_ref_time(50_753_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) #[rustfmt::skip] - fn update_association() -> Weight { - Weight::from_ref_time(41_499_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + fn update_association() -> Weight { + Weight::from_ref_time(41_499_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:0 w:1) #[rustfmt::skip] - fn clear_association() -> Weight { - Weight::from_ref_time(55_398_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + fn clear_association() -> Weight { + Weight::from_ref_time(55_398_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + // Storage: System Account (r:1 w:1) #[rustfmt::skip] - fn remove_keys() -> Weight { - Weight::from_ref_time(60_757_000 as u64) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + fn remove_keys() -> Weight { + Weight::from_ref_time(60_757_000_u64) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + // Storage: AuthorMapping NimbusLookup (r:1 w:1) + // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) #[rustfmt::skip] - fn set_keys() -> Weight { - Weight::from_ref_time(45_388_000 as u64) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + fn set_keys() -> Weight { + Weight::from_ref_time(45_388_000_u64) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } } diff --git a/external/pallets/author-slot-filter/Cargo.toml b/external/pallets/author-slot-filter/Cargo.toml index e4b4ea067..236372328 100644 --- a/external/pallets/author-slot-filter/Cargo.toml +++ b/external/pallets/author-slot-filter/Cargo.toml @@ -1,45 +1,45 @@ [package] -name = "pallet-author-slot-filter" -authors = [ "PureStake" ] +authors = ["PureStake"] description = "Selects a pseudorandom Subset of eligible (probably staked) authors at each slot" edition = "2021" +name = "pallet-author-slot-filter" version = "0.9.0" [dependencies] -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } log = { version = "0.4.17", default-features = false } nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.0.0", default-features = false, features = [ "derive" ] } -serde = { version = "1.0.101", default-features = false, features = [ "derive" ] } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.32" } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", default-features = false, features = ["derive"] } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } # Benchmarks -frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false , branch = "polkadot-v0.9.32" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.32" } [dev-dependencies] -frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0" , branch = "polkadot-v0.9.32" } +frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0", branch = "polkadot-v0.9.32" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } [features] -default = [ "std" ] +default = ["std"] std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "serde/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", ] -runtime-benchmarks = [ "frame-benchmarking", "nimbus-primitives/runtime-benchmarks" ] +runtime-benchmarks = ["frame-benchmarking", "nimbus-primitives/runtime-benchmarks"] -try-runtime = [ "frame-support/try-runtime", "nimbus-primitives/try-runtime" ] +try-runtime = ["frame-support/try-runtime", "nimbus-primitives/try-runtime"] diff --git a/external/pallets/author-slot-filter/src/benchmarks.rs b/external/pallets/author-slot-filter/src/benchmarks.rs index 57537e76e..eb037ce49 100644 --- a/external/pallets/author-slot-filter/src/benchmarks.rs +++ b/external/pallets/author-slot-filter/src/benchmarks.rs @@ -16,35 +16,28 @@ #![cfg(feature = "runtime-benchmarks")] -use crate::num::NonZeroU32; -use crate::{Call, Config, Pallet}; +use crate::{num::NonZeroU32, Call, Config, Pallet}; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; use frame_system::RawOrigin; benchmarks! { - set_eligible { - let count = NonZeroU32::new_unchecked(34); - }: _(RawOrigin::Root, count.clone()) - verify { - assert_eq!(Pallet::::eligible_count(), count); - } + set_eligible { + let count = NonZeroU32::new_unchecked(34); + }: _(RawOrigin::Root, count.clone()) + verify { + assert_eq!(Pallet::::eligible_count(), count); + } } #[cfg(test)] mod tests { - use crate::mock::Test; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - TestExternalities::new(t) - } + use crate::mock::Test; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t) + } } -impl_benchmark_test_suite!( - Pallet, - crate::benchmarks::tests::new_test_ext(), - crate::mock::Test -); +impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Test); diff --git a/external/pallets/author-slot-filter/src/lib.rs b/external/pallets/author-slot-filter/src/lib.rs index 0fb60f5bb..011eb0b56 100644 --- a/external/pallets/author-slot-filter/src/lib.rs +++ b/external/pallets/author-slot-filter/src/lib.rs @@ -23,6 +23,7 @@ //! disfavor authors who are authoring a disproportionate amount of the time in an attempt to //! "even the playing field". +#![allow(deprecated)] #![cfg_attr(not(feature = "std"), no_std)] pub use pallet::*; @@ -42,186 +43,183 @@ mod tests; #[frame_support::pallet] pub mod pallet { - use crate::num::NonZeroU32; - use crate::weights::WeightInfo; - use frame_support::{pallet_prelude::*, traits::Randomness}; - use frame_system::pallet_prelude::*; - use log::debug; - use nimbus_primitives::CanAuthor; - use sp_core::H256; - use sp_runtime::Percent; - use sp_std::vec::Vec; - - /// The Author Filter pallet - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - /// Configuration trait of this pallet. - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type - type RuntimeEvent: From + IsType<::RuntimeEvent>; - /// Deterministic on-chain pseudo-randomness used to do the filtering - type RandomnessSource: Randomness; - //TODO introduce a new trait for exhaustive sets and use it here. - // Oh actually, we can use the same trait. First we call the inner one - // to determine whether this particular author is eligible there. then we - // use the author as part of the subject when querying eligibility. I like this better. - /// A source for the complete set of potential authors. - /// The starting point of the filtering. - type PotentialAuthors: Get>; - type WeightInfo: WeightInfo; - } - - /// Compute a pseudo-random subset of the input accounts by using Pallet's - /// source of randomness, `Config::RandomnessSource`. - /// Returns (Eligible, Ineligible), each is a set of accounts - pub fn compute_pseudo_random_subset( - mut active: Vec, - seed: &u32, - ) -> (Vec, Vec) { - let mut num_eligible = EligibleCount::::get().get() as usize; - if num_eligible > active.len() { - num_eligible = active.len(); - } - - let mut eligible = Vec::with_capacity(num_eligible); - - for i in 0..num_eligible { - // A context identifier for grabbing the randomness. Consists of three parts - // 1. Constant string *b"filter" - to identify this pallet - // 2. First 2 bytes of index.to_le_bytes when selecting the ith eligible author - // 3. First 4 bytes of seed.to_be_bytes - let mut first_two_bytes_of_index = &i.to_le_bytes()[..2]; - let mut first_four_bytes_of_seed = &seed.to_be_bytes()[..4]; - let mut constant_string: [u8; 6] = [b'f', b'i', b'l', b't', b'e', b'r']; - let mut subject: [u8; 12] = [0u8; 12]; - subject[..6].copy_from_slice(&mut constant_string); - subject[6..8].copy_from_slice(&mut first_two_bytes_of_index); - subject[8..].copy_from_slice(&mut first_four_bytes_of_seed); - let (randomness, _) = T::RandomnessSource::random(&subject); - debug!(target: "author-filter", "🎲Randomness sample {}: {:?}", i, &randomness); - - // Cast to u32 first so we get consistent results on 32- and 64-bit platforms. - let bytes: [u8; 4] = randomness.to_fixed_bytes()[0..4] - .try_into() - .expect("H256 has at least 4 bytes; qed"); - let randomness = u32::from_le_bytes(bytes) as usize; - - // Move the selected author from the original vector into the eligible vector - // TODO we could short-circuit this check by returning early when the claimed - // author is selected. For now I'll leave it like this because: - // 1. it is easier to understand what our core filtering logic is - // 2. we currently show the entire filtered set in the debug event - eligible.push(active.remove(randomness % active.len())); - } - (eligible, active) - } - - // This code will be called by the author-inherent pallet to check whether the reported author - // of this block is eligible in this slot. We calculate that result on demand and do not - // record it in storage (although we do emit a debugging event for now). - impl CanAuthor for Pallet { - #[cfg(not(feature = "try-runtime"))] - fn can_author(author: &T::AccountId, slot: &u32) -> bool { - // Compute pseudo-random subset of potential authors - let (eligible, ineligible) = - compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); - - // Print some logs for debugging purposes. - debug!(target: "author-filter", "Eligible Authors: {:?}", eligible); - debug!(target: "author-filter", "Ineligible Authors: {:?}", &ineligible); - debug!(target: "author-filter", - "Current author, {:?}, is eligible: {}", - author, - eligible.contains(author) - ); - - eligible.contains(author) - } - #[cfg(feature = "runtime-benchmarks")] - fn get_authors(slot: &u32) -> Vec { - // Compute pseudo-random subset of potential authors - let (eligible, _) = compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); - eligible - } - } - - #[pallet::call] - impl Pallet { - /// Update the eligible count. Intended to be called by governance. - #[pallet::weight(T::WeightInfo::set_eligible())] - pub fn set_eligible( - origin: OriginFor, - new: EligibilityValue, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - EligibleCount::::put(&new); - >::deposit_event(Event::EligibleUpdated(new)); - - Ok(Default::default()) - } - } - - /// The type of eligibility to use - pub type EligibilityValue = NonZeroU32; - - impl EligibilityValue { - /// Default total number of eligible authors, must NOT be 0. - pub fn default() -> Self { - NonZeroU32::new_unchecked(50) - } - } - - #[pallet::storage] - #[pallet::getter(fn eligible_ratio)] - #[deprecated(note = "use `pallet::EligibleCount` instead")] - pub type EligibleRatio = StorageValue<_, Percent, ValueQuery, Half>; - - // Default value for the `EligibleRatio` is one half. - #[pallet::type_value] - pub fn Half() -> Percent { - Percent::from_percent(50) - } - - /// The number of active authors that will be eligible at each height. - #[pallet::storage] - #[pallet::getter(fn eligible_count)] - pub type EligibleCount = - StorageValue<_, EligibilityValue, ValueQuery, DefaultEligibilityValue>; - - // Default value for the `EligibleCount`. - #[pallet::type_value] - pub fn DefaultEligibilityValue() -> EligibilityValue { - EligibilityValue::default() - } - - #[pallet::genesis_config] - pub struct GenesisConfig { - pub eligible_count: EligibilityValue, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - eligible_count: EligibilityValue::default(), - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - EligibleCount::::put(self.eligible_count.clone()); - } - } - - #[pallet::event] - #[pallet::generate_deposit(fn deposit_event)] - pub enum Event { - /// The amount of eligible authors for the filter to select has been changed. - EligibleUpdated(EligibilityValue), - } + use crate::{num::NonZeroU32, weights::WeightInfo}; + use frame_support::{pallet_prelude::*, traits::Randomness}; + use frame_system::pallet_prelude::*; + use log::debug; + use nimbus_primitives::CanAuthor; + use sp_core::H256; + use sp_runtime::Percent; + use sp_std::vec::Vec; + + /// The Author Filter pallet + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type + type RuntimeEvent: From + IsType<::RuntimeEvent>; + /// Deterministic on-chain pseudo-randomness used to do the filtering + type RandomnessSource: Randomness; + //TODO introduce a new trait for exhaustive sets and use it here. + // Oh actually, we can use the same trait. First we call the inner one + // to determine whether this particular author is eligible there. then we + // use the author as part of the subject when querying eligibility. I like this better. + /// A source for the complete set of potential authors. + /// The starting point of the filtering. + type PotentialAuthors: Get>; + type WeightInfo: WeightInfo; + } + + /// Compute a pseudo-random subset of the input accounts by using Pallet's + /// source of randomness, `Config::RandomnessSource`. + /// Returns (Eligible, Ineligible), each is a set of accounts + pub fn compute_pseudo_random_subset( + mut active: Vec, + seed: &u32, + ) -> (Vec, Vec) { + let mut num_eligible = EligibleCount::::get().get() as usize; + if num_eligible > active.len() { + num_eligible = active.len(); + } + + let mut eligible = Vec::with_capacity(num_eligible); + + for i in 0..num_eligible { + // A context identifier for grabbing the randomness. Consists of three parts + // 1. Constant string *b"filter" - to identify this pallet + // 2. First 2 bytes of index.to_le_bytes when selecting the ith eligible author + // 3. First 4 bytes of seed.to_be_bytes + let first_two_bytes_of_index = &i.to_le_bytes()[..2]; + let first_four_bytes_of_seed = &seed.to_be_bytes()[..4]; + let constant_string: [u8; 6] = [b'f', b'i', b'l', b't', b'e', b'r']; + let mut subject: [u8; 12] = [0u8; 12]; + subject[..6].copy_from_slice(&constant_string); + subject[6..8].copy_from_slice(first_two_bytes_of_index); + subject[8..].copy_from_slice(first_four_bytes_of_seed); + let (randomness, _) = T::RandomnessSource::random(&subject); + debug!(target: "author-filter", "🎲Randomness sample {}: {:?}", i, &randomness); + + // Cast to u32 first so we get consistent results on 32- and 64-bit platforms. + let bytes: [u8; 4] = randomness.to_fixed_bytes()[0..4] + .try_into() + .expect("H256 has at least 4 bytes; qed"); + let randomness = u32::from_le_bytes(bytes) as usize; + + // Move the selected author from the original vector into the eligible vector + // TODO we could short-circuit this check by returning early when the claimed + // author is selected. For now I'll leave it like this because: + // 1. it is easier to understand what our core filtering logic is + // 2. we currently show the entire filtered set in the debug event + eligible.push(active.remove(randomness % active.len())); + } + (eligible, active) + } + + // This code will be called by the author-inherent pallet to check whether the reported author + // of this block is eligible in this slot. We calculate that result on demand and do not + // record it in storage (although we do emit a debugging event for now). + impl CanAuthor for Pallet { + #[cfg(not(feature = "try-runtime"))] + fn can_author(author: &T::AccountId, slot: &u32) -> bool { + // Compute pseudo-random subset of potential authors + let (eligible, ineligible) = + compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); + + // Print some logs for debugging purposes. + debug!(target: "author-filter", "Eligible Authors: {:?}", eligible); + debug!(target: "author-filter", "Ineligible Authors: {:?}", &ineligible); + debug!(target: "author-filter", + "Current author, {:?}, is eligible: {}", + author, + eligible.contains(author) + ); + + eligible.contains(author) + } + #[cfg(feature = "runtime-benchmarks")] + fn get_authors(slot: &u32) -> Vec { + // Compute pseudo-random subset of potential authors + let (eligible, _) = compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); + eligible + } + } + + #[pallet::call] + impl Pallet { + /// Update the eligible count. Intended to be called by governance. + #[pallet::weight(T::WeightInfo::set_eligible())] + pub fn set_eligible( + origin: OriginFor, + new: EligibilityValue, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + EligibleCount::::put(&new); + >::deposit_event(Event::EligibleUpdated(new)); + + Ok(Default::default()) + } + } + + /// The type of eligibility to use + pub type EligibilityValue = NonZeroU32; + + impl EligibilityValue { + /// Default total number of eligible authors, must NOT be 0. + pub fn default() -> Self { + NonZeroU32::new_unchecked(50) + } + } + + #[pallet::storage] + #[pallet::getter(fn eligible_ratio)] + #[deprecated(note = "use `pallet::EligibleCount` instead")] + pub type EligibleRatio = StorageValue<_, Percent, ValueQuery, Half>; + + // Default value for the `EligibleRatio` is one half. + #[pallet::type_value] + pub fn Half() -> Percent { + Percent::from_percent(50) + } + + /// The number of active authors that will be eligible at each height. + #[pallet::storage] + #[pallet::getter(fn eligible_count)] + pub type EligibleCount = + StorageValue<_, EligibilityValue, ValueQuery, DefaultEligibilityValue>; + + // Default value for the `EligibleCount`. + #[pallet::type_value] + pub fn DefaultEligibilityValue() -> EligibilityValue { + EligibilityValue::default() + } + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub eligible_count: EligibilityValue, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { eligible_count: EligibilityValue::default() } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + EligibleCount::::put(self.eligible_count.clone()); + } + } + + #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] + pub enum Event { + /// The amount of eligible authors for the filter to select has been changed. + EligibleUpdated(EligibilityValue), + } } diff --git a/external/pallets/author-slot-filter/src/migration.rs b/external/pallets/author-slot-filter/src/migration.rs index 79f02023d..a9a7572ca 100644 --- a/external/pallets/author-slot-filter/src/migration.rs +++ b/external/pallets/author-slot-filter/src/migration.rs @@ -15,88 +15,87 @@ // along with Nimbus. If not, see . use core::marker::PhantomData; -use frame_support::traits::Get; -use frame_support::traits::OnRuntimeUpgrade; -use frame_support::weights::Weight; +use frame_support::{ + traits::{Get, OnRuntimeUpgrade}, + weights::Weight, +}; use parity_scale_codec::{Decode, Encode}; use sp_runtime::Percent; use sp_std::vec::Vec; -use super::num::NonZeroU32; -use super::pallet::Config; -use super::pallet::EligibilityValue; -use super::pallet::EligibleCount; -use super::pallet::Pallet; +use super::{ + num::NonZeroU32, + pallet::{Config, EligibilityValue, EligibleCount, Pallet}, +}; pub struct EligibleRatioToEligiblityCount(PhantomData); impl OnRuntimeUpgrade for EligibleRatioToEligiblityCount where - T: Config, + T: Config, { - fn on_runtime_upgrade() -> Weight { - log::info!(target: "EligibleRatioToEligiblityCount", "starting migration"); + fn on_runtime_upgrade() -> Weight { + log::info!(target: "EligibleRatioToEligiblityCount", "starting migration"); - let old_value = >::eligible_ratio(); - let total_authors = ::PotentialAuthors::get().len(); - let new_value = percent_of_num(old_value, total_authors as u32); - let new_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); - >::put(new_value); + let old_value = >::eligible_ratio(); + let total_authors = ::PotentialAuthors::get().len(); + let new_value = percent_of_num(old_value, total_authors as u32); + let new_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); + >::put(new_value); - T::DbWeight::get().reads_writes(1, 1) - } + T::DbWeight::get().reads_writes(1, 1) + } - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - let old_value = >::eligible_ratio(); + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let old_value = >::eligible_ratio(); - let total_authors = ::PotentialAuthors::get().len(); - let new_value = percent_of_num(old_value, total_authors as u32); - let expected_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); + let total_authors = ::PotentialAuthors::get().len(); + let new_value = percent_of_num(old_value, total_authors as u32); + let expected_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); - Ok(expected_value.encode()) - } + Ok(expected_value.encode()) + } - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - let expected: NonZeroU32 = - Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + let expected: NonZeroU32 = + Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - let actual = >::eligible_count(); + let actual = >::eligible_count(); - assert_eq!(expected, actual); + assert_eq!(expected, actual); - Ok(()) - } + Ok(()) + } } fn percent_of_num(percent: Percent, num: u32) -> u32 { - percent.mul_ceil(num as u32) + percent.mul_ceil(num as u32) } #[cfg(test)] mod tests { - use super::percent_of_num; - use super::*; + use super::{percent_of_num, *}; - #[test] - fn test_percent_of_num_ceils_value() { - let fifty_percent = Percent::from_float(0.5); + #[test] + fn test_percent_of_num_ceils_value() { + let fifty_percent = Percent::from_float(0.5); - let actual = percent_of_num(fifty_percent, 5); - assert_eq!(3, actual); + let actual = percent_of_num(fifty_percent, 5); + assert_eq!(3, actual); - let actual = percent_of_num(fifty_percent, 20); - assert_eq!(10, actual); - } + let actual = percent_of_num(fifty_percent, 20); + assert_eq!(10, actual); + } - #[test] - fn test_percent_of_num_hundred_percent_uses_full_value() { - let one_hundred_percent = Percent::from_float(1.0); + #[test] + fn test_percent_of_num_hundred_percent_uses_full_value() { + let one_hundred_percent = Percent::from_float(1.0); - let actual = percent_of_num(one_hundred_percent, 5); - assert_eq!(5, actual); + let actual = percent_of_num(one_hundred_percent, 5); + assert_eq!(5, actual); - let actual = percent_of_num(one_hundred_percent, 20); - assert_eq!(20, actual); - } + let actual = percent_of_num(one_hundred_percent, 20); + assert_eq!(20, actual); + } } diff --git a/external/pallets/author-slot-filter/src/mock.rs b/external/pallets/author-slot-filter/src/mock.rs index 1fdbe069a..7354a20db 100644 --- a/external/pallets/author-slot-filter/src/mock.rs +++ b/external/pallets/author-slot-filter/src/mock.rs @@ -15,78 +15,72 @@ // along with Nimbus. If not, see . use crate as pallet_testing; -use frame_support::parameter_types; -use frame_support::sp_io; -use frame_support::traits::ConstU32; -use frame_support::weights::RuntimeDbWeight; +use frame_support::{parameter_types, sp_io, traits::ConstU32, weights::RuntimeDbWeight}; use frame_support_test::TestRandomness; use sp_core::H256; use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, }; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - AuthorSlotFilter: pallet_testing::{Pallet, Call, Storage, Event}, - } + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + AuthorSlotFilter: pallet_testing::{Pallet, Call, Storage, Event}, + } ); parameter_types! { - pub const BlockHashCount: u64 = 250; - pub Authors: Vec = vec![1, 2, 3, 4, 5]; - pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 1, - write: 10, - }; + pub const BlockHashCount: u64 = 250; + pub Authors: Vec = vec![1, 2, 3, 4, 5]; + pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 1, + write: 10, + }; } impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = TestDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = TestDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; } impl pallet_testing::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RandomnessSource = TestRandomness; - type PotentialAuthors = Authors; - type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type RandomnessSource = TestRandomness; + type PotentialAuthors = Authors; + type WeightInfo = (); } /// Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::default() - .build_storage::() - .unwrap() - .into() + frame_system::GenesisConfig::default().build_storage::().unwrap().into() } diff --git a/external/pallets/author-slot-filter/src/num.rs b/external/pallets/author-slot-filter/src/num.rs index e38daad73..765423c61 100644 --- a/external/pallets/author-slot-filter/src/num.rs +++ b/external/pallets/author-slot-filter/src/num.rs @@ -19,109 +19,104 @@ use parity_scale_codec::{Decode, Encode, Error, Input}; use scale_info::TypeInfo; -use serde::de::Error as DeserializeError; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{de::Error as DeserializeError, Deserialize, Deserializer, Serialize, Serializer}; #[derive(Clone, Debug, TypeInfo, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NonZeroU32(u32); impl core::ops::Deref for NonZeroU32 { - type Target = u32; - fn deref(&self) -> &Self::Target { - &self.0 - } + type Target = u32; + fn deref(&self) -> &Self::Target { + &self.0 + } } impl parity_scale_codec::EncodeLike for NonZeroU32 {} impl NonZeroU32 { - /// Creates a new `Some(NonZeroU32)` instance if value is 0, `None` otherwise. - #[inline] - pub const fn new(n: u32) -> Option { - if n != 0 { - Some(Self(n)) - } else { - None - } - } - - /// new_unchecked creats a `NonZeroU32` where the user MUST guarantee - /// that the value is nonzero. - #[inline] - pub const fn new_unchecked(n: u32) -> Self { - Self(n) - } - - /// Returns the the underlying number - pub fn get(&self) -> u32 { - self.0 - } + /// Creates a new `Some(NonZeroU32)` instance if value is 0, `None` otherwise. + #[inline] + pub const fn new(n: u32) -> Option { + if n != 0 { Some(Self(n)) } else { None } + } + + /// new_unchecked creats a `NonZeroU32` where the user MUST guarantee + /// that the value is nonzero. + #[inline] + pub const fn new_unchecked(n: u32) -> Self { + Self(n) + } + + /// Returns the the underlying number + pub fn get(&self) -> u32 { + self.0 + } } #[cfg(feature = "std")] impl Serialize for NonZeroU32 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.clone().get().serialize(serializer) - } + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.clone().get().serialize(serializer) + } } #[cfg(feature = "std")] impl<'de> Deserialize<'de> for NonZeroU32 { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let value = Deserialize::deserialize(deserializer)?; - match NonZeroU32::new(value) { - Some(nonzero) => Ok(nonzero), - None => Err(DeserializeError::custom("expected a non-zero value")), - } - } + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = Deserialize::deserialize(deserializer)?; + match NonZeroU32::new(value) { + Some(nonzero) => Ok(nonzero), + None => Err(DeserializeError::custom("expected a non-zero value")), + } + } } impl Decode for NonZeroU32 { - fn decode(input: &mut I) -> Result { - Self::new(Decode::decode(input)?) - .ok_or_else(|| Error::from("cannot create non-zero number from 0")) - } + fn decode(input: &mut I) -> Result { + Self::new(Decode::decode(input)?) + .ok_or_else(|| Error::from("cannot create non-zero number from 0")) + } } #[cfg(test)] mod tests { - use super::*; - use parity_scale_codec::Encode; - - #[test] - fn test_new_returns_none_if_zero() { - assert_eq!(None, NonZeroU32::new(0)); - } - - #[test] - fn test_new_returns_some_if_nonzero() { - let n = 10; - let expected = Some(NonZeroU32::new_unchecked(n)); - - let actual = NonZeroU32::new(n); - assert_eq!(expected, actual); - assert_eq!(n, actual.unwrap().get()); - } - - #[test] - fn test_decode_errors_if_zero_value() { - let buf: Vec = 0u32.encode(); - let result = NonZeroU32::decode(&mut &buf[..]); - assert!(result.is_err(), "expected error, got {:?}", result); - } - - #[test] - fn test_decode_succeeds_if_nonzero_value() { - let buf: Vec = 1u32.encode(); - - let result = NonZeroU32::decode(&mut &buf[..]); - assert!(result.is_ok(), "unexpected error, got {:?}", result); - assert_eq!(Ok(NonZeroU32::new_unchecked(1)), result); - } + use super::*; + use parity_scale_codec::Encode; + + #[test] + fn test_new_returns_none_if_zero() { + assert_eq!(None, NonZeroU32::new(0)); + } + + #[test] + fn test_new_returns_some_if_nonzero() { + let n = 10; + let expected = Some(NonZeroU32::new_unchecked(n)); + + let actual = NonZeroU32::new(n); + assert_eq!(expected, actual); + assert_eq!(n, actual.unwrap().get()); + } + + #[test] + fn test_decode_errors_if_zero_value() { + let buf: Vec = 0u32.encode(); + let result = NonZeroU32::decode(&mut &buf[..]); + assert!(result.is_err(), "expected error, got {:?}", result); + } + + #[test] + fn test_decode_succeeds_if_nonzero_value() { + let buf: Vec = 1u32.encode(); + + let result = NonZeroU32::decode(&mut &buf[..]); + assert!(result.is_ok(), "unexpected error, got {:?}", result); + assert_eq!(Ok(NonZeroU32::new_unchecked(1)), result); + } } diff --git a/external/pallets/author-slot-filter/src/tests.rs b/external/pallets/author-slot-filter/src/tests.rs index cae418ad8..f01599a5e 100644 --- a/external/pallets/author-slot-filter/src/tests.rs +++ b/external/pallets/author-slot-filter/src/tests.rs @@ -15,84 +15,79 @@ // along with Nimbus. If not, see . use super::*; -use crate::mock::*; -use crate::num::NonZeroU32; +use crate::{mock::*, num::NonZeroU32}; -use frame_support::assert_ok; -use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; +use frame_support::{assert_ok, traits::OnRuntimeUpgrade, weights::Weight}; use sp_runtime::Percent; #[test] fn test_set_eligibility_works() { - new_test_ext().execute_with(|| { - let value = num::NonZeroU32::new_unchecked(34); - - assert_ok!(AuthorSlotFilter::set_eligible( - RuntimeOrigin::root(), - value.clone() - )); - assert_eq!(AuthorSlotFilter::eligible_count(), value) - }); + new_test_ext().execute_with(|| { + let value = num::NonZeroU32::new_unchecked(34); + + assert_ok!(AuthorSlotFilter::set_eligible(RuntimeOrigin::root(), value.clone())); + assert_eq!(AuthorSlotFilter::eligible_count(), value) + }); } #[allow(deprecated)] #[test] fn test_migration_works_for_converting_existing_eligible_ratio_to_eligible_count() { - new_test_ext().execute_with(|| { - let input_eligible_ratio = Percent::from_percent(50); - let total_author_count = mock::Authors::get().len(); - let eligible_author_count = input_eligible_ratio.mul_ceil(total_author_count) as u32; - let expected_eligible_count = NonZeroU32::new_unchecked(eligible_author_count); - let expected_weight = - Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); - - >::put(input_eligible_ratio); - - let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); - assert_eq!(expected_weight, actual_weight); - - let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); - let actual_eligible_count = AuthorSlotFilter::eligible_count(); - assert_eq!(expected_eligible_count, actual_eligible_count); - assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); - }); + new_test_ext().execute_with(|| { + let input_eligible_ratio = Percent::from_percent(50); + let total_author_count = mock::Authors::get().len(); + let eligible_author_count = input_eligible_ratio.mul_ceil(total_author_count) as u32; + let expected_eligible_count = NonZeroU32::new_unchecked(eligible_author_count); + let expected_weight = + Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); + + >::put(input_eligible_ratio); + + let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); + assert_eq!(expected_weight, actual_weight); + + let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); + let actual_eligible_count = AuthorSlotFilter::eligible_count(); + assert_eq!(expected_eligible_count, actual_eligible_count); + assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); + }); } #[allow(deprecated)] #[test] fn test_migration_works_for_converting_existing_zero_eligible_ratio_to_default_eligible_count() { - new_test_ext().execute_with(|| { - let input_eligible_ratio = Percent::from_percent(0); - let expected_eligible_count = EligibilityValue::default(); - let expected_weight = - Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); - - >::put(input_eligible_ratio); - - let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); - assert_eq!(expected_weight, actual_weight); - - let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); - let actual_eligible_count = AuthorSlotFilter::eligible_count(); - assert_eq!(expected_eligible_count, actual_eligible_count); - assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); - }); + new_test_ext().execute_with(|| { + let input_eligible_ratio = Percent::from_percent(0); + let expected_eligible_count = EligibilityValue::default(); + let expected_weight = + Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); + + >::put(input_eligible_ratio); + + let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); + assert_eq!(expected_weight, actual_weight); + + let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); + let actual_eligible_count = AuthorSlotFilter::eligible_count(); + assert_eq!(expected_eligible_count, actual_eligible_count); + assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); + }); } #[allow(deprecated)] #[test] fn test_migration_inserts_default_value_for_missing_eligible_ratio() { - new_test_ext().execute_with(|| { - let default_eligible_ratio = Percent::from_percent(50); - let expected_default_eligible_count = - NonZeroU32::new_unchecked(default_eligible_ratio.mul_ceil(Authors::get().len() as u32)); - let expected_weight = - Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); - - let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); - assert_eq!(expected_weight, actual_weight); - - let actual_eligible_count = AuthorSlotFilter::eligible_count(); - assert_eq!(expected_default_eligible_count, actual_eligible_count); - }); + new_test_ext().execute_with(|| { + let default_eligible_ratio = Percent::from_percent(50); + let expected_default_eligible_count = + NonZeroU32::new_unchecked(default_eligible_ratio.mul_ceil(Authors::get().len() as u32)); + let expected_weight = + Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); + + let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); + assert_eq!(expected_weight, actual_weight); + + let actual_eligible_count = AuthorSlotFilter::eligible_count(); + assert_eq!(expected_default_eligible_count, actual_eligible_count); + }); } diff --git a/external/pallets/author-slot-filter/src/weights.rs b/external/pallets/author-slot-filter/src/weights.rs index 8542f0aa7..8b7ee79c2 100644 --- a/external/pallets/author-slot-filter/src/weights.rs +++ b/external/pallets/author-slot-filter/src/weights.rs @@ -44,28 +44,27 @@ #![allow(unused_imports)] use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, + traits::Get, + weights::{constants::RocksDbWeight, Weight}, }; use sp_std::marker::PhantomData; /// Weight functions needed for pallet_author_slot_filter. pub trait WeightInfo { - fn set_eligible() -> Weight; + fn set_eligible() -> Weight; } /// Weights for pallet_author_slot_filter using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn set_eligible() -> Weight { - Weight::from_ref_time(13_250_000 as u64).saturating_add(T::DbWeight::get().writes(1 as u64)) - } + fn set_eligible() -> Weight { + Weight::from_ref_time(13_250_000_u64).saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests impl WeightInfo for () { - fn set_eligible() -> Weight { - Weight::from_ref_time(13_250_000 as u64) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } + fn set_eligible() -> Weight { + Weight::from_ref_time(13_250_000_u64).saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/external/pallets/parachain-staking/Cargo.toml b/external/pallets/parachain-staking/Cargo.toml index 2c9a4b562..3b596e3fa 100644 --- a/external/pallets/parachain-staking/Cargo.toml +++ b/external/pallets/parachain-staking/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "pallet-parachain-staking" -authors = [ "PureStake" ] +authors = ["PureStake"] description = "parachain staking pallet for collator selection and reward distribution" edition = "2021" +name = "pallet-parachain-staking" version = "3.0.0" [dependencies] @@ -13,8 +13,8 @@ serde = { version = "1.0.101", optional = true } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0", default-features = false, features = ["derive"] } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } @@ -29,17 +29,17 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot- sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } [features] -default = [ "std" ] +default = ["std"] +runtime-benchmarks = ["frame-benchmarking"] std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "serde", - "sp-runtime/std", - "sp-std/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde", + "sp-runtime/std", + "sp-std/std", ] -runtime-benchmarks = [ "frame-benchmarking" ] -try-runtime = [ "frame-support/try-runtime" ] +try-runtime = ["frame-support/try-runtime"] diff --git a/external/pallets/parachain-staking/src/auto_compound.rs b/external/pallets/parachain-staking/src/auto_compound.rs index 653c96ff9..f9ee68b54 100644 --- a/external/pallets/parachain-staking/src/auto_compound.rs +++ b/external/pallets/parachain-staking/src/auto_compound.rs @@ -15,27 +15,25 @@ // along with Moonbeam. If not, see . //! Auto-compounding functionality for staking rewards - -use crate::pallet::{ - AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, CandidateInfo, - Config, DelegatorState, Error, Event, Pallet, Total, +#![allow(clippy::len_without_is_empty)] +use crate::{ + pallet::{ + AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, CandidateInfo, + Config, DelegatorState, Error, Event, Pallet, Total, + }, + types::{Bond, BondAdjust, Delegator}, }; -use crate::types::{Bond, BondAdjust, Delegator}; -use frame_support::ensure; -use frame_support::traits::Get; -use frame_support::{dispatch::DispatchResultWithPostInfo, RuntimeDebug}; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_runtime::traits::Saturating; -use sp_runtime::Percent; -use sp_std::prelude::*; -use sp_std::vec::Vec; +use sp_runtime::{traits::Saturating, Percent}; +use sp_std::{prelude::*, vec::Vec}; /// Represents the auto-compounding amount for a delegation. #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] pub struct AutoCompoundConfig { - pub delegator: AccountId, - pub value: Percent, + pub delegator: AccountId, + pub value: Percent, } /// Represents the auto-compounding [Delegations] for `T: Config` @@ -44,334 +42,285 @@ pub struct AutoCompoundDelegations(Vec AutoCompoundDelegations where - T: Config, + T: Config, { - /// Creates a new instance of [AutoCompoundingDelegations] from a vector of sorted_delegations. - /// This is used for testing purposes only. - #[cfg(test)] - pub fn new(sorted_delegations: Vec>) -> Self { - Self(sorted_delegations) - } - - /// Retrieves an instance of [AutoCompoundingDelegations] storage as [AutoCompoundDelegations]. - pub fn get_storage(candidate: &T::AccountId) -> Self { - Self(>::get(candidate)) - } - - /// Inserts the current state to [AutoCompoundingDelegations] storage. - pub fn set_storage(self, candidate: &T::AccountId) { - >::insert(candidate, self.0) - } - - /// Retrieves the auto-compounding value for a delegation. The `delegations_config` must be a - /// sorted vector for binary_search to work. - pub fn get_for_delegator(&self, delegator: &T::AccountId) -> Option { - match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { - Ok(index) => Some(self.0[index].value), - Err(_) => None, - } - } - - /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted - /// vector for binary_search to work. - pub fn set_for_delegator(&mut self, delegator: T::AccountId, value: Percent) -> bool { - match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { - Ok(index) => { - if self.0[index].value == value { - false - } else { - self.0[index].value = value; - true - } - } - Err(index) => { - self.0 - .insert(index, AutoCompoundConfig { delegator, value }); - true - } - } - } - - /// Removes the auto-compounding value for a delegation. - /// Returns `true` if the entry was removed, `false` otherwise. The `delegations_config` must be a - /// sorted vector for binary_search to work. - pub fn remove_for_delegator(&mut self, delegator: &T::AccountId) -> bool { - match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { - Ok(index) => { - self.0.remove(index); - true - } - Err(_) => false, - } - } - - /// Returns the length of the inner vector. - pub fn len(&self) -> u32 { - self.0.len() as u32 - } - - /// Returns a reference to the inner vector. - #[cfg(test)] - pub fn inner(&self) -> &Vec> { - &self.0 - } - - /// Converts the [AutoCompoundDelegations] into the inner vector. - #[cfg(test)] - pub fn into_inner(self) -> Vec> { - self.0 - } - - // -- pallet functions -- - - /// Delegates and sets the auto-compounding config. The function skips inserting auto-compound - /// storage and validation, if the auto-compound value is 0%. - pub(crate) fn delegate_with_auto_compound( - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - auto_compound: Percent, - candidate_delegation_count_hint: u32, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - // check that caller can lock the amount before any changes to storage - ensure!( - >::get_delegator_stakable_free_balance(&delegator) >= amount, - Error::::InsufficientBalance - ); - - let mut delegator_state = if let Some(mut state) = >::get(&delegator) { - // delegation after first - ensure!( - amount >= T::MinDelegation::get(), - Error::::DelegationBelowMin - ); - ensure!( - delegation_count_hint >= state.delegations.0.len() as u32, - Error::::TooLowDelegationCountToDelegate - ); - ensure!( - (state.delegations.0.len() as u32) < T::MaxDelegationsPerDelegator::get(), - Error::::ExceedMaxDelegationsPerDelegator - ); - ensure!( - state.add_delegation(Bond { - owner: candidate.clone(), - amount - }), - Error::::AlreadyDelegatedCandidate - ); - state - } else { - // first delegation - ensure!( - amount >= T::MinDelegatorStk::get(), - Error::::DelegatorBondBelowMin - ); - ensure!( - !>::is_candidate(&delegator), - Error::::CandidateExists - ); - Delegator::new(delegator.clone(), candidate.clone(), amount) - }; - let mut candidate_state = - >::get(&candidate).ok_or(Error::::CandidateDNE)?; - ensure!( - candidate_delegation_count_hint >= candidate_state.delegation_count, - Error::::TooLowCandidateDelegationCountToDelegate - ); - - let auto_compounding_state = if !auto_compound.is_zero() { - let auto_compounding_state = Self::get_storage(&candidate); - ensure!( - auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, - >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, - ); - Some(auto_compounding_state) - } else { - None - }; - - // add delegation to candidate - let (delegator_position, less_total_staked) = candidate_state.add_delegation::( - &candidate, - Bond { - owner: delegator.clone(), - amount, - }, - )?; - - // lock delegator amount - delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; - - // adjust total locked, - // only is_some if kicked the lowest bottom as a consequence of this new delegation - let net_total_increase = if let Some(less) = less_total_staked { - amount.saturating_sub(less) - } else { - amount - }; - let new_total_locked = >::get().saturating_add(net_total_increase); - - // maybe set auto-compound config, state is Some if the percent is non-zero - if let Some(mut state) = auto_compounding_state { - state.set_for_delegator(delegator.clone(), auto_compound.clone()); - state.set_storage(&candidate); - } - - >::put(new_total_locked); - >::insert(&candidate, candidate_state); - >::insert(&delegator, delegator_state); - >::deposit_event(Event::Delegation { - delegator: delegator, - locked_amount: amount, - candidate: candidate, - delegator_position: delegator_position, - auto_compound, - }); - - Ok(().into()) - } - - /// Sets the auto-compounding value for a delegation. The config is removed if value is zero. - pub(crate) fn set_auto_compound( - candidate: T::AccountId, - delegator: T::AccountId, - value: Percent, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - let delegator_state = - >::get(&delegator).ok_or(>::DelegatorDNE)?; - ensure!( - delegator_state.delegations.0.len() <= delegation_count_hint as usize, - >::TooLowDelegationCountToAutoCompound, - ); - ensure!( - delegator_state - .delegations - .0 - .iter() - .any(|b| b.owner == candidate), - >::DelegationDNE, - ); - - let mut auto_compounding_state = Self::get_storage(&candidate); - ensure!( - auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, - >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - ); - let state_updated = if value.is_zero() { - auto_compounding_state.remove_for_delegator(&delegator) - } else { - auto_compounding_state.set_for_delegator(delegator.clone(), value) - }; - if state_updated { - auto_compounding_state.set_storage(&candidate); - } - - >::deposit_event(Event::AutoCompoundSet { - candidate, - delegator, - value, - }); - - Ok(().into()) - } - - /// Removes the auto-compounding value for a delegation. This should be called when the - /// delegation is revoked to cleanup storage. Storage is only written iff the entry existed. - pub(crate) fn remove_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) { - let mut auto_compounding_state = Self::get_storage(candidate); - if auto_compounding_state.remove_for_delegator(delegator) { - auto_compounding_state.set_storage(&candidate); - } - } - - /// Returns the value of auto-compound, if it exists for a given delegation, zero otherwise. - pub(crate) fn auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { - let delegations_config = Self::get_storage(candidate); - delegations_config - .get_for_delegator(&delegator) - .unwrap_or_else(|| Percent::zero()) - } + /// Creates a new instance of [AutoCompoundingDelegations] from a vector of sorted_delegations. + /// This is used for testing purposes only. + #[cfg(test)] + pub fn new(sorted_delegations: Vec>) -> Self { + Self(sorted_delegations) + } + + /// Retrieves an instance of [AutoCompoundingDelegations] storage as [AutoCompoundDelegations]. + pub fn get_storage(candidate: &T::AccountId) -> Self { + Self(>::get(candidate)) + } + + /// Inserts the current state to [AutoCompoundingDelegations] storage. + pub fn set_storage(self, candidate: &T::AccountId) { + >::insert(candidate, self.0) + } + + /// Retrieves the auto-compounding value for a delegation. The `delegations_config` must be a + /// sorted vector for binary_search to work. + pub fn get_for_delegator(&self, delegator: &T::AccountId) -> Option { + match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { + Ok(index) => Some(self.0[index].value), + Err(_) => None, + } + } + + /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted + /// vector for binary_search to work. + pub fn set_for_delegator(&mut self, delegator: T::AccountId, value: Percent) -> bool { + match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { + Ok(index) => { + if self.0[index].value == value { + false + } else { + self.0[index].value = value; + true + } + } + Err(index) => { + self.0.insert(index, AutoCompoundConfig { delegator, value }); + true + } + } + } + + /// Removes the auto-compounding value for a delegation. + /// Returns `true` if the entry was removed, `false` otherwise. The `delegations_config` must be a + /// sorted vector for binary_search to work. + pub fn remove_for_delegator(&mut self, delegator: &T::AccountId) -> bool { + match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { + Ok(index) => { + self.0.remove(index); + true + } + Err(_) => false, + } + } + + /// Returns the length of the inner vector. + pub fn len(&self) -> u32 { + self.0.len() as u32 + } + + /// Returns a reference to the inner vector. + #[cfg(test)] + pub fn inner(&self) -> &Vec> { + &self.0 + } + + /// Converts the [AutoCompoundDelegations] into the inner vector. + #[cfg(test)] + pub fn into_inner(self) -> Vec> { + self.0 + } + + // -- pallet functions -- + + /// Delegates and sets the auto-compounding config. The function skips inserting auto-compound + /// storage and validation, if the auto-compound value is 0%. + pub(crate) fn delegate_with_auto_compound( + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + auto_compound: Percent, + candidate_delegation_count_hint: u32, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + // check that caller can lock the amount before any changes to storage + ensure!( + >::get_delegator_stakable_free_balance(&delegator) >= amount, + Error::::InsufficientBalance + ); + + let mut delegator_state = if let Some(mut state) = >::get(&delegator) { + // delegation after first + ensure!(amount >= T::MinDelegation::get(), Error::::DelegationBelowMin); + ensure!( + delegation_count_hint >= state.delegations.0.len() as u32, + Error::::TooLowDelegationCountToDelegate + ); + ensure!( + (state.delegations.0.len() as u32) < T::MaxDelegationsPerDelegator::get(), + Error::::ExceedMaxDelegationsPerDelegator + ); + ensure!( + state.add_delegation(Bond { owner: candidate.clone(), amount }), + Error::::AlreadyDelegatedCandidate + ); + state + } else { + // first delegation + ensure!(amount >= T::MinDelegatorStk::get(), Error::::DelegatorBondBelowMin); + ensure!(!>::is_candidate(&delegator), Error::::CandidateExists); + Delegator::new(delegator.clone(), candidate.clone(), amount) + }; + let mut candidate_state = + >::get(&candidate).ok_or(Error::::CandidateDNE)?; + ensure!( + candidate_delegation_count_hint >= candidate_state.delegation_count, + Error::::TooLowCandidateDelegationCountToDelegate + ); + + let auto_compounding_state = if !auto_compound.is_zero() { + let auto_compounding_state = Self::get_storage(&candidate); + ensure!( + auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, + >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, + ); + Some(auto_compounding_state) + } else { + None + }; + + // add delegation to candidate + let (delegator_position, less_total_staked) = candidate_state + .add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; + + // lock delegator amount + delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; + + // adjust total locked, + // only is_some if kicked the lowest bottom as a consequence of this new delegation + let net_total_increase = + if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; + let new_total_locked = >::get().saturating_add(net_total_increase); + + // maybe set auto-compound config, state is Some if the percent is non-zero + if let Some(mut state) = auto_compounding_state { + state.set_for_delegator(delegator.clone(), auto_compound); + state.set_storage(&candidate); + } + + >::put(new_total_locked); + >::insert(&candidate, candidate_state); + >::insert(&delegator, delegator_state); + >::deposit_event(Event::Delegation { + delegator, + locked_amount: amount, + candidate, + delegator_position, + auto_compound, + }); + + Ok(().into()) + } + + /// Sets the auto-compounding value for a delegation. The config is removed if value is zero. + pub(crate) fn set_auto_compound( + candidate: T::AccountId, + delegator: T::AccountId, + value: Percent, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + let delegator_state = + >::get(&delegator).ok_or(>::DelegatorDNE)?; + ensure!( + delegator_state.delegations.0.len() <= delegation_count_hint as usize, + >::TooLowDelegationCountToAutoCompound, + ); + ensure!( + delegator_state.delegations.0.iter().any(|b| b.owner == candidate), + >::DelegationDNE, + ); + + let mut auto_compounding_state = Self::get_storage(&candidate); + ensure!( + auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, + >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + ); + let state_updated = if value.is_zero() { + auto_compounding_state.remove_for_delegator(&delegator) + } else { + auto_compounding_state.set_for_delegator(delegator.clone(), value) + }; + if state_updated { + auto_compounding_state.set_storage(&candidate); + } + + >::deposit_event(Event::AutoCompoundSet { candidate, delegator, value }); + + Ok(().into()) + } + + /// Removes the auto-compounding value for a delegation. This should be called when the + /// delegation is revoked to cleanup storage. Storage is only written iff the entry existed. + pub(crate) fn remove_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) { + let mut auto_compounding_state = Self::get_storage(candidate); + if auto_compounding_state.remove_for_delegator(delegator) { + auto_compounding_state.set_storage(candidate); + } + } + + /// Returns the value of auto-compound, if it exists for a given delegation, zero otherwise. + pub(crate) fn auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { + let delegations_config = Self::get_storage(candidate); + delegations_config.get_for_delegator(delegator).unwrap_or_else(Percent::zero) + } } #[cfg(test)] mod tests { - use super::*; - use crate::mock::Test; - - #[test] - fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { - let mut delegations_config = AutoCompoundDelegations::::new(vec![]); - assert_eq!( - true, - delegations_config.set_for_delegator(1, Percent::from_percent(50)) - ); - assert_eq!( - vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(50), - }], - delegations_config.into_inner(), - ); - } - - #[test] - fn test_set_for_delegator_updates_config_and_returns_true_if_entry_changed() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }]); - assert_eq!( - true, - delegations_config.set_for_delegator(1, Percent::from_percent(50)) - ); - assert_eq!( - vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(50), - }], - delegations_config.into_inner(), - ); - } - - #[test] - fn test_set_for_delegator_updates_config_and_returns_false_if_entry_unchanged() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }]); - assert_eq!( - false, - delegations_config.set_for_delegator(1, Percent::from_percent(10)) - ); - assert_eq!( - vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }], - delegations_config.into_inner(), - ); - } - - #[test] - fn test_remove_for_delegator_returns_false_if_entry_was_missing() { - let mut delegations_config = AutoCompoundDelegations::::new(vec![]); - assert_eq!(false, delegations_config.remove_for_delegator(&1),); - } - - #[test] - fn test_remove_delegation_config_returns_true_if_entry_existed() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }]); - assert_eq!(true, delegations_config.remove_for_delegator(&1)); - } + use super::*; + use crate::mock::Test; + + #[test] + fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { + let mut delegations_config = AutoCompoundDelegations::::new(vec![]); + assert!(delegations_config.set_for_delegator(1, Percent::from_percent(50))); + assert_eq!( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], + delegations_config.into_inner(), + ); + } + + #[test] + fn test_set_for_delegator_updates_config_and_returns_true_if_entry_changed() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }]); + assert!(delegations_config.set_for_delegator(1, Percent::from_percent(50))); + assert_eq!( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], + delegations_config.into_inner(), + ); + } + + #[test] + fn test_set_for_delegator_updates_config_and_returns_false_if_entry_unchanged() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }]); + assert!(!delegations_config.set_for_delegator(1, Percent::from_percent(10))); + assert_eq!( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }], + delegations_config.into_inner(), + ); + } + + #[test] + fn test_remove_for_delegator_returns_false_if_entry_was_missing() { + let mut delegations_config = AutoCompoundDelegations::::new(vec![]); + assert!(!delegations_config.remove_for_delegator(&1),); + } + + #[test] + fn test_remove_delegation_config_returns_true_if_entry_existed() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![AutoCompoundConfig { + delegator: 1, + value: Percent::from_percent(10), + }]); + assert!(delegations_config.remove_for_delegator(&1)); + } } diff --git a/external/pallets/parachain-staking/src/benchmarks.rs b/external/pallets/parachain-staking/src/benchmarks.rs index a34536d04..283f270c2 100644 --- a/external/pallets/parachain-staking/src/benchmarks.rs +++ b/external/pallets/parachain-staking/src/benchmarks.rs @@ -18,9 +18,9 @@ //! Benchmarking use crate::{ - AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, - ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, - Staked, TopDelegations, + AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, + ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, + Staked, TopDelegations, }; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; @@ -30,1473 +30,1454 @@ use sp_std::vec::Vec; /// Minimum collator candidate stake fn min_candidate_stk() -> BalanceOf { - <::MinCollatorStk as Get>>::get() + <::MinCollatorStk as Get>>::get() } /// Minimum delegator stake fn min_delegator_stk() -> BalanceOf { - <::MinDelegatorStk as Get>>::get() + <::MinDelegatorStk as Get>>::get() } /// Create a funded user. /// Extra + min_candidate_stk is total minted funds /// Returns tuple (id, balance) fn create_funded_user( - string: &'static str, - n: u32, - extra: BalanceOf, + string: &'static str, + n: u32, + extra: BalanceOf, ) -> (T::AccountId, BalanceOf) { - const SEED: u32 = 0; - let user = account(string, n, SEED); - let min_candidate_stk = min_candidate_stk::(); - let total = min_candidate_stk + extra; - T::Currency::make_free_balance_be(&user, total); - T::Currency::issue(total); - (user, total) + const SEED: u32 = 0; + let user = account(string, n, SEED); + let min_candidate_stk = min_candidate_stk::(); + let total = min_candidate_stk + extra; + T::Currency::make_free_balance_be(&user, total); + T::Currency::issue(total); + (user, total) } /// Create a funded delegator. fn create_funded_delegator( - string: &'static str, - n: u32, - extra: BalanceOf, - collator: T::AccountId, - min_bond: bool, - collator_delegator_count: u32, + string: &'static str, + n: u32, + extra: BalanceOf, + collator: T::AccountId, + min_bond: bool, + collator_delegator_count: u32, ) -> Result { - let (user, total) = create_funded_user::(string, n, extra); - let bond = if min_bond { - min_delegator_stk::() - } else { - total - }; - Pallet::::delegate( - RawOrigin::Signed(user.clone()).into(), - collator, - bond, - collator_delegator_count, - 0u32, // first delegation for all calls - )?; - Ok(user) + let (user, total) = create_funded_user::(string, n, extra); + let bond = if min_bond { min_delegator_stk::() } else { total }; + Pallet::::delegate( + RawOrigin::Signed(user.clone()).into(), + collator, + bond, + collator_delegator_count, + 0u32, // first delegation for all calls + )?; + Ok(user) } /// Create a funded collator. fn create_funded_collator( - string: &'static str, - n: u32, - extra: BalanceOf, - min_bond: bool, - candidate_count: u32, + string: &'static str, + n: u32, + extra: BalanceOf, + min_bond: bool, + candidate_count: u32, ) -> Result { - let (user, total) = create_funded_user::(string, n, extra); - let bond = if min_bond { - min_candidate_stk::() - } else { - total - }; - Pallet::::join_candidates( - RawOrigin::Signed(user.clone()).into(), - bond, - candidate_count, - )?; - Ok(user) + let (user, total) = create_funded_user::(string, n, extra); + let bond = if min_bond { min_candidate_stk::() } else { total }; + Pallet::::join_candidates(RawOrigin::Signed(user.clone()).into(), bond, candidate_count)?; + Ok(user) } // Simulate staking on finalize by manually setting points fn parachain_staking_on_finalize(author: T::AccountId) { - let now = >::get().current; - let score_plus_20 = >::get(now, &author).saturating_add(20); - >::insert(now, author, score_plus_20); - >::mutate(now, |x| *x = x.saturating_add(20)); + let now = >::get().current; + let score_plus_20 = >::get(now, &author).saturating_add(20); + >::insert(now, author, score_plus_20); + >::mutate(now, |x| *x = x.saturating_add(20)); } /// Run to end block and author fn roll_to_and_author(round_delay: u32, author: T::AccountId) { - let total_rounds = round_delay + 1u32; - let round_length: T::BlockNumber = Pallet::::round().length.into(); - let mut now = >::block_number() + 1u32.into(); - let end = Pallet::::round().first + (round_length * total_rounds.into()); - while now < end { - parachain_staking_on_finalize::(author.clone()); - >::on_finalize(>::block_number()); - >::set_block_number( - >::block_number() + 1u32.into(), - ); - >::on_initialize(>::block_number()); - Pallet::::on_initialize(>::block_number()); - now += 1u32.into(); - } + let total_rounds = round_delay + 1u32; + let round_length: T::BlockNumber = Pallet::::round().length.into(); + let mut now = >::block_number() + 1u32.into(); + let end = Pallet::::round().first + (round_length * total_rounds.into()); + while now < end { + parachain_staking_on_finalize::(author.clone()); + >::on_finalize(>::block_number()); + >::set_block_number( + >::block_number() + 1u32.into(), + ); + >::on_initialize(>::block_number()); + Pallet::::on_initialize(>::block_number()); + now += 1u32.into(); + } } const USER_SEED: u32 = 999666; struct Seed { - pub inner: u32, + pub inner: u32, } impl Seed { - fn new() -> Self { - Seed { inner: USER_SEED } - } - - pub fn take(&mut self) -> u32 { - let v = self.inner; - self.inner += 1; - v - } + fn new() -> Self { + Seed { inner: USER_SEED } + } + + pub fn take(&mut self) -> u32 { + let v = self.inner; + self.inner += 1; + v + } } benchmarks! { - // MONETARY ORIGIN DISPATCHABLES - set_staking_expectations { - let stake_range: Range> = Range { - min: 100u32.into(), - ideal: 200u32.into(), - max: 300u32.into(), - }; - }: _(RawOrigin::Root, stake_range) - verify { - assert_eq!(Pallet::::inflation_config().expect, stake_range); - } - - set_inflation { - let inflation_range: Range = Range { - min: Perbill::from_perthousand(1), - ideal: Perbill::from_perthousand(2), - max: Perbill::from_perthousand(3), - }; - - }: _(RawOrigin::Root, inflation_range) - verify { - assert_eq!(Pallet::::inflation_config().annual, inflation_range); - } - - set_parachain_bond_account { - let parachain_bond_account: T::AccountId = account("TEST", 0u32, USER_SEED); - }: _(RawOrigin::Root, parachain_bond_account.clone()) - verify { - assert_eq!(Pallet::::parachain_bond_info().account, parachain_bond_account); - } - - set_parachain_bond_reserve_percent { - }: _(RawOrigin::Root, Percent::from_percent(33)) - verify { - assert_eq!(Pallet::::parachain_bond_info().percent, Percent::from_percent(33)); - } - - // ROOT DISPATCHABLES - - set_total_selected { - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; - }: _(RawOrigin::Root, 100u32) - verify { - assert_eq!(Pallet::::total_selected(), 100u32); - } - - set_collator_commission {}: _(RawOrigin::Root, Perbill::from_percent(33)) - verify { - assert_eq!(Pallet::::collator_commission(), Perbill::from_percent(33)); - } - - set_blocks_per_round {}: _(RawOrigin::Root, 1200u32) - verify { - assert_eq!(Pallet::::round().length, 1200u32); - } - - // USER DISPATCHABLES - - join_candidates { - let x in 3..1_000; - // Worst Case Complexity is insertion into an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let (caller, min_candidate_stk) = create_funded_user::("caller", USER_SEED, 0u32.into()); - }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk, candidate_count) - verify { - assert!(Pallet::::is_candidate(&caller)); - } - - // This call schedules the collator's exit and removes them from the candidate pool - // -> it retains the self-bond and delegator bonds - schedule_leave_candidates { - let x in 3..1_000; - // Worst Case Complexity is removal from an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let caller: T::AccountId = create_funded_collator::( - "caller", - USER_SEED, - 0u32.into(), - true, - candidate_count, - )?; - candidate_count += 1u32; - }: _(RawOrigin::Signed(caller.clone()), candidate_count) - verify { - assert!(Pallet::::candidate_info(&caller).unwrap().is_leaving()); - } - - execute_leave_candidates { - // x is total number of delegations for the candidate - let x in 2..(<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get()); - let candidate: T::AccountId = create_funded_collator::( - "unique_caller", - USER_SEED - 100, - 0u32.into(), - true, - 1u32, - )?; - // 2nd delegation required for all delegators to ensure DelegatorState updated not removed - let second_candidate: T::AccountId = create_funded_collator::( - "unique__caller", - USER_SEED - 99, - 0u32.into(), - true, - 2u32, - )?; - let mut delegators: Vec = Vec::new(); - let mut col_del_count = 0u32; - for i in 1..x { - let seed = USER_SEED + i; - let delegator = create_funded_delegator::( - "delegator", - seed, - min_delegator_stk::(), - candidate.clone(), - true, - col_del_count, - )?; - Pallet::::delegate( - RawOrigin::Signed(delegator.clone()).into(), - second_candidate.clone(), - min_delegator_stk::(), - col_del_count, - 1u32, - )?; - Pallet::::schedule_revoke_delegation( - RawOrigin::Signed(delegator.clone()).into(), - candidate.clone() - )?; - delegators.push(delegator); - col_del_count += 1u32; - } - Pallet::::schedule_leave_candidates( - RawOrigin::Signed(candidate.clone()).into(), - 3u32 - )?; - roll_to_and_author::(2, candidate.clone()); - }: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count) - verify { - assert!(Pallet::::candidate_info(&candidate).is_none()); - assert!(Pallet::::candidate_info(&second_candidate).is_some()); - for delegator in delegators { - assert!(Pallet::::is_delegator(&delegator)); - } - } - - cancel_leave_candidates { - let x in 3..1_000; - // Worst Case Complexity is removal from an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let caller: T::AccountId = create_funded_collator::( - "caller", - USER_SEED, - 0u32.into(), - true, - candidate_count, - )?; - candidate_count += 1u32; - Pallet::::schedule_leave_candidates( - RawOrigin::Signed(caller.clone()).into(), - candidate_count - )?; - candidate_count -= 1u32; - }: _(RawOrigin::Signed(caller.clone()), candidate_count) - verify { - assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); - } - - go_offline { - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(!Pallet::::candidate_info(&caller).unwrap().is_active()); - } - - go_online { - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - Pallet::::go_offline(RawOrigin::Signed(caller.clone()).into())?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); - } - - candidate_bond_more { - let more = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - more, - true, - 1u32, - )?; - }: _(RawOrigin::Signed(caller.clone()), more) - verify { - let expected_bond = more * 2u32.into(); - assert_eq!( - Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, - expected_bond, - ); - } - - schedule_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk) - verify { - let state = Pallet::::candidate_info(&caller).expect("request bonded less so exists"); - assert_eq!( - state.request, - Some(CandidateBondLessRequest { - amount: min_candidate_stk, - when_executable: 3, - }) - ); - } - - execute_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - Pallet::::schedule_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - min_candidate_stk - )?; - roll_to_and_author::(2, caller.clone()); - }: { - Pallet::::execute_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - caller.clone() - )?; - } verify { - assert_eq!( - Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, - min_candidate_stk, - ); - } - - cancel_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - Pallet::::schedule_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - min_candidate_stk - )?; - }: { - Pallet::::cancel_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - )?; - } verify { - assert!( - Pallet::::candidate_info(&caller).unwrap().request.is_none() - ); - } - - delegate { - let x in 3..<::MaxDelegationsPerDelegator as Get>::get(); - let y in 2..<::MaxTopDelegationsPerCandidate as Get>::get(); - // Worst Case is full of delegations before calling `delegate` - let mut collators: Vec = Vec::new(); - // Initialize MaxDelegationsPerDelegator collator candidates - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - collators.len() as u32 + 1u32, - )?; - collators.push(collator.clone()); - } - let bond = <::MinDelegatorStk as Get>>::get(); - let extra = if (bond * (collators.len() as u32 + 1u32).into()) > min_candidate_stk::() { - (bond * (collators.len() as u32 + 1u32).into()) - min_candidate_stk::() - } else { - 0u32.into() - }; - let (caller, _) = create_funded_user::("caller", USER_SEED, extra.into()); - // Delegation count - let mut del_del_count = 0u32; - // Nominate MaxDelegationsPerDelegators collator candidates - for col in collators.clone() { - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), col, bond, 0u32, del_del_count - )?; - del_del_count += 1u32; - } - // Last collator to be delegated - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - collators.len() as u32 + 1u32, - )?; - // Worst Case Complexity is insertion into an almost full collator - let mut col_del_count = 0u32; - for i in 1..y { - let seed = USER_SEED + i; - let _ = create_funded_delegator::( - "delegator", - seed, - 0u32.into(), - collator.clone(), - true, - col_del_count, - )?; - col_del_count += 1u32; - } - }: _(RawOrigin::Signed(caller.clone()), collator, bond, col_del_count, del_del_count) - verify { - assert!(Pallet::::is_delegator(&caller)); - } - - schedule_leave_delegators { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!( - Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|r| r.delegator == caller && matches!(r.action, DelegationAction::Revoke(_))) - ); - } - - execute_leave_delegators { - let x in 2..<::MaxDelegationsPerDelegator as Get>::get(); - // Worst Case is full of delegations before execute exit - let mut collators: Vec = Vec::new(); - // Initialize MaxDelegationsPerDelegator collator candidates - for i in 1..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - collators.len() as u32 + 1u32 - )?; - collators.push(collator.clone()); - } - let bond = <::MinDelegatorStk as Get>>::get(); - let need = bond * (collators.len() as u32).into(); - let default_minted = min_candidate_stk::(); - let need: BalanceOf = if need > default_minted { - need - default_minted - } else { - 0u32.into() - }; - // Fund the delegator - let (caller, _) = create_funded_user::("caller", USER_SEED, need); - // Delegation count - let mut delegation_count = 0u32; - let author = collators[0].clone(); - // Nominate MaxDelegationsPerDelegators collator candidates - for col in collators { - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), - col, - bond, - 0u32, - delegation_count - )?; - delegation_count += 1u32; - } - Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; - roll_to_and_author::(2, author); - }: _(RawOrigin::Signed(caller.clone()), caller.clone(), delegation_count) - verify { - assert!(Pallet::::delegator_state(&caller).is_none()); - } - - cancel_leave_delegators { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(Pallet::::delegator_state(&caller).unwrap().is_active()); - } - - schedule_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone()), collator.clone()) - verify { - assert_eq!( - Pallet::::delegation_scheduled_requests(&collator), - vec![ScheduledRequest { - delegator: caller, - when_executable: 3, - action: DelegationAction::Revoke(bond), - }], - ); - } - - delegator_bond_more { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond) - verify { - let expected_bond = bond * 2u32.into(); - assert_eq!( - Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, - expected_bond, - ); - } - - schedule_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond_less) - verify { - let state = Pallet::::delegator_state(&caller) - .expect("just request bonded less so exists"); - assert_eq!( - Pallet::::delegation_scheduled_requests(&collator), - vec![ScheduledRequest { - delegator: caller, - when_executable: 3, - action: DelegationAction::Decrease(bond_less), - }], - ); - } - - execute_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_revoke_delegation(RawOrigin::Signed( - caller.clone()).into(), - collator.clone() - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::execute_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - caller.clone(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::is_delegator(&caller) - ); - } - - execute_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - Pallet::::schedule_delegator_bond_less( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond_less - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::execute_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - caller.clone(), - collator.clone() - )?; - } verify { - let expected = total - bond_less; - assert_eq!( - Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, - expected, - ); - } - - cancel_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_revoke_delegation( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - }: { - Pallet::::cancel_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|x| &x.delegator == &caller) - ); - } - - cancel_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - Pallet::::schedule_delegator_bond_less( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond_less - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::cancel_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|x| &x.delegator == &caller) - ); - } - - // ON_INITIALIZE - - prepare_staking_payouts { - let reward_delay = <::RewardPaymentDelay as Get>::get(); - let round = reward_delay + 2u32; - let payout_round = round - reward_delay; - // may need: - // > - // > - // > - // ensure parachain bond account exists so that deposit_into_existing succeeds - >::insert(payout_round, 100); - >::insert(payout_round, min_candidate_stk::()); - - // set an account in the bond config so that we will measure the payout to it - let account = create_funded_user::( - "parachain_bond", - 0, - min_candidate_stk::(), - ).0; - >::put(ParachainBondConfig { - account, - percent: Percent::from_percent(50), - }); - - }: { Pallet::::prepare_staking_payouts(round); } - verify { - } - - get_rewardable_delegators { - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators - - let high_inflation: Range = Range { - min: Perbill::one(), - ideal: Perbill::one(), - max: Perbill::one(), - }; - Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; - Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; - - let collator = create_funded_collator::( - "collator", - 0, - min_candidate_stk::() * 1_000_000u32.into(), - true, - 1, - )?; - - // create delegators - for i in 0..y { - let seed = USER_SEED + i + 1; - let delegator = create_funded_delegator::( - "delegator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - collator.clone(), - true, - i, - )?; - } - - let mut _results = None; - - }: { _results = Some(Pallet::::get_rewardable_delegators(&collator)); } - verify { - let counted_delegations = _results.expect("get_rewardable_delegators returned some results"); - assert!(counted_delegations.uncounted_stake == 0u32.into()); - assert!(counted_delegations.rewardable_delegations.len() as u32 == y); - let top_delegations = >::get(collator.clone()) - .expect("delegations were set for collator through delegate() calls"); - assert!(top_delegations.delegations.len() as u32 == y); - } - - select_top_candidates { - let x in 0..50; // num collators - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators - - let high_inflation: Range = Range { - min: Perbill::one(), - ideal: Perbill::one(), - max: Perbill::one(), - }; - Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; - Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; - - let mut seed = USER_SEED + 1; - - for _ in 0..x { - let collator = create_funded_collator::( - "collator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - true, - 999999, - )?; - seed += 1; - - // create delegators - for _ in 0..y { - let delegator = create_funded_delegator::( - "delegator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - collator.clone(), - true, - 9999999, - )?; - seed += 1; - } - } - - }: { Some(Pallet::::select_top_candidates(1)); } - verify { - } - - pay_one_collator_reward { - // y controls number of delegations, its maximum per collator is the max top delegations - let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); - - // must come after 'let foo in 0..` statements for macro - use crate::{ - DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points, - AwardedPts, - }; - - let before_running_round_index = Pallet::::round().current; - let initial_stake_amount = min_candidate_stk::() * 1_000_000u32.into(); - - let mut total_staked = 0u32.into(); - - // initialize our single collator - let sole_collator = create_funded_collator::( - "collator", - 0, - initial_stake_amount, - true, - 1u32, - )?; - total_staked += initial_stake_amount; - - // generate funded collator accounts - let mut delegators: Vec = Vec::new(); - for i in 0..y { - let seed = USER_SEED + i; - let delegator = create_funded_delegator::( - "delegator", - seed, - initial_stake_amount, - sole_collator.clone(), - true, - delegators.len() as u32, - )?; - delegators.push(delegator); - total_staked += initial_stake_amount; - } - - // rather than roll through rounds in order to initialize the storage we want, we set it - // directly and then call pay_one_collator_reward directly. - - let round_for_payout = 5; - >::insert(&round_for_payout, DelayedPayout { - // NOTE: round_issuance is not correct here, but it doesn't seem to cause problems - round_issuance: 1000u32.into(), - total_staking_reward: total_staked, - collator_commission: Perbill::from_rational(1u32, 100u32), - }); - - let mut delegations: Vec>> = Vec::new(); - for delegator in &delegators { - delegations.push(BondWithAutoCompound { - owner: delegator.clone(), - amount: 100u32.into(), - auto_compound: Percent::zero(), - }); - } - - >::insert(round_for_payout, &sole_collator, CollatorSnapshot { - bond: 1_000u32.into(), - delegations, - total: 1_000_000u32.into(), - }); - - >::insert(round_for_payout, 100); - >::insert(round_for_payout, &sole_collator, 20); - - }: { - let round_for_payout = 5; - // TODO: this is an extra read right here (we should whitelist it?) - let payout_info = Pallet::::delayed_payouts(round_for_payout).expect("payout expected"); - let result = Pallet::::pay_one_collator_reward(round_for_payout, payout_info); - // TODO: how to keep this in scope so it can be done in verify block? - assert!(matches!(result.0, RewardPayment::Paid)); - } - verify { - // collator should have been paid - assert!( - T::Currency::free_balance(&sole_collator) > initial_stake_amount, - "collator should have been paid in pay_one_collator_reward" - ); - // nominators should have been paid - for delegator in &delegators { - assert!( - T::Currency::free_balance(&delegator) > initial_stake_amount, - "delegator should have been paid in pay_one_collator_reward" - ); - } - } - - base_on_initialize { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let start = >::block_number(); - parachain_staking_on_finalize::(collator.clone()); - >::on_finalize(start); - >::set_block_number( - start + 1u32.into() - ); - let end = >::block_number(); - >::on_initialize(end); - }: { Pallet::::on_initialize(end); } - verify { - // Round transitions - assert_eq!(start + 1u32.into(), end); - } - - set_auto_compound { - // x controls number of distinct auto-compounding delegations the prime collator will have - // y controls number of distinct delegations the prime delegator will have - let x in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); - - use crate::auto_compound::AutoCompoundDelegations; - - let min_candidate_stake = min_candidate_stk::(); - let min_delegator_stake = min_delegator_stk::(); - let mut seed = Seed::new(); - - // initialize the prime collator - let prime_candidate = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - 1, - )?; - - // initialize the prime delegator - let prime_delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake * (y+1).into(), - prime_candidate.clone(), - true, - 0, - )?; - - // have x-1 distinct auto-compounding delegators delegate to prime collator - // we directly set the storage, since benchmarks don't work when the same extrinsic is - // called from within the benchmark. - let mut auto_compounding_state = >::get_storage(&prime_candidate); - for i in 1..x { - let delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake, - prime_candidate.clone(), - true, - i, - )?; - auto_compounding_state.set_for_delegator( - delegator, - Percent::from_percent(100), - ); - } - auto_compounding_state.set_storage(&prime_candidate); - - // delegate to y-1 distinct collators from the prime delegator - for i in 1..y { - let collator = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - i+1, - )?; - Pallet::::delegate( - RawOrigin::Signed(prime_delegator.clone()).into(), - collator, - min_delegator_stake, - 0, - i, - )?; - } - }: { - Pallet::::set_auto_compound( - RawOrigin::Signed(prime_delegator.clone()).into(), - prime_candidate.clone(), - Percent::from_percent(50), - x, - y+1, - )?; - } - verify { - let actual_auto_compound = >::get_storage(&prime_candidate) - .get_for_delegator(&prime_delegator); - let expected_auto_compound = Some(Percent::from_percent(50)); - assert_eq!( - expected_auto_compound, - actual_auto_compound, - "delegation must have an auto-compound entry", - ); - } - - delegate_with_auto_compound { - // x controls number of distinct delegations the prime collator will have - // y controls number of distinct auto-compounding delegations the prime collator will have - // z controls number of distinct delegations the prime delegator will have - let x in 0..(<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get()); - let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get(); - let z in 0..<::MaxDelegationsPerDelegator as Get>::get(); - - use crate::auto_compound::AutoCompoundDelegations; - - let min_candidate_stake = min_candidate_stk::(); - let min_delegator_stake = min_delegator_stk::(); - let mut seed = Seed::new(); - - // initialize the prime collator - let prime_candidate = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - 1, - )?; - - // initialize the future delegator - let (prime_delegator, _) = create_funded_user::( - "delegator", - seed.take(), - min_delegator_stake * (z+1).into(), - ); - - // have x-1 distinct delegators delegate to prime collator, of which y are auto-compounding. - // we can directly set the storage here. - let auto_compound_z = x * y / 100; - for i in 1..x { - let delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake, - prime_candidate.clone(), - true, - i, - )?; - if i <= y { - Pallet::::set_auto_compound( - RawOrigin::Signed(delegator.clone()).into(), - prime_candidate.clone(), - Percent::from_percent(100), - i+1, - i, - )?; - } - } - - // delegate to z-1 distinct collators from the prime delegator - for i in 1..z { - let collator = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - i+1, - )?; - Pallet::::delegate( - RawOrigin::Signed(prime_delegator.clone()).into(), - collator, - min_delegator_stake, - 0, - i, - )?; - } - }: { - Pallet::::delegate_with_auto_compound( - RawOrigin::Signed(prime_delegator.clone()).into(), - prime_candidate.clone(), - min_delegator_stake, - Percent::from_percent(50), - x, - y, - z, - )?; - } - verify { - assert!(Pallet::::is_delegator(&prime_delegator)); - let actual_auto_compound = >::get_storage(&prime_candidate) - .get_for_delegator(&prime_delegator); - let expected_auto_compound = Some(Percent::from_percent(50)); - assert_eq!( - expected_auto_compound, - actual_auto_compound, - "delegation must have an auto-compound entry", - ); - } - - mint_collator_reward { - let mut seed = Seed::new(); - let collator = create_funded_collator::( - "collator", - seed.take(), - 0u32.into(), - true, - 1, - )?; - let original_free_balance = T::Currency::free_balance(&collator); - }: { - Pallet::::mint_collator_reward(1u32.into(), collator.clone(), 50u32.into()) - } - verify { - assert_eq!(T::Currency::free_balance(&collator), original_free_balance + 50u32.into()); - } + // MONETARY ORIGIN DISPATCHABLES + set_staking_expectations { + let stake_range: Range> = Range { + min: 100u32.into(), + ideal: 200u32.into(), + max: 300u32.into(), + }; + }: _(RawOrigin::Root, stake_range) + verify { + assert_eq!(Pallet::::inflation_config().expect, stake_range); + } + + set_inflation { + let inflation_range: Range = Range { + min: Perbill::from_perthousand(1), + ideal: Perbill::from_perthousand(2), + max: Perbill::from_perthousand(3), + }; + + }: _(RawOrigin::Root, inflation_range) + verify { + assert_eq!(Pallet::::inflation_config().annual, inflation_range); + } + + set_parachain_bond_account { + let parachain_bond_account: T::AccountId = account("TEST", 0u32, USER_SEED); + }: _(RawOrigin::Root, parachain_bond_account.clone()) + verify { + assert_eq!(Pallet::::parachain_bond_info().account, parachain_bond_account); + } + + set_parachain_bond_reserve_percent { + }: _(RawOrigin::Root, Percent::from_percent(33)) + verify { + assert_eq!(Pallet::::parachain_bond_info().percent, Percent::from_percent(33)); + } + + // ROOT DISPATCHABLES + + set_total_selected { + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; + }: _(RawOrigin::Root, 100u32) + verify { + assert_eq!(Pallet::::total_selected(), 100u32); + } + + set_collator_commission {}: _(RawOrigin::Root, Perbill::from_percent(33)) + verify { + assert_eq!(Pallet::::collator_commission(), Perbill::from_percent(33)); + } + + set_blocks_per_round {}: _(RawOrigin::Root, 1200u32) + verify { + assert_eq!(Pallet::::round().length, 1200u32); + } + + // USER DISPATCHABLES + + join_candidates { + let x in 3..1_000; + // Worst Case Complexity is insertion into an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let (caller, min_candidate_stk) = create_funded_user::("caller", USER_SEED, 0u32.into()); + }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk, candidate_count) + verify { + assert!(Pallet::::is_candidate(&caller)); + } + + // This call schedules the collator's exit and removes them from the candidate pool + // -> it retains the self-bond and delegator bonds + schedule_leave_candidates { + let x in 3..1_000; + // Worst Case Complexity is removal from an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let caller: T::AccountId = create_funded_collator::( + "caller", + USER_SEED, + 0u32.into(), + true, + candidate_count, + )?; + candidate_count += 1u32; + }: _(RawOrigin::Signed(caller.clone()), candidate_count) + verify { + assert!(Pallet::::candidate_info(&caller).unwrap().is_leaving()); + } + + execute_leave_candidates { + // x is total number of delegations for the candidate + let x in 2..(<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get()); + let candidate: T::AccountId = create_funded_collator::( + "unique_caller", + USER_SEED - 100, + 0u32.into(), + true, + 1u32, + )?; + // 2nd delegation required for all delegators to ensure DelegatorState updated not removed + let second_candidate: T::AccountId = create_funded_collator::( + "unique__caller", + USER_SEED - 99, + 0u32.into(), + true, + 2u32, + )?; + let mut delegators: Vec = Vec::new(); + let mut col_del_count = 0u32; + for i in 1..x { + let seed = USER_SEED + i; + let delegator = create_funded_delegator::( + "delegator", + seed, + min_delegator_stk::(), + candidate.clone(), + true, + col_del_count, + )?; + Pallet::::delegate( + RawOrigin::Signed(delegator.clone()).into(), + second_candidate.clone(), + min_delegator_stk::(), + col_del_count, + 1u32, + )?; + Pallet::::schedule_revoke_delegation( + RawOrigin::Signed(delegator.clone()).into(), + candidate.clone() + )?; + delegators.push(delegator); + col_del_count += 1u32; + } + Pallet::::schedule_leave_candidates( + RawOrigin::Signed(candidate.clone()).into(), + 3u32 + )?; + roll_to_and_author::(2, candidate.clone()); + }: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count) + verify { + assert!(Pallet::::candidate_info(&candidate).is_none()); + assert!(Pallet::::candidate_info(&second_candidate).is_some()); + for delegator in delegators { + assert!(Pallet::::is_delegator(&delegator)); + } + } + + cancel_leave_candidates { + let x in 3..1_000; + // Worst Case Complexity is removal from an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let caller: T::AccountId = create_funded_collator::( + "caller", + USER_SEED, + 0u32.into(), + true, + candidate_count, + )?; + candidate_count += 1u32; + Pallet::::schedule_leave_candidates( + RawOrigin::Signed(caller.clone()).into(), + candidate_count + )?; + candidate_count -= 1u32; + }: _(RawOrigin::Signed(caller.clone()), candidate_count) + verify { + assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); + } + + go_offline { + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(!Pallet::::candidate_info(&caller).unwrap().is_active()); + } + + go_online { + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + Pallet::::go_offline(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); + } + + candidate_bond_more { + let more = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + more, + true, + 1u32, + )?; + }: _(RawOrigin::Signed(caller.clone()), more) + verify { + let expected_bond = more * 2u32.into(); + assert_eq!( + Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, + expected_bond, + ); + } + + schedule_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk) + verify { + let state = Pallet::::candidate_info(&caller).expect("request bonded less so exists"); + assert_eq!( + state.request, + Some(CandidateBondLessRequest { + amount: min_candidate_stk, + when_executable: 3, + }) + ); + } + + execute_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + Pallet::::schedule_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + min_candidate_stk + )?; + roll_to_and_author::(2, caller.clone()); + }: { + Pallet::::execute_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + caller.clone() + )?; + } verify { + assert_eq!( + Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, + min_candidate_stk, + ); + } + + cancel_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + Pallet::::schedule_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + min_candidate_stk + )?; + }: { + Pallet::::cancel_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + )?; + } verify { + assert!( + Pallet::::candidate_info(&caller).unwrap().request.is_none() + ); + } + + delegate { + let x in 3..<::MaxDelegationsPerDelegator as Get>::get(); + let y in 2..<::MaxTopDelegationsPerCandidate as Get>::get(); + // Worst Case is full of delegations before calling `delegate` + let mut collators: Vec = Vec::new(); + // Initialize MaxDelegationsPerDelegator collator candidates + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + collators.len() as u32 + 1u32, + )?; + collators.push(collator.clone()); + } + let bond = <::MinDelegatorStk as Get>>::get(); + let extra = if (bond * (collators.len() as u32 + 1u32).into()) > min_candidate_stk::() { + (bond * (collators.len() as u32 + 1u32).into()) - min_candidate_stk::() + } else { + 0u32.into() + }; + let (caller, _) = create_funded_user::("caller", USER_SEED, extra); + // Delegation count + let mut del_del_count = 0u32; + // Nominate MaxDelegationsPerDelegators collator candidates + for col in collators.clone() { + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), col, bond, 0u32, del_del_count + )?; + del_del_count += 1u32; + } + // Last collator to be delegated + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + collators.len() as u32 + 1u32, + )?; + // Worst Case Complexity is insertion into an almost full collator + let mut col_del_count = 0u32; + for i in 1..y { + let seed = USER_SEED + i; + let _ = create_funded_delegator::( + "delegator", + seed, + 0u32.into(), + collator.clone(), + true, + col_del_count, + )?; + col_del_count += 1u32; + } + }: _(RawOrigin::Signed(caller.clone()), collator, bond, col_del_count, del_del_count) + verify { + assert!(Pallet::::is_delegator(&caller)); + } + + schedule_leave_delegators { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!( + Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|r| r.delegator == caller && matches!(r.action, DelegationAction::Revoke(_))) + ); + } + + execute_leave_delegators { + let x in 2..<::MaxDelegationsPerDelegator as Get>::get(); + // Worst Case is full of delegations before execute exit + let mut collators: Vec = Vec::new(); + // Initialize MaxDelegationsPerDelegator collator candidates + for i in 1..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + collators.len() as u32 + 1u32 + )?; + collators.push(collator.clone()); + } + let bond = <::MinDelegatorStk as Get>>::get(); + let need = bond * (collators.len() as u32).into(); + let default_minted = min_candidate_stk::(); + let need: BalanceOf = if need > default_minted { + need - default_minted + } else { + 0u32.into() + }; + // Fund the delegator + let (caller, _) = create_funded_user::("caller", USER_SEED, need); + // Delegation count + let mut delegation_count = 0u32; + let author = collators[0].clone(); + // Nominate MaxDelegationsPerDelegators collator candidates + for col in collators { + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), + col, + bond, + 0u32, + delegation_count + )?; + delegation_count += 1u32; + } + Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; + roll_to_and_author::(2, author); + }: _(RawOrigin::Signed(caller.clone()), caller.clone(), delegation_count) + verify { + assert!(Pallet::::delegator_state(&caller).is_none()); + } + + cancel_leave_delegators { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator, + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(Pallet::::delegator_state(&caller).unwrap().is_active()); + } + + schedule_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone()), collator.clone()) + verify { + assert_eq!( + Pallet::::delegation_scheduled_requests(&collator), + vec![ScheduledRequest { + delegator: caller, + when_executable: 3, + action: DelegationAction::Revoke(bond), + }], + ); + } + + delegator_bond_more { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone()), collator, bond) + verify { + let expected_bond = bond * 2u32.into(); + assert_eq!( + Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, + expected_bond, + ); + } + + schedule_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond_less) + verify { + let state = Pallet::::delegator_state(&caller) + .expect("just request bonded less so exists"); + assert_eq!( + Pallet::::delegation_scheduled_requests(&collator), + vec![ScheduledRequest { + delegator: caller, + when_executable: 3, + action: DelegationAction::Decrease(bond_less), + }], + ); + } + + execute_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_revoke_delegation(RawOrigin::Signed( + caller.clone()).into(), + collator.clone() + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::execute_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + caller.clone(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::is_delegator(&caller) + ); + } + + execute_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + Pallet::::schedule_delegator_bond_less( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond_less + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::execute_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + caller.clone(), + collator.clone() + )?; + } verify { + let expected = total - bond_less; + assert_eq!( + Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, + expected, + ); + } + + cancel_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_revoke_delegation( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + }: { + Pallet::::cancel_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|x| x.delegator == caller) + ); + } + + cancel_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + Pallet::::schedule_delegator_bond_less( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond_less + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::cancel_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|x| x.delegator == caller) + ); + } + + // ON_INITIALIZE + + prepare_staking_payouts { + let reward_delay = <::RewardPaymentDelay as Get>::get(); + let round = reward_delay + 2u32; + let payout_round = round - reward_delay; + // may need: + // > + // > + // > + // ensure parachain bond account exists so that deposit_into_existing succeeds + >::insert(payout_round, 100); + >::insert(payout_round, min_candidate_stk::()); + + // set an account in the bond config so that we will measure the payout to it + let account = create_funded_user::( + "parachain_bond", + 0, + min_candidate_stk::(), + ).0; + >::put(ParachainBondConfig { + account, + percent: Percent::from_percent(50), + }); + + }: { Pallet::::prepare_staking_payouts(round); } + verify { + } + + get_rewardable_delegators { + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators + + let high_inflation: Range = Range { + min: Perbill::one(), + ideal: Perbill::one(), + max: Perbill::one(), + }; + Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation)?; + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; + Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; + + let collator = create_funded_collator::( + "collator", + 0, + min_candidate_stk::() * 1_000_000u32.into(), + true, + 1, + )?; + + // create delegators + for i in 0..y { + let seed = USER_SEED + i + 1; + let delegator = create_funded_delegator::( + "delegator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + collator.clone(), + true, + i, + )?; + } + + let mut _results = None; + + }: { _results = Some(Pallet::::get_rewardable_delegators(&collator)); } + verify { + let counted_delegations = _results.expect("get_rewardable_delegators returned some results"); + assert!(counted_delegations.uncounted_stake == 0u32.into()); + assert!(counted_delegations.rewardable_delegations.len() as u32 == y); + let top_delegations = >::get(collator.clone()) + .expect("delegations were set for collator through delegate() calls"); + assert!(top_delegations.delegations.len() as u32 == y); + } + + select_top_candidates { + let x in 0..50; // num collators + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators + + let high_inflation: Range = Range { + min: Perbill::one(), + ideal: Perbill::one(), + max: Perbill::one(), + }; + Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation)?; + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; + Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; + + let mut seed = USER_SEED + 1; + + for _ in 0..x { + let collator = create_funded_collator::( + "collator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + true, + 999999, + )?; + seed += 1; + + // create delegators + for _ in 0..y { + let delegator = create_funded_delegator::( + "delegator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + collator.clone(), + true, + 9999999, + )?; + seed += 1; + } + } + + }: { Pallet::::select_top_candidates(1); } + verify { + } + + pay_one_collator_reward { + // y controls number of delegations, its maximum per collator is the max top delegations + let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); + + // must come after 'let foo in 0..` statements for macro + use crate::{ + DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points, + AwardedPts, + }; + + let before_running_round_index = Pallet::::round().current; + let initial_stake_amount = min_candidate_stk::() * 1_000_000u32.into(); + + let mut total_staked = 0u32.into(); + + // initialize our single collator + let sole_collator = create_funded_collator::( + "collator", + 0, + initial_stake_amount, + true, + 1u32, + )?; + total_staked += initial_stake_amount; + + // generate funded collator accounts + let mut delegators: Vec = Vec::new(); + for i in 0..y { + let seed = USER_SEED + i; + let delegator = create_funded_delegator::( + "delegator", + seed, + initial_stake_amount, + sole_collator.clone(), + true, + delegators.len() as u32, + )?; + delegators.push(delegator); + total_staked += initial_stake_amount; + } + + // rather than roll through rounds in order to initialize the storage we want, we set it + // directly and then call pay_one_collator_reward directly. + + let round_for_payout = 5; + >::insert(round_for_payout, DelayedPayout { + // NOTE: round_issuance is not correct here, but it doesn't seem to cause problems + round_issuance: 1000u32.into(), + total_staking_reward: total_staked, + collator_commission: Perbill::from_rational(1u32, 100u32), + }); + + let mut delegations: Vec>> = Vec::new(); + for delegator in &delegators { + delegations.push(BondWithAutoCompound { + owner: delegator.clone(), + amount: 100u32.into(), + auto_compound: Percent::zero(), + }); + } + + >::insert(round_for_payout, &sole_collator, CollatorSnapshot { + bond: 1_000u32.into(), + delegations, + total: 1_000_000u32.into(), + }); + + >::insert(round_for_payout, 100); + >::insert(round_for_payout, &sole_collator, 20); + + }: { + let round_for_payout = 5; + // TODO: this is an extra read right here (we should whitelist it?) + let payout_info = Pallet::::delayed_payouts(round_for_payout).expect("payout expected"); + let result = Pallet::::pay_one_collator_reward(round_for_payout, payout_info); + // TODO: how to keep this in scope so it can be done in verify block? + assert!(matches!(result.0, RewardPayment::Paid)); + } + verify { + // collator should have been paid + assert!( + T::Currency::free_balance(&sole_collator) > initial_stake_amount, + "collator should have been paid in pay_one_collator_reward" + ); + // nominators should have been paid + for delegator in &delegators { + assert!( + T::Currency::free_balance(delegator) > initial_stake_amount, + "delegator should have been paid in pay_one_collator_reward" + ); + } + } + + base_on_initialize { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let start = >::block_number(); + parachain_staking_on_finalize::(collator); + >::on_finalize(start); + >::set_block_number( + start + 1u32.into() + ); + let end = >::block_number(); + >::on_initialize(end); + }: { Pallet::::on_initialize(end); } + verify { + // Round transitions + assert_eq!(start + 1u32.into(), end); + } + + set_auto_compound { + // x controls number of distinct auto-compounding delegations the prime collator will have + // y controls number of distinct delegations the prime delegator will have + let x in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); + + use crate::auto_compound::AutoCompoundDelegations; + + let min_candidate_stake = min_candidate_stk::(); + let min_delegator_stake = min_delegator_stk::(); + let mut seed = Seed::new(); + + // initialize the prime collator + let prime_candidate = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + 1, + )?; + + // initialize the prime delegator + let prime_delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake * (y+1).into(), + prime_candidate.clone(), + true, + 0, + )?; + + // have x-1 distinct auto-compounding delegators delegate to prime collator + // we directly set the storage, since benchmarks don't work when the same extrinsic is + // called from within the benchmark. + let mut auto_compounding_state = >::get_storage(&prime_candidate); + for i in 1..x { + let delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake, + prime_candidate.clone(), + true, + i, + )?; + auto_compounding_state.set_for_delegator( + delegator, + Percent::from_percent(100), + ); + } + auto_compounding_state.set_storage(&prime_candidate); + + // delegate to y-1 distinct collators from the prime delegator + for i in 1..y { + let collator = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + i+1, + )?; + Pallet::::delegate( + RawOrigin::Signed(prime_delegator.clone()).into(), + collator, + min_delegator_stake, + 0, + i, + )?; + } + }: { + Pallet::::set_auto_compound( + RawOrigin::Signed(prime_delegator.clone()).into(), + prime_candidate.clone(), + Percent::from_percent(50), + x, + y+1, + )?; + } + verify { + let actual_auto_compound = >::get_storage(&prime_candidate) + .get_for_delegator(&prime_delegator); + let expected_auto_compound = Some(Percent::from_percent(50)); + assert_eq!( + expected_auto_compound, + actual_auto_compound, + "delegation must have an auto-compound entry", + ); + } + + delegate_with_auto_compound { + // x controls number of distinct delegations the prime collator will have + // y controls number of distinct auto-compounding delegations the prime collator will have + // z controls number of distinct delegations the prime delegator will have + let x in 0..(<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get()); + let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get(); + let z in 0..<::MaxDelegationsPerDelegator as Get>::get(); + + use crate::auto_compound::AutoCompoundDelegations; + + let min_candidate_stake = min_candidate_stk::(); + let min_delegator_stake = min_delegator_stk::(); + let mut seed = Seed::new(); + + // initialize the prime collator + let prime_candidate = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + 1, + )?; + + // initialize the future delegator + let (prime_delegator, _) = create_funded_user::( + "delegator", + seed.take(), + min_delegator_stake * (z+1).into(), + ); + + // have x-1 distinct delegators delegate to prime collator, of which y are auto-compounding. + // we can directly set the storage here. + let auto_compound_z = x * y / 100; + for i in 1..x { + let delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake, + prime_candidate.clone(), + true, + i, + )?; + if i <= y { + Pallet::::set_auto_compound( + RawOrigin::Signed(delegator.clone()).into(), + prime_candidate.clone(), + Percent::from_percent(100), + i+1, + i, + )?; + } + } + + // delegate to z-1 distinct collators from the prime delegator + for i in 1..z { + let collator = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + i+1, + )?; + Pallet::::delegate( + RawOrigin::Signed(prime_delegator.clone()).into(), + collator, + min_delegator_stake, + 0, + i, + )?; + } + }: { + Pallet::::delegate_with_auto_compound( + RawOrigin::Signed(prime_delegator.clone()).into(), + prime_candidate.clone(), + min_delegator_stake, + Percent::from_percent(50), + x, + y, + z, + )?; + } + verify { + assert!(Pallet::::is_delegator(&prime_delegator)); + let actual_auto_compound = >::get_storage(&prime_candidate) + .get_for_delegator(&prime_delegator); + let expected_auto_compound = Some(Percent::from_percent(50)); + assert_eq!( + expected_auto_compound, + actual_auto_compound, + "delegation must have an auto-compound entry", + ); + } + + mint_collator_reward { + let mut seed = Seed::new(); + let collator = create_funded_collator::( + "collator", + seed.take(), + 0u32.into(), + true, + 1, + )?; + let original_free_balance = T::Currency::free_balance(&collator); + }: { + Pallet::::mint_collator_reward(1u32, collator.clone(), 50u32.into()) + } + verify { + assert_eq!(T::Currency::free_balance(&collator), original_free_balance + 50u32.into()); + } } #[cfg(test)] mod tests { - use crate::benchmarks::*; - use crate::mock::Test; - use frame_support::assert_ok; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - TestExternalities::new(t) - } - - #[test] - fn bench_set_staking_expectations() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_staking_expectations()); - }); - } - - #[test] - fn bench_set_inflation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_inflation()); - }); - } - - #[test] - fn bench_set_parachain_bond_account() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_parachain_bond_account()); - }); - } - - #[test] - fn bench_set_parachain_bond_reserve_percent() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_parachain_bond_reserve_percent()); - }); - } - - #[test] - fn bench_set_total_selected() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_total_selected()); - }); - } - - #[test] - fn bench_set_collator_commission() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_collator_commission()); - }); - } - - #[test] - fn bench_set_blocks_per_round() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_blocks_per_round()); - }); - } - - #[test] - fn bench_join_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_join_candidates()); - }); - } - - #[test] - fn bench_schedule_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_leave_candidates()); - }); - } - - #[test] - fn bench_execute_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_leave_candidates()); - }); - } - - #[test] - fn bench_cancel_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_leave_candidates()); - }); - } - - #[test] - fn bench_go_offline() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_go_offline()); - }); - } - - #[test] - fn bench_go_online() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_go_online()); - }); - } - - #[test] - fn bench_candidate_bond_more() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_candidate_bond_more()); - }); - } - - #[test] - fn bench_schedule_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_candidate_bond_less()); - }); - } - - #[test] - fn bench_execute_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_candidate_bond_less()); - }); - } - - #[test] - fn bench_cancel_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_candidate_bond_less()); - }); - } - - #[test] - fn bench_delegate() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_delegate()); - }); - } - - #[test] - fn bench_schedule_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_leave_delegators()); - }); - } - - #[test] - fn bench_execute_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_leave_delegators()); - }); - } - - #[test] - fn bench_cancel_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_leave_delegators()); - }); - } - - #[test] - fn bench_schedule_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_revoke_delegation()); - }); - } - - #[test] - fn bench_delegator_bond_more() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_delegator_bond_more()); - }); - } - - #[test] - fn bench_schedule_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_delegator_bond_less()); - }); - } - - #[test] - fn bench_execute_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_revoke_delegation()); - }); - } - - #[test] - fn bench_execute_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_delegator_bond_less()); - }); - } - - #[test] - fn bench_cancel_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_revoke_delegation()); - }); - } - - #[test] - fn bench_cancel_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_delegator_bond_less()); - }); - } - - #[test] - fn bench_base_on_initialize() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_base_on_initialize()); - }); - } + use crate::{benchmarks::*, mock::Test}; + use frame_support::assert_ok; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t) + } + + #[test] + fn bench_set_staking_expectations() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_staking_expectations()); + }); + } + + #[test] + fn bench_set_inflation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_inflation()); + }); + } + + #[test] + fn bench_set_parachain_bond_account() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_parachain_bond_account()); + }); + } + + #[test] + fn bench_set_parachain_bond_reserve_percent() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_parachain_bond_reserve_percent()); + }); + } + + #[test] + fn bench_set_total_selected() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_total_selected()); + }); + } + + #[test] + fn bench_set_collator_commission() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_collator_commission()); + }); + } + + #[test] + fn bench_set_blocks_per_round() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_blocks_per_round()); + }); + } + + #[test] + fn bench_join_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_join_candidates()); + }); + } + + #[test] + fn bench_schedule_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_leave_candidates()); + }); + } + + #[test] + fn bench_execute_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_leave_candidates()); + }); + } + + #[test] + fn bench_cancel_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_leave_candidates()); + }); + } + + #[test] + fn bench_go_offline() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_go_offline()); + }); + } + + #[test] + fn bench_go_online() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_go_online()); + }); + } + + #[test] + fn bench_candidate_bond_more() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_candidate_bond_more()); + }); + } + + #[test] + fn bench_schedule_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_candidate_bond_less()); + }); + } + + #[test] + fn bench_execute_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_candidate_bond_less()); + }); + } + + #[test] + fn bench_cancel_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_candidate_bond_less()); + }); + } + + #[test] + fn bench_delegate() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_delegate()); + }); + } + + #[test] + fn bench_schedule_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_leave_delegators()); + }); + } + + #[test] + fn bench_execute_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_leave_delegators()); + }); + } + + #[test] + fn bench_cancel_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_leave_delegators()); + }); + } + + #[test] + fn bench_schedule_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_revoke_delegation()); + }); + } + + #[test] + fn bench_delegator_bond_more() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_delegator_bond_more()); + }); + } + + #[test] + fn bench_schedule_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_delegator_bond_less()); + }); + } + + #[test] + fn bench_execute_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_revoke_delegation()); + }); + } + + #[test] + fn bench_execute_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_delegator_bond_less()); + }); + } + + #[test] + fn bench_cancel_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_revoke_delegation()); + }); + } + + #[test] + fn bench_cancel_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_delegator_bond_less()); + }); + } + + #[test] + fn bench_base_on_initialize() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_base_on_initialize()); + }); + } } -impl_benchmark_test_suite!( - Pallet, - crate::benchmarks::tests::new_test_ext(), - crate::mock::Test -); +impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Test); diff --git a/external/pallets/parachain-staking/src/delegation_requests.rs b/external/pallets/parachain-staking/src/delegation_requests.rs index 6ca5e6411..ce454a3aa 100644 --- a/external/pallets/parachain-staking/src/delegation_requests.rs +++ b/external/pallets/parachain-staking/src/delegation_requests.rs @@ -16,14 +16,15 @@ //! Scheduled requests functionality for delegators -use crate::pallet::{ - BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, Event, - Pallet, Round, RoundIndex, Total, +use crate::{ + auto_compound::AutoCompoundDelegations, + pallet::{ + BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, + Event, Pallet, Round, RoundIndex, Total, + }, + Delegator, DelegatorStatus, }; -use crate::{auto_compound::AutoCompoundDelegations, Delegator, DelegatorStatus}; -use frame_support::ensure; -use frame_support::traits::Get; -use frame_support::{dispatch::DispatchResultWithPostInfo, RuntimeDebug}; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::traits::Saturating; @@ -32,673 +33,615 @@ use sp_std::{vec, vec::Vec}; /// An action that can be performed upon a delegation #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] pub enum DelegationAction { - Revoke(Balance), - Decrease(Balance), + Revoke(Balance), + Decrease(Balance), } impl DelegationAction { - /// Returns the wrapped amount value. - pub fn amount(&self) -> Balance { - match self { - DelegationAction::Revoke(amount) => *amount, - DelegationAction::Decrease(amount) => *amount, - } - } + /// Returns the wrapped amount value. + pub fn amount(&self) -> Balance { + match self { + DelegationAction::Revoke(amount) => *amount, + DelegationAction::Decrease(amount) => *amount, + } + } } /// Represents a scheduled request that define a [DelegationAction]. The request is executable /// iff the provided [RoundIndex] is achieved. #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] pub struct ScheduledRequest { - pub delegator: AccountId, - pub when_executable: RoundIndex, - pub action: DelegationAction, + pub delegator: AccountId, + pub when_executable: RoundIndex, + pub action: DelegationAction, } /// Represents a cancelled scheduled request for emitting an event. #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct CancelledScheduledRequest { - pub when_executable: RoundIndex, - pub action: DelegationAction, + pub when_executable: RoundIndex, + pub action: DelegationAction, } impl From> for CancelledScheduledRequest { - fn from(request: ScheduledRequest) -> Self { - CancelledScheduledRequest { - when_executable: request.when_executable, - action: request.action, - } - } + fn from(request: ScheduledRequest) -> Self { + CancelledScheduledRequest { + when_executable: request.when_executable, + action: request.action, + } + } } impl Pallet { - /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. - pub(crate) fn delegation_schedule_revoke( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - ensure!( - !scheduled_requests - .iter() - .any(|req| req.delegator == delegator), - >::PendingDelegationRequestAlreadyExists, - ); - - let bonded_amount = state - .get_bond_amount(&collator) - .ok_or(>::DelegationDNE)?; - let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); - scheduled_requests.push(ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Revoke(bonded_amount), - when_executable: when, - }); - state.less_total = state.less_total.saturating_add(bonded_amount); - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::DelegationRevocationScheduled { - round: now, - delegator, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Schedules a [DelegationAction::Decrease] for the delegator, towards a given collator. - pub(crate) fn delegation_schedule_bond_decrease( - collator: T::AccountId, - delegator: T::AccountId, - decrease_amount: BalanceOf, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - ensure!( - !scheduled_requests - .iter() - .any(|req| req.delegator == delegator), - >::PendingDelegationRequestAlreadyExists, - ); - - let bonded_amount = state - .get_bond_amount(&collator) - .ok_or(>::DelegationDNE)?; - ensure!( - bonded_amount > decrease_amount, - >::DelegatorBondBelowMin - ); - let new_amount: BalanceOf = (bonded_amount - decrease_amount).into(); - ensure!( - new_amount >= T::MinDelegation::get(), - >::DelegationBelowMin - ); - - // Net Total is total after pending orders are executed - let net_total = state.total().saturating_sub(state.less_total); - // Net Total is always >= MinDelegatorStk - let max_subtracted_amount = net_total.saturating_sub(T::MinDelegatorStk::get().into()); - ensure!( - decrease_amount <= max_subtracted_amount, - >::DelegatorBondBelowMin - ); - - let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); - scheduled_requests.push(ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Decrease(decrease_amount), - when_executable: when, - }); - state.less_total = state.less_total.saturating_add(decrease_amount); - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::DelegationDecreaseScheduled { - delegator, - candidate: collator, - amount_to_decrease: decrease_amount, - execute_round: when, - }); - Ok(().into()) - } - - /// Cancels the delegator's existing [ScheduledRequest] towards a given collator. - pub(crate) fn delegation_cancel_request( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) - .ok_or(>::PendingDelegationRequestDNE)?; - - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::CancelledDelegationRequest { - delegator, - collator, - cancelled_request: request.into(), - }); - Ok(().into()) - } - - fn cancel_request_with_state( - delegator: &T::AccountId, - state: &mut Delegator>, - scheduled_requests: &mut Vec>>, - ) -> Option>> { - let request_idx = scheduled_requests - .iter() - .position(|req| &req.delegator == delegator)?; - - let request = scheduled_requests.remove(request_idx); - let amount = request.action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - Some(request) - } - - /// Executes the delegator's existing [ScheduledRequest] towards a given collator. - pub(crate) fn delegation_execute_scheduled_request( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - let request_idx = scheduled_requests - .iter() - .position(|req| req.delegator == delegator) - .ok_or(>::PendingDelegationRequestDNE)?; - let request = &scheduled_requests[request_idx]; - - let now = >::get().current; - ensure!( - request.when_executable <= now, - >::PendingDelegationRequestNotDueYet - ); - - match request.action { - DelegationAction::Revoke(amount) => { - // revoking last delegation => leaving set of delegators - let leaving = if state.delegations.0.len() == 1usize { - true - } else { - ensure!( - state - .total() - .saturating_sub(T::MinDelegatorStk::get().into()) - >= amount, - >::DelegatorBondBelowMin - ); - false - }; - - // remove from pending requests - let amount = scheduled_requests.remove(request_idx).action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - - // remove delegation from delegator state - state.rm_delegation::(&collator); - - // remove delegation from auto-compounding info - >::remove_auto_compound(&collator, &delegator); - - // remove delegation from collator state delegations - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), amount)?; - Self::deposit_event(Event::DelegationRevoked { - delegator: delegator.clone(), - candidate: collator.clone(), - unstaked_amount: amount, - }); - - >::insert(collator, scheduled_requests); - if leaving { - >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { - delegator, - unstaked_amount: amount, - }); - } else { - >::insert(&delegator, state); - } - Ok(().into()) - } - DelegationAction::Decrease(_) => { - // remove from pending requests - let amount = scheduled_requests.remove(request_idx).action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - - // decrease delegation - for bond in &mut state.delegations.0 { - if bond.owner == collator { - return if bond.amount > amount { - let amount_before: BalanceOf = bond.amount.into(); - bond.amount = bond.amount.saturating_sub(amount); - let mut collator_info = >::get(&collator) - .ok_or(>::CandidateDNE)?; - - state.total_sub_if::(amount, |total| { - let new_total: BalanceOf = total.into(); - ensure!( - new_total >= T::MinDelegation::get(), - >::DelegationBelowMin - ); - ensure!( - new_total >= T::MinDelegatorStk::get(), - >::DelegatorBondBelowMin - ); - - Ok(()) - })?; - - // need to go into decrease_delegation - let in_top = collator_info.decrease_delegation::( - &collator, - delegator.clone(), - amount_before, - amount, - )?; - >::insert(&collator, collator_info); - let new_total_staked = >::get().saturating_sub(amount); - >::put(new_total_staked); - - >::insert( - collator.clone(), - scheduled_requests, - ); - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegationDecreased { - delegator, - candidate: collator.clone(), - amount, - in_top, - }); - Ok(().into()) - } else { - // must rm entire delegation if bond.amount <= less or cancel request - Err(>::DelegationBelowMin.into()) - }; - } - } - Err(>::DelegationDNE.into()) - } - } - } - - /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. - /// The last fulfilled request causes the delegator to leave the set of delegators. - pub(crate) fn delegator_schedule_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut updated_scheduled_requests = vec![]; - let now = >::get().current; - let when = now.saturating_add(T::LeaveDelegatorsDelay::get()); - - // lazy migration for DelegatorStatus::Leaving - #[allow(deprecated)] - if matches!(state.status, DelegatorStatus::Leaving(_)) { - state.status = DelegatorStatus::Active; - >::insert(delegator.clone(), state.clone()); - } - - // it is assumed that a multiple delegations to the same collator does not exist, else this - // will cause a bug - the last duplicate delegation update will be the only one applied. - let mut existing_revoke_count = 0; - for bond in state.delegations.0.clone() { - let collator = bond.owner; - let bonded_amount = bond.amount; - let mut scheduled_requests = >::get(&collator); - - // cancel any existing requests - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); - let request = match request { - Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { - existing_revoke_count += 1; - revoke_req // re-insert the same Revoke request - } - _ => ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Revoke(bonded_amount.clone()), - when_executable: when, - }, - }; - - scheduled_requests.push(request); - state.less_total = state.less_total.saturating_add(bonded_amount); - updated_scheduled_requests.push((collator, scheduled_requests)); - } - - if existing_revoke_count == state.delegations.0.len() { - return Err(>::DelegatorAlreadyLeaving.into()); - } - - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitScheduled { - round: now, - delegator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. - /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be - /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_cancel_scheduled_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut updated_scheduled_requests = vec![]; - - // backwards compatible handling for DelegatorStatus::Leaving - #[allow(deprecated)] - if matches!(state.status, DelegatorStatus::Leaving(_)) { - state.status = DelegatorStatus::Active; - >::insert(delegator.clone(), state.clone()); - Self::deposit_event(Event::DelegatorExitCancelled { delegator }); - return Ok(().into()); - } - - // pre-validate that all delegations have a Revoke request. - for bond in &state.delegations.0 { - let collator = bond.owner.clone(); - let scheduled_requests = >::get(&collator); - scheduled_requests - .iter() - .find(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - .ok_or(>::DelegatorNotLeaving)?; - } - - // cancel all requests - for bond in state.delegations.0.clone() { - let collator = bond.owner.clone(); - let mut scheduled_requests = >::get(&collator); - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); - updated_scheduled_requests.push((collator, scheduled_requests)); - } - - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitCancelled { delegator }); - - Ok(().into()) - } - - /// Executes every [DelegationAction::Revoke] request for a delegator towards a collator. - /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be - /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_execute_scheduled_revoke_all( - delegator: T::AccountId, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - ensure!( - delegation_count >= (state.delegations.0.len() as u32), - Error::::TooLowDelegationCountToLeaveDelegators - ); - let now = >::get().current; - - // backwards compatible handling for DelegatorStatus::Leaving - #[allow(deprecated)] - if let DelegatorStatus::Leaving(when) = state.status { - ensure!( - >::get().current >= when, - Error::::DelegatorCannotLeaveYet - ); - - for bond in state.delegations.0.clone() { - if let Err(error) = Self::delegator_leaves_candidate( - bond.owner.clone(), - delegator.clone(), - bond.amount, - ) { - log::warn!( - "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", - error - ); - } - - Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); - >::remove_auto_compound(&bond.owner, &delegator); - } - >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { - delegator, - unstaked_amount: state.total, - }); - return Ok(().into()); - } - - let mut validated_scheduled_requests = vec![]; - // pre-validate that all delegations have a Revoke request that can be executed now. - for bond in &state.delegations.0 { - let scheduled_requests = >::get(&bond.owner); - let request_idx = scheduled_requests - .iter() - .position(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - .ok_or(>::DelegatorNotLeaving)?; - let request = &scheduled_requests[request_idx]; - - ensure!( - request.when_executable <= now, - >::DelegatorCannotLeaveYet - ); - - validated_scheduled_requests.push((bond.clone(), scheduled_requests, request_idx)) - } - - let mut updated_scheduled_requests = vec![]; - // we do not update the delegator state, since the it will be completely removed - for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { - let collator = bond.owner; - - if let Err(error) = - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) - { - log::warn!( - "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", - delegator, - error - ); - } - - // remove the scheduled request, since it is fulfilled - scheduled_requests.remove(request_idx).action.amount(); - updated_scheduled_requests.push((collator.clone(), scheduled_requests)); - - // remove the auto-compounding entry for the delegation - >::remove_auto_compound(&collator, &delegator); - } - - // set state.total so that state.adjust_bond_lock will remove lock - let unstaked_amount = state.total(); - state.total_sub::(unstaked_amount)?; - - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - Self::deposit_event(Event::DelegatorLeft { - delegator: delegator.clone(), - unstaked_amount, - }); - >::remove(&delegator); - - Ok(().into()) - } - - /// Removes the delegator's existing [ScheduledRequest] towards a given collator, if exists. - /// The state needs to be persisted by the caller of this function. - pub(crate) fn delegation_remove_request_with_state( - collator: &T::AccountId, - delegator: &T::AccountId, - state: &mut Delegator>, - ) { - let mut scheduled_requests = >::get(collator); - - let maybe_request_idx = scheduled_requests - .iter() - .position(|req| &req.delegator == delegator); - - if let Some(request_idx) = maybe_request_idx { - let request = scheduled_requests.remove(request_idx); - let amount = request.action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - >::insert(collator, scheduled_requests); - } - } - - /// Returns true if a [ScheduledRequest] exists for a given delegation - pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { - >::get(collator) - .iter() - .any(|req| &req.delegator == delegator) - } - - /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation - pub fn delegation_request_revoke_exists( - collator: &T::AccountId, - delegator: &T::AccountId, - ) -> bool { - >::get(collator) - .iter() - .any(|req| { - &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - } + /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. + pub(crate) fn delegation_schedule_revoke( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + ensure!( + !scheduled_requests.iter().any(|req| req.delegator == delegator), + >::PendingDelegationRequestAlreadyExists, + ); + + let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; + let now = >::get().current; + let when = now.saturating_add(T::RevokeDelegationDelay::get()); + scheduled_requests.push(ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Revoke(bonded_amount), + when_executable: when, + }); + state.less_total = state.less_total.saturating_add(bonded_amount); + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::DelegationRevocationScheduled { + round: now, + delegator, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Schedules a [DelegationAction::Decrease] for the delegator, towards a given collator. + pub(crate) fn delegation_schedule_bond_decrease( + collator: T::AccountId, + delegator: T::AccountId, + decrease_amount: BalanceOf, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + ensure!( + !scheduled_requests.iter().any(|req| req.delegator == delegator), + >::PendingDelegationRequestAlreadyExists, + ); + + let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; + ensure!(bonded_amount > decrease_amount, >::DelegatorBondBelowMin); + let new_amount: BalanceOf = bonded_amount - decrease_amount; + ensure!(new_amount >= T::MinDelegation::get(), >::DelegationBelowMin); + + // Net Total is total after pending orders are executed + let net_total = state.total().saturating_sub(state.less_total); + // Net Total is always >= MinDelegatorStk + let max_subtracted_amount = net_total.saturating_sub(T::MinDelegatorStk::get()); + ensure!(decrease_amount <= max_subtracted_amount, >::DelegatorBondBelowMin); + + let now = >::get().current; + let when = now.saturating_add(T::RevokeDelegationDelay::get()); + scheduled_requests.push(ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Decrease(decrease_amount), + when_executable: when, + }); + state.less_total = state.less_total.saturating_add(decrease_amount); + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::DelegationDecreaseScheduled { + delegator, + candidate: collator, + amount_to_decrease: decrease_amount, + execute_round: when, + }); + Ok(().into()) + } + + /// Cancels the delegator's existing [ScheduledRequest] towards a given collator. + pub(crate) fn delegation_cancel_request( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) + .ok_or(>::PendingDelegationRequestDNE)?; + + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::CancelledDelegationRequest { + delegator, + collator, + cancelled_request: request.into(), + }); + Ok(().into()) + } + + fn cancel_request_with_state( + delegator: &T::AccountId, + state: &mut Delegator>, + scheduled_requests: &mut Vec>>, + ) -> Option>> { + let request_idx = scheduled_requests.iter().position(|req| &req.delegator == delegator)?; + + let request = scheduled_requests.remove(request_idx); + let amount = request.action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + Some(request) + } + + /// Executes the delegator's existing [ScheduledRequest] towards a given collator. + pub(crate) fn delegation_execute_scheduled_request( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + let request_idx = scheduled_requests + .iter() + .position(|req| req.delegator == delegator) + .ok_or(>::PendingDelegationRequestDNE)?; + let request = &scheduled_requests[request_idx]; + + let now = >::get().current; + ensure!(request.when_executable <= now, >::PendingDelegationRequestNotDueYet); + + match request.action { + DelegationAction::Revoke(amount) => { + // revoking last delegation => leaving set of delegators + let leaving = if state.delegations.0.len() == 1usize { + true + } else { + ensure!( + state.total().saturating_sub(T::MinDelegatorStk::get()) >= amount, + >::DelegatorBondBelowMin + ); + false + }; + + // remove from pending requests + let amount = scheduled_requests.remove(request_idx).action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + + // remove delegation from delegator state + state.rm_delegation::(&collator); + + // remove delegation from auto-compounding info + >::remove_auto_compound(&collator, &delegator); + + // remove delegation from collator state delegations + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), amount)?; + Self::deposit_event(Event::DelegationRevoked { + delegator: delegator.clone(), + candidate: collator.clone(), + unstaked_amount: amount, + }); + + >::insert(collator, scheduled_requests); + if leaving { + >::remove(&delegator); + Self::deposit_event(Event::DelegatorLeft { + delegator, + unstaked_amount: amount, + }); + } else { + >::insert(&delegator, state); + } + Ok(().into()) + } + DelegationAction::Decrease(_) => { + // remove from pending requests + let amount = scheduled_requests.remove(request_idx).action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + + // decrease delegation + for bond in &mut state.delegations.0 { + if bond.owner == collator { + return if bond.amount > amount { + let amount_before: BalanceOf = bond.amount; + bond.amount = bond.amount.saturating_sub(amount); + let mut collator_info = >::get(&collator) + .ok_or(>::CandidateDNE)?; + + state.total_sub_if::(amount, |total| { + let new_total: BalanceOf = total; + ensure!( + new_total >= T::MinDelegation::get(), + >::DelegationBelowMin + ); + ensure!( + new_total >= T::MinDelegatorStk::get(), + >::DelegatorBondBelowMin + ); + + Ok(()) + })?; + + // need to go into decrease_delegation + let in_top = collator_info.decrease_delegation::( + &collator, + delegator.clone(), + amount_before, + amount, + )?; + >::insert(&collator, collator_info); + let new_total_staked = >::get().saturating_sub(amount); + >::put(new_total_staked); + + >::insert( + collator.clone(), + scheduled_requests, + ); + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegationDecreased { + delegator, + candidate: collator.clone(), + amount, + in_top, + }); + Ok(().into()) + } else { + // must rm entire delegation if bond.amount <= less or cancel request + Err(>::DelegationBelowMin.into()) + }; + } + } + Err(>::DelegationDNE.into()) + } + } + } + + /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. + /// The last fulfilled request causes the delegator to leave the set of delegators. + pub(crate) fn delegator_schedule_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut updated_scheduled_requests = vec![]; + let now = >::get().current; + let when = now.saturating_add(T::LeaveDelegatorsDelay::get()); + + // lazy migration for DelegatorStatus::Leaving + #[allow(deprecated)] + if matches!(state.status, DelegatorStatus::Leaving(_)) { + state.status = DelegatorStatus::Active; + >::insert(delegator.clone(), state.clone()); + } + + // it is assumed that a multiple delegations to the same collator does not exist, else this + // will cause a bug - the last duplicate delegation update will be the only one applied. + let mut existing_revoke_count = 0; + for bond in state.delegations.0.clone() { + let collator = bond.owner; + let bonded_amount = bond.amount; + let mut scheduled_requests = >::get(&collator); + + // cancel any existing requests + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + let request = match request { + Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { + existing_revoke_count += 1; + revoke_req // re-insert the same Revoke request + } + _ => ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Revoke(bonded_amount), + when_executable: when, + }, + }; + + scheduled_requests.push(request); + state.less_total = state.less_total.saturating_add(bonded_amount); + updated_scheduled_requests.push((collator, scheduled_requests)); + } + + if existing_revoke_count == state.delegations.0.len() { + return Err(>::DelegatorAlreadyLeaving.into()); + } + + updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegatorExitScheduled { + round: now, + delegator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. + /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be + /// executed in the current round, for this function to succeed. + pub(crate) fn delegator_cancel_scheduled_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut updated_scheduled_requests = vec![]; + + // backwards compatible handling for DelegatorStatus::Leaving + #[allow(deprecated)] + if matches!(state.status, DelegatorStatus::Leaving(_)) { + state.status = DelegatorStatus::Active; + >::insert(delegator.clone(), state.clone()); + Self::deposit_event(Event::DelegatorExitCancelled { delegator }); + return Ok(().into()); + } + + // pre-validate that all delegations have a Revoke request. + for bond in &state.delegations.0 { + let collator = bond.owner.clone(); + let scheduled_requests = >::get(&collator); + scheduled_requests + .iter() + .find(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + .ok_or(>::DelegatorNotLeaving)?; + } + + // cancel all requests + for bond in state.delegations.0.clone() { + let collator = bond.owner.clone(); + let mut scheduled_requests = >::get(&collator); + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + updated_scheduled_requests.push((collator, scheduled_requests)); + } + + updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegatorExitCancelled { delegator }); + + Ok(().into()) + } + + /// Executes every [DelegationAction::Revoke] request for a delegator towards a collator. + /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be + /// executed in the current round, for this function to succeed. + pub(crate) fn delegator_execute_scheduled_revoke_all( + delegator: T::AccountId, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + ensure!( + delegation_count >= (state.delegations.0.len() as u32), + Error::::TooLowDelegationCountToLeaveDelegators + ); + let now = >::get().current; + + // backwards compatible handling for DelegatorStatus::Leaving + #[allow(deprecated)] + if let DelegatorStatus::Leaving(when) = state.status { + ensure!(>::get().current >= when, Error::::DelegatorCannotLeaveYet); + + for bond in state.delegations.0.clone() { + if let Err(error) = Self::delegator_leaves_candidate( + bond.owner.clone(), + delegator.clone(), + bond.amount, + ) { + log::warn!( + "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", + error + ); + } + + Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); + >::remove_auto_compound(&bond.owner, &delegator); + } + >::remove(&delegator); + Self::deposit_event(Event::DelegatorLeft { delegator, unstaked_amount: state.total }); + return Ok(().into()); + } + + let mut validated_scheduled_requests = vec![]; + // pre-validate that all delegations have a Revoke request that can be executed now. + for bond in &state.delegations.0 { + let scheduled_requests = >::get(&bond.owner); + let request_idx = scheduled_requests + .iter() + .position(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + .ok_or(>::DelegatorNotLeaving)?; + let request = &scheduled_requests[request_idx]; + + ensure!(request.when_executable <= now, >::DelegatorCannotLeaveYet); + + validated_scheduled_requests.push((bond.clone(), scheduled_requests, request_idx)) + } + + let mut updated_scheduled_requests = vec![]; + // we do not update the delegator state, since the it will be completely removed + for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { + let collator = bond.owner; + + if let Err(error) = + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) + { + log::warn!( + "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", + delegator, + error + ); + } + + // remove the scheduled request, since it is fulfilled + scheduled_requests.remove(request_idx).action.amount(); + updated_scheduled_requests.push((collator.clone(), scheduled_requests)); + + // remove the auto-compounding entry for the delegation + >::remove_auto_compound(&collator, &delegator); + } + + // set state.total so that state.adjust_bond_lock will remove lock + let unstaked_amount = state.total(); + state.total_sub::(unstaked_amount)?; + + updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + Self::deposit_event(Event::DelegatorLeft { delegator: delegator.clone(), unstaked_amount }); + >::remove(&delegator); + + Ok(().into()) + } + + /// Removes the delegator's existing [ScheduledRequest] towards a given collator, if exists. + /// The state needs to be persisted by the caller of this function. + pub(crate) fn delegation_remove_request_with_state( + collator: &T::AccountId, + delegator: &T::AccountId, + state: &mut Delegator>, + ) { + let mut scheduled_requests = >::get(collator); + + let maybe_request_idx = + scheduled_requests.iter().position(|req| &req.delegator == delegator); + + if let Some(request_idx) = maybe_request_idx { + let request = scheduled_requests.remove(request_idx); + let amount = request.action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + >::insert(collator, scheduled_requests); + } + } + + /// Returns true if a [ScheduledRequest] exists for a given delegation + pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { + >::get(collator) + .iter() + .any(|req| &req.delegator == delegator) + } + + /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation + pub fn delegation_request_revoke_exists( + collator: &T::AccountId, + delegator: &T::AccountId, + ) -> bool { + >::get(collator).iter().any(|req| { + &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + } } #[cfg(test)] mod tests { - use super::*; - use crate::{mock::Test, set::OrderedSet, Bond}; - - #[test] - fn test_cancel_request_with_state_removes_request_for_correct_delegator_and_updates_state() { - let mut state = Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { - amount: 100, - owner: 2, - }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - }; - let mut scheduled_requests = vec![ - ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }, - ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }, - ]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); - - assert_eq!( - removed_request, - Some(ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }) - ); - assert_eq!( - scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] - ); - assert_eq!( - state, - Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { - amount: 100, - owner: 2, - }]), - total: 100, - less_total: 0, - status: crate::DelegatorStatus::Active, - } - ); - } - - #[test] - fn test_cancel_request_with_state_does_nothing_when_request_does_not_exist() { - let mut state = Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { - amount: 100, - owner: 2, - }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - }; - let mut scheduled_requests = vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); - - assert_eq!(removed_request, None,); - assert_eq!( - scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] - ); - assert_eq!( - state, - Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { - amount: 100, - owner: 2, - }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - } - ); - } + use super::*; + use crate::{mock::Test, set::OrderedSet, Bond}; + + #[test] + fn test_cancel_request_with_state_removes_request_for_correct_delegator_and_updates_state() { + let mut state = Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + }; + let mut scheduled_requests = vec![ + ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }, + ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }, + ]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + + assert_eq!( + removed_request, + Some(ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }) + ); + assert_eq!( + scheduled_requests, + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] + ); + assert_eq!( + state, + Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 0, + status: crate::DelegatorStatus::Active, + } + ); + } + + #[test] + fn test_cancel_request_with_state_does_nothing_when_request_does_not_exist() { + let mut state = Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + }; + let mut scheduled_requests = vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + + assert_eq!(removed_request, None,); + assert_eq!( + scheduled_requests, + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] + ); + assert_eq!( + state, + Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + } + ); + } } diff --git a/external/pallets/parachain-staking/src/inflation.rs b/external/pallets/parachain-staking/src/inflation.rs index edc246575..d2f7522dd 100644 --- a/external/pallets/parachain-staking/src/inflation.rs +++ b/external/pallets/parachain-staking/src/inflation.rs @@ -21,208 +21,188 @@ use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -use sp_runtime::PerThing; -use sp_runtime::{Perbill, RuntimeDebug}; -use substrate_fixed::transcendental::pow as floatpow; -use substrate_fixed::types::I64F64; +use sp_runtime::{PerThing, Perbill, RuntimeDebug}; +use substrate_fixed::{transcendental::pow as floatpow, types::I64F64}; const SECONDS_PER_YEAR: u32 = 31557600; const SECONDS_PER_BLOCK: u32 = 12; pub const BLOCKS_PER_YEAR: u32 = SECONDS_PER_YEAR / SECONDS_PER_BLOCK; fn rounds_per_year() -> u32 { - let blocks_per_round = >::round().length; - BLOCKS_PER_YEAR / blocks_per_round + let blocks_per_round = >::round().length; + BLOCKS_PER_YEAR / blocks_per_round } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[derive( - Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, + Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, )] pub struct Range { - pub min: T, - pub ideal: T, - pub max: T, + pub min: T, + pub ideal: T, + pub max: T, } impl Range { - pub fn is_valid(&self) -> bool { - self.max >= self.ideal && self.ideal >= self.min - } + pub fn is_valid(&self) -> bool { + self.max >= self.ideal && self.ideal >= self.min + } } impl From for Range { - fn from(other: T) -> Range { - Range { - min: other, - ideal: other, - max: other, - } - } + fn from(other: T) -> Range { + Range { min: other, ideal: other, max: other } + } } /// Convert an annual inflation to a round inflation /// round = (1+annual)^(1/rounds_per_year) - 1 pub fn perbill_annual_to_perbill_round( - annual: Range, - rounds_per_year: u32, + annual: Range, + rounds_per_year: u32, ) -> Range { - let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); - let annual_to_round = |annual: Perbill| -> Perbill { - let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); - let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) - .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); - Perbill::from_parts( - ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) - .ceil() - .to_num::(), - ) - }; - Range { - min: annual_to_round(annual.min), - ideal: annual_to_round(annual.ideal), - max: annual_to_round(annual.max), - } + let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); + let annual_to_round = |annual: Perbill| -> Perbill { + let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); + let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) + .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); + Perbill::from_parts( + ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) + .ceil() + .to_num::(), + ) + }; + Range { + min: annual_to_round(annual.min), + ideal: annual_to_round(annual.ideal), + max: annual_to_round(annual.max), + } } /// Convert annual inflation rate range to round inflation range pub fn annual_to_round(annual: Range) -> Range { - let periods = rounds_per_year::(); - perbill_annual_to_perbill_round(annual, periods) + let periods = rounds_per_year::(); + perbill_annual_to_perbill_round(annual, periods) } /// Compute round issuance range from round inflation range and current total issuance pub fn round_issuance_range(round: Range) -> Range> { - let circulating = T::Currency::total_issuance(); - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } + let circulating = T::Currency::total_issuance(); + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] pub struct InflationInfo { - /// Staking expectations - pub expect: Range, - /// Annual inflation range - pub annual: Range, - /// Round inflation range - pub round: Range, + /// Staking expectations + pub expect: Range, + /// Annual inflation range + pub annual: Range, + /// Round inflation range + pub round: Range, } impl InflationInfo { - pub fn new( - annual: Range, - expect: Range, - ) -> InflationInfo { - InflationInfo { - expect, - annual, - round: annual_to_round::(annual), - } - } - /// Set round inflation range according to input annual inflation range - pub fn set_round_from_annual(&mut self, new: Range) { - self.round = annual_to_round::(new); - } - /// Reset round inflation rate based on changes to round length - pub fn reset_round(&mut self, new_length: u32) { - let periods = BLOCKS_PER_YEAR / new_length; - self.round = perbill_annual_to_perbill_round(self.annual, periods); - } - /// Set staking expectations - pub fn set_expectations(&mut self, expect: Range) { - self.expect = expect; - } + pub fn new( + annual: Range, + expect: Range, + ) -> InflationInfo { + InflationInfo { expect, annual, round: annual_to_round::(annual) } + } + /// Set round inflation range according to input annual inflation range + pub fn set_round_from_annual(&mut self, new: Range) { + self.round = annual_to_round::(new); + } + /// Reset round inflation rate based on changes to round length + pub fn reset_round(&mut self, new_length: u32) { + let periods = BLOCKS_PER_YEAR / new_length; + self.round = perbill_annual_to_perbill_round(self.annual, periods); + } + /// Set staking expectations + pub fn set_expectations(&mut self, expect: Range) { + self.expect = expect; + } } #[cfg(test)] mod tests { - use super::*; - fn mock_annual_to_round(annual: Range, rounds_per_year: u32) -> Range { - perbill_annual_to_perbill_round(annual, rounds_per_year) - } - fn mock_round_issuance_range( - // Total circulating before minting - circulating: u128, - // Round inflation range - round: Range, - ) -> Range { - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } - } - #[test] - fn simple_issuance_conversion() { - // 5% inflation for 10_000_0000 = 500,000 minted over the year - // let's assume there are 10 periods in a year - // => mint 500_000 over 10 periods => 50_000 minted per period - let expected_round_issuance_range: Range = Range { - min: 48_909, - ideal: 48_909, - max: 48_909, - }; - let schedule = Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_issuance_range, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) - ); - } - #[test] - fn range_issuance_conversion() { - // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year - // let's assume there are 10 periods in a year - // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period - let expected_round_issuance_range: Range = Range { - min: 29_603, - ideal: 39298, - max: 48_909, - }; - let schedule = Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_issuance_range, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) - ); - } - #[test] - fn expected_parameterization() { - let expected_round_schedule: Range = Range { - min: 45, - ideal: 56, - max: 56, - }; - let schedule = Range { - min: Perbill::from_percent(4), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_schedule, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) - ); - } - #[test] - fn inflation_does_not_panic_at_round_number_limit() { - let schedule = Range { - min: Perbill::from_percent(100), - ideal: Perbill::from_percent(100), - max: Perbill::from_percent(100), - }; - mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1)); - mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1)); - mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, 1)); - } + use super::*; + fn mock_annual_to_round(annual: Range, rounds_per_year: u32) -> Range { + perbill_annual_to_perbill_round(annual, rounds_per_year) + } + fn mock_round_issuance_range( + // Total circulating before minting + circulating: u128, + // Round inflation range + round: Range, + ) -> Range { + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } + } + #[test] + fn simple_issuance_conversion() { + // 5% inflation for 10_000_0000 = 500,000 minted over the year + // let's assume there are 10 periods in a year + // => mint 500_000 over 10 periods => 50_000 minted per period + let expected_round_issuance_range: Range = + Range { min: 48_909, ideal: 48_909, max: 48_909 }; + let schedule = Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_issuance_range, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) + ); + } + #[test] + fn range_issuance_conversion() { + // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year + // let's assume there are 10 periods in a year + // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period + let expected_round_issuance_range: Range = + Range { min: 29_603, ideal: 39298, max: 48_909 }; + let schedule = Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_issuance_range, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) + ); + } + #[test] + fn expected_parameterization() { + let expected_round_schedule: Range = Range { min: 45, ideal: 56, max: 56 }; + let schedule = Range { + min: Perbill::from_percent(4), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_schedule, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) + ); + } + #[test] + fn inflation_does_not_panic_at_round_number_limit() { + let schedule = Range { + min: Perbill::from_percent(100), + ideal: Perbill::from_percent(100), + max: Perbill::from_percent(100), + }; + mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u128::MAX, mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1)); + mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1)); + mock_round_issuance_range(u128::MAX, mock_annual_to_round(schedule, 1)); + } } diff --git a/external/pallets/parachain-staking/src/lib.rs b/external/pallets/parachain-staking/src/lib.rs index 172fc371c..6da9321ec 100644 --- a/external/pallets/parachain-staking/src/lib.rs +++ b/external/pallets/parachain-staking/src/lib.rs @@ -47,6 +47,7 @@ //! To leave the set of delegators and revoke all delegations, call `leave_delegators`. #![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::type_complexity)] mod auto_compound; mod delegation_requests; @@ -77,1850 +78,1773 @@ pub use RoundIndex; #[pallet] pub mod pallet { - use crate::delegation_requests::{ - CancelledScheduledRequest, DelegationAction, ScheduledRequest, - }; - use crate::{set::OrderedSet, traits::*, types::*, InflationInfo, Range, WeightInfo}; - use crate::{AutoCompoundConfig, AutoCompoundDelegations}; - use frame_support::pallet_prelude::*; - use frame_support::traits::{ - tokens::WithdrawReasons, Currency, Get, Imbalance, LockIdentifier, LockableCurrency, - ReservableCurrency, - }; - use frame_system::pallet_prelude::*; - use sp_runtime::{ - traits::{Saturating, Zero}, - Perbill, Percent, - }; - use sp_std::{collections::btree_map::BTreeMap, prelude::*}; - - /// Pallet for parachain staking - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - pub type RoundIndex = u32; - type RewardPoint = u32; - pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; - - pub const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol"; - pub const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel"; - - /// Configuration trait of this pallet. - #[pallet::config] - pub trait Config: frame_system::Config { - /// Overarching event type - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// The currency type - type Currency: Currency - + ReservableCurrency - + LockableCurrency; - /// The origin for monetary governance - type MonetaryGovernanceOrigin: EnsureOrigin; - /// Minimum number of blocks per round - #[pallet::constant] - type MinBlocksPerRound: Get; - /// Number of rounds that candidates remain bonded before exit request is executable - #[pallet::constant] - type LeaveCandidatesDelay: Get; - /// Number of rounds candidate requests to decrease self-bond must wait to be executable - #[pallet::constant] - type CandidateBondLessDelay: Get; - /// Number of rounds that delegators remain bonded before exit request is executable - #[pallet::constant] - type LeaveDelegatorsDelay: Get; - /// Number of rounds that delegations remain bonded before revocation request is executable - #[pallet::constant] - type RevokeDelegationDelay: Get; - /// Number of rounds that delegation less requests must wait before executable - #[pallet::constant] - type DelegationBondLessDelay: Get; - /// Number of rounds after which block authors are rewarded - #[pallet::constant] - type RewardPaymentDelay: Get; - /// Minimum number of selected candidates every round - #[pallet::constant] - type MinSelectedCandidates: Get; - /// Maximum top delegations counted per candidate - #[pallet::constant] - type MaxTopDelegationsPerCandidate: Get; - /// Maximum bottom delegations (not counted) per candidate - #[pallet::constant] - type MaxBottomDelegationsPerCandidate: Get; - /// Maximum delegations per delegator - #[pallet::constant] - type MaxDelegationsPerDelegator: Get; - /// Minimum stake required for any candidate to be in `SelectedCandidates` for the round - #[pallet::constant] - type MinCollatorStk: Get>; - /// Minimum stake required for any account to be a collator candidate - #[pallet::constant] - type MinCandidateStk: Get>; - /// Minimum stake for any registered on-chain account to delegate - #[pallet::constant] - type MinDelegation: Get>; - /// Minimum stake for any registered on-chain account to be a delegator - #[pallet::constant] - type MinDelegatorStk: Get>; - /// Get the current block author - type BlockAuthor: Get; - /// Handler to notify the runtime when a collator is paid. - /// If you don't need it, you can specify the type `()`. - type OnCollatorPayout: OnCollatorPayout>; - /// Handler to distribute a collator's reward. - /// To use the default implementation of minting rewards, specify the type `()`. - type PayoutCollatorReward: PayoutCollatorReward; - /// Handler to notify the runtime when a new round begin. - /// If you don't need it, you can specify the type `()`. - type OnNewRound: OnNewRound; - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - } - - #[pallet::error] - pub enum Error { - DelegatorDNE, - DelegatorDNEinTopNorBottom, - DelegatorDNEInDelegatorSet, - CandidateDNE, - DelegationDNE, - DelegatorExists, - CandidateExists, - CandidateBondBelowMin, - InsufficientBalance, - DelegatorBondBelowMin, - DelegationBelowMin, - AlreadyOffline, - AlreadyActive, - DelegatorAlreadyLeaving, - DelegatorNotLeaving, - DelegatorCannotLeaveYet, - CannotDelegateIfLeaving, - CandidateAlreadyLeaving, - CandidateNotLeaving, - CandidateCannotLeaveYet, - CannotGoOnlineIfLeaving, - ExceedMaxDelegationsPerDelegator, - AlreadyDelegatedCandidate, - InvalidSchedule, - CannotSetBelowMin, - RoundLengthMustBeGreaterThanTotalSelectedCollators, - NoWritingSameValue, - TooLowCandidateCountWeightHintJoinCandidates, - TooLowCandidateCountWeightHintCancelLeaveCandidates, - TooLowCandidateCountToLeaveCandidates, - TooLowDelegationCountToDelegate, - TooLowCandidateDelegationCountToDelegate, - TooLowCandidateDelegationCountToLeaveCandidates, - TooLowDelegationCountToLeaveDelegators, - PendingCandidateRequestsDNE, - PendingCandidateRequestAlreadyExists, - PendingCandidateRequestNotDueYet, - PendingDelegationRequestDNE, - PendingDelegationRequestAlreadyExists, - PendingDelegationRequestNotDueYet, - CannotDelegateLessThanOrEqualToLowestBottomWhenFull, - PendingDelegationRevoke, - TooLowDelegationCountToAutoCompound, - TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - TooLowCandidateAutoCompoundingDelegationCountToDelegate, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// Started new round. - NewRound { - starting_block: T::BlockNumber, - round: RoundIndex, - selected_collators_number: u32, - total_balance: BalanceOf, - }, - /// Account joined the set of collator candidates. - JoinedCollatorCandidates { - account: T::AccountId, - amount_locked: BalanceOf, - new_total_amt_locked: BalanceOf, - }, - /// Candidate selected for collators. Total Exposed Amount includes all delegations. - CollatorChosen { - round: RoundIndex, - collator_account: T::AccountId, - total_exposed_amount: BalanceOf, - }, - /// Candidate requested to decrease a self bond. - CandidateBondLessRequested { - candidate: T::AccountId, - amount_to_decrease: BalanceOf, - execute_round: RoundIndex, - }, - /// Candidate has increased a self bond. - CandidateBondedMore { - candidate: T::AccountId, - amount: BalanceOf, - new_total_bond: BalanceOf, - }, - /// Candidate has decreased a self bond. - CandidateBondedLess { - candidate: T::AccountId, - amount: BalanceOf, - new_bond: BalanceOf, - }, - /// Candidate temporarily leave the set of collator candidates without unbonding. - CandidateWentOffline { candidate: T::AccountId }, - /// Candidate rejoins the set of collator candidates. - CandidateBackOnline { candidate: T::AccountId }, - /// Candidate has requested to leave the set of candidates. - CandidateScheduledExit { - exit_allowed_round: RoundIndex, - candidate: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Cancelled request to leave the set of candidates. - CancelledCandidateExit { candidate: T::AccountId }, - /// Cancelled request to decrease candidate's bond. - CancelledCandidateBondLess { - candidate: T::AccountId, - amount: BalanceOf, - execute_round: RoundIndex, - }, - /// Candidate has left the set of candidates. - CandidateLeft { - ex_candidate: T::AccountId, - unlocked_amount: BalanceOf, - new_total_amt_locked: BalanceOf, - }, - /// Delegator requested to decrease a bond for the collator candidate. - DelegationDecreaseScheduled { - delegator: T::AccountId, - candidate: T::AccountId, - amount_to_decrease: BalanceOf, - execute_round: RoundIndex, - }, - // Delegation increased. - DelegationIncreased { - delegator: T::AccountId, - candidate: T::AccountId, - amount: BalanceOf, - in_top: bool, - }, - // Delegation decreased. - DelegationDecreased { - delegator: T::AccountId, - candidate: T::AccountId, - amount: BalanceOf, - in_top: bool, - }, - /// Delegator requested to leave the set of delegators. - DelegatorExitScheduled { - round: RoundIndex, - delegator: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Delegator requested to revoke delegation. - DelegationRevocationScheduled { - round: RoundIndex, - delegator: T::AccountId, - candidate: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Delegator has left the set of delegators. - DelegatorLeft { - delegator: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Delegation revoked. - DelegationRevoked { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Delegation kicked. - DelegationKicked { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Cancelled a pending request to exit the set of delegators. - DelegatorExitCancelled { delegator: T::AccountId }, - /// Cancelled request to change an existing delegation. - CancelledDelegationRequest { - delegator: T::AccountId, - cancelled_request: CancelledScheduledRequest>, - collator: T::AccountId, - }, - /// New delegation (increase of the existing one). - Delegation { - delegator: T::AccountId, - locked_amount: BalanceOf, - candidate: T::AccountId, - delegator_position: DelegatorAdded>, - auto_compound: Percent, - }, - /// Delegation from candidate state has been remove. - DelegatorLeftCandidate { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - total_candidate_staked: BalanceOf, - }, - /// Paid the account (delegator or collator) the balance as liquid rewards. - Rewarded { - account: T::AccountId, - rewards: BalanceOf, - }, - /// Transferred to account which holds funds reserved for parachain bond. - ReservedForParachainBond { - account: T::AccountId, - value: BalanceOf, - }, - /// Account (re)set for parachain bond treasury. - ParachainBondAccountSet { - old: T::AccountId, - new: T::AccountId, - }, - /// Percent of inflation reserved for parachain bond (re)set. - ParachainBondReservePercentSet { old: Percent, new: Percent }, - /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) - InflationSet { - annual_min: Perbill, - annual_ideal: Perbill, - annual_max: Perbill, - round_min: Perbill, - round_ideal: Perbill, - round_max: Perbill, - }, - /// Staking expectations set. - StakeExpectationsSet { - expect_min: BalanceOf, - expect_ideal: BalanceOf, - expect_max: BalanceOf, - }, - /// Set total selected candidates to this value. - TotalSelectedSet { old: u32, new: u32 }, - /// Set collator commission to this value. - CollatorCommissionSet { old: Perbill, new: Perbill }, - /// Set blocks per round - BlocksPerRoundSet { - current_round: RoundIndex, - first_block: T::BlockNumber, - old: u32, - new: u32, - new_per_round_inflation_min: Perbill, - new_per_round_inflation_ideal: Perbill, - new_per_round_inflation_max: Perbill, - }, - /// Auto-compounding reward percent was set for a delegation. - AutoCompoundSet { - candidate: T::AccountId, - delegator: T::AccountId, - value: Percent, - }, - /// Compounded a portion of rewards towards the delegation. - Compounded { - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - }, - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(n: T::BlockNumber) -> Weight { - let mut weight = T::WeightInfo::base_on_initialize(); - - let mut round = >::get(); - if round.should_update(n) { - // mutate round - round.update(n); - // notify that new round begin - weight = weight.saturating_add(T::OnNewRound::on_new_round(round.current)); - // pay all stakers for T::RewardPaymentDelay rounds ago - weight = weight.saturating_add(Self::prepare_staking_payouts(round.current)); - // select top collator candidates for next round - let (extra_weight, collator_count, _delegation_count, total_staked) = - Self::select_top_candidates(round.current); - weight = weight.saturating_add(extra_weight); - // start next round - >::put(round); - // snapshot total stake - >::insert(round.current, >::get()); - Self::deposit_event(Event::NewRound { - starting_block: round.first, - round: round.current, - selected_collators_number: collator_count, - total_balance: total_staked, - }); - // account for Round and Staked writes - weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 2)); - } else { - weight = weight.saturating_add(Self::handle_delayed_payouts(round.current)); - } - - // add on_finalize weight - // read: Author, Points, AwardedPts - // write: Points, AwardedPts - weight = weight.saturating_add(T::DbWeight::get().reads_writes(3, 2)); - weight - } - fn on_finalize(_n: T::BlockNumber) { - Self::award_points_to_block_author(); - } - } - - #[pallet::storage] - #[pallet::getter(fn collator_commission)] - /// Commission percent taken off of rewards for all collators - type CollatorCommission = StorageValue<_, Perbill, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn total_selected)] - /// The total candidates selected every round - pub(crate) type TotalSelected = StorageValue<_, u32, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn parachain_bond_info)] - /// Parachain bond config info { account, percent_of_inflation } - pub(crate) type ParachainBondInfo = - StorageValue<_, ParachainBondConfig, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn round)] - /// Current round index and next round scheduled transition - pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn delegator_state)] - /// Get delegator state associated with an account if account is delegating else None - pub(crate) type DelegatorState = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegator>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn candidate_info)] - /// Get collator candidate info associated with an account if account is candidate else None - pub(crate) type CandidateInfo = - StorageMap<_, Twox64Concat, T::AccountId, CandidateMetadata>, OptionQuery>; - - /// Stores outstanding delegation requests per collator. - #[pallet::storage] - #[pallet::getter(fn delegation_scheduled_requests)] - pub(crate) type DelegationScheduledRequests = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec>>, - ValueQuery, - >; - - /// Stores auto-compounding configuration per collator. - #[pallet::storage] - #[pallet::getter(fn auto_compounding_delegations)] - pub(crate) type AutoCompoundingDelegations = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec>, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn top_delegations)] - /// Top delegations for collator candidate - pub(crate) type TopDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn bottom_delegations)] - /// Bottom delegations for collator candidate - pub(crate) type BottomDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn selected_candidates)] - /// The collator candidates selected for the current round - type SelectedCandidates = StorageValue<_, Vec, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn total)] - /// Total capital locked by this staking pallet - pub(crate) type Total = StorageValue<_, BalanceOf, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn candidate_pool)] - /// The pool of collator candidates, each with their total backing stake - pub(crate) type CandidatePool = - StorageValue<_, OrderedSet>>, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn at_stake)] - /// Snapshot of collator delegation stake at the start of the round - pub type AtStake = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - CollatorSnapshot>, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn delayed_payouts)] - /// Delayed payouts - pub type DelayedPayouts = - StorageMap<_, Twox64Concat, RoundIndex, DelayedPayout>, OptionQuery>; - - #[pallet::storage] - #[pallet::getter(fn staked)] - /// Total counted stake for selected candidates in the round - pub type Staked = StorageMap<_, Twox64Concat, RoundIndex, BalanceOf, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn inflation_config)] - /// Inflation configuration - pub type InflationConfig = StorageValue<_, InflationInfo>, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn points)] - /// Total points awarded to collators for block production in the round - pub type Points = StorageMap<_, Twox64Concat, RoundIndex, RewardPoint, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn awarded_pts)] - /// Points for each collator per round - pub type AwardedPts = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - RewardPoint, - ValueQuery, - >; - - #[pallet::genesis_config] - pub struct GenesisConfig { - /// Initialize balance and register all as collators: `(collator AccountId, balance Amount)` - pub candidates: Vec<(T::AccountId, BalanceOf)>, - /// Initialize balance and make delegations: - /// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding Percent)` - pub delegations: Vec<(T::AccountId, T::AccountId, BalanceOf, Percent)>, - /// Inflation configuration - pub inflation_config: InflationInfo>, - /// Default fixed percent a collator takes off the top of due rewards - pub collator_commission: Perbill, - /// Default percent of inflation set aside for parachain bond every round - pub parachain_bond_reserve_percent: Percent, - /// Default number of blocks in a round - pub blocks_per_round: u32, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - candidates: vec![], - delegations: vec![], - inflation_config: Default::default(), - collator_commission: Default::default(), - parachain_bond_reserve_percent: Default::default(), - blocks_per_round: 1u32, - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - assert!(self.blocks_per_round > 0, "Blocks per round must be > 0"); - >::put(self.inflation_config.clone()); - let mut candidate_count = 0u32; - // Initialize the candidates - for &(ref candidate, balance) in &self.candidates { - assert!( - >::get_collator_stakable_free_balance(candidate) >= balance, - "Account does not have enough balance to bond as a candidate." - ); - if let Err(error) = >::join_candidates( - T::RuntimeOrigin::from(Some(candidate.clone()).into()), - balance, - candidate_count, - ) { - log::warn!("Join candidates failed in genesis with error {:?}", error); - } else { - candidate_count = candidate_count.saturating_add(1u32); - } - } - - let mut col_delegator_count: BTreeMap = BTreeMap::new(); - let mut col_auto_compound_delegator_count: BTreeMap = - BTreeMap::new(); - let mut del_delegation_count: BTreeMap = BTreeMap::new(); - // Initialize the delegations - for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { - assert!( - >::get_delegator_stakable_free_balance(delegator) >= balance, - "Account does not have enough balance to place delegation." - ); - let cd_count = if let Some(x) = col_delegator_count.get(target) { - *x - } else { - 0u32 - }; - let dd_count = if let Some(x) = del_delegation_count.get(delegator) { - *x - } else { - 0u32 - }; - let cd_auto_compound_count = col_auto_compound_delegator_count - .get(target) - .cloned() - .unwrap_or_default(); - if let Err(error) = >::delegate_with_auto_compound( - T::RuntimeOrigin::from(Some(delegator.clone()).into()), - target.clone(), - balance, - auto_compound, - cd_count, - cd_auto_compound_count, - dd_count, - ) { - log::warn!("Delegate failed in genesis with error {:?}", error); - } else { - if let Some(x) = col_delegator_count.get_mut(target) { - *x = x.saturating_add(1u32); - } else { - col_delegator_count.insert(target.clone(), 1u32); - }; - if let Some(x) = del_delegation_count.get_mut(delegator) { - *x = x.saturating_add(1u32); - } else { - del_delegation_count.insert(delegator.clone(), 1u32); - }; - if !auto_compound.is_zero() { - col_auto_compound_delegator_count - .entry(target.clone()) - .and_modify(|x| *x = x.saturating_add(1)) - .or_insert(1); - } - } - } - // Set collator commission to default config - >::put(self.collator_commission); - // Set parachain bond config to default config - >::put(ParachainBondConfig { - // must be set soon; if not => due inflation will be sent to collators/delegators - account: T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - percent: self.parachain_bond_reserve_percent, - }); - // Set total selected candidates to minimum config - >::put(T::MinSelectedCandidates::get()); - // Choose top TotalSelected collator candidates - let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); - // Start Round 1 at Block 0 - let round: RoundInfo = - RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); - >::put(round); - // Snapshot total stake - >::insert(1u32, >::get()); - >::deposit_event(Event::NewRound { - starting_block: T::BlockNumber::zero(), - round: 1u32, - selected_collators_number: v_count, - total_balance: total_staked, - }); - } - } - - #[pallet::call] - impl Pallet { - #[pallet::weight(::WeightInfo::set_staking_expectations())] - /// Set the expectations for total staked. These expectations determine the issuance for - /// the round according to logic in `fn compute_issuance` - pub fn set_staking_expectations( - origin: OriginFor, - expectations: Range>, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - ensure!(expectations.is_valid(), Error::::InvalidSchedule); - let mut config = >::get(); - ensure!( - config.expect != expectations, - Error::::NoWritingSameValue - ); - config.set_expectations(expectations); - Self::deposit_event(Event::StakeExpectationsSet { - expect_min: config.expect.min, - expect_ideal: config.expect.ideal, - expect_max: config.expect.max, - }); - >::put(config); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_inflation())] - /// Set the annual inflation rate to derive per-round inflation - pub fn set_inflation( - origin: OriginFor, - schedule: Range, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - ensure!(schedule.is_valid(), Error::::InvalidSchedule); - let mut config = >::get(); - ensure!(config.annual != schedule, Error::::NoWritingSameValue); - config.annual = schedule; - config.set_round_from_annual::(schedule); - Self::deposit_event(Event::InflationSet { - annual_min: config.annual.min, - annual_ideal: config.annual.ideal, - annual_max: config.annual.max, - round_min: config.round.min, - round_ideal: config.round.ideal, - round_max: config.round.max, - }); - >::put(config); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_parachain_bond_account())] - /// Set the account that will hold funds set aside for parachain bond - pub fn set_parachain_bond_account( - origin: OriginFor, - new: T::AccountId, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - let ParachainBondConfig { - account: old, - percent, - } = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(ParachainBondConfig { - account: new.clone(), - percent, - }); - Self::deposit_event(Event::ParachainBondAccountSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] - /// Set the percent of inflation set aside for parachain bond - pub fn set_parachain_bond_reserve_percent( - origin: OriginFor, - new: Percent, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - let ParachainBondConfig { - account, - percent: old, - } = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(ParachainBondConfig { - account, - percent: new, - }); - Self::deposit_event(Event::ParachainBondReservePercentSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_total_selected())] - /// Set the total number of collator candidates selected per round - /// - changes are not applied until the start of the next round - pub fn set_total_selected(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - ensure!( - new >= T::MinSelectedCandidates::get(), - Error::::CannotSetBelowMin - ); - let old = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new <= >::get().length, - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - >::put(new); - Self::deposit_event(Event::TotalSelectedSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_collator_commission())] - /// Set the commission for all collators - pub fn set_collator_commission( - origin: OriginFor, - new: Perbill, - ) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - let old = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(new); - Self::deposit_event(Event::CollatorCommissionSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_blocks_per_round())] - /// Set blocks per round - /// - if called with `new` less than length of current round, will transition immediately - /// in the next block - /// - also updates per-round inflation config - pub fn set_blocks_per_round(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - ensure!( - new >= T::MinBlocksPerRound::get(), - Error::::CannotSetBelowMin - ); - let mut round = >::get(); - let (now, first, old) = (round.current, round.first, round.length); - ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new >= >::get(), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - round.length = new; - // update per-round inflation given new rounds per year - let mut inflation_config = >::get(); - inflation_config.reset_round(new); - >::put(round); - Self::deposit_event(Event::BlocksPerRoundSet { - current_round: now, - first_block: first, - old: old, - new: new, - new_per_round_inflation_min: inflation_config.round.min, - new_per_round_inflation_ideal: inflation_config.round.ideal, - new_per_round_inflation_max: inflation_config.round.max, - }); - >::put(inflation_config); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::join_candidates(*candidate_count))] - /// Join the set of collator candidates - pub fn join_candidates( - origin: OriginFor, - bond: BalanceOf, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - ensure!(!Self::is_candidate(&acc), Error::::CandidateExists); - ensure!(!Self::is_delegator(&acc), Error::::DelegatorExists); - ensure!( - bond >= T::MinCandidateStk::get(), - Error::::CandidateBondBelowMin - ); - let mut candidates = >::get(); - let old_count = candidates.0.len() as u32; - ensure!( - candidate_count >= old_count, - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - ensure!( - candidates.insert(Bond { - owner: acc.clone(), - amount: bond - }), - Error::::CandidateExists - ); - ensure!( - Self::get_collator_stakable_free_balance(&acc) >= bond, - Error::::InsufficientBalance, - ); - T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); - let candidate = CandidateMetadata::new(bond); - >::insert(&acc, candidate); - let empty_delegations: Delegations> = Default::default(); - // insert empty top delegations - >::insert(&acc, empty_delegations.clone()); - // insert empty bottom delegations - >::insert(&acc, empty_delegations); - >::put(candidates); - let new_total = >::get().saturating_add(bond); - >::put(new_total); - Self::deposit_event(Event::JoinedCollatorCandidates { - account: acc, - amount_locked: bond, - new_total_amt_locked: new_total, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] - /// Request to leave the set of candidates. If successful, the account is immediately - /// removed from the candidate pool to prevent selection as a collator. - pub fn schedule_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let (now, when) = state.schedule_leave::()?; - let mut candidates = >::get(); - ensure!( - candidate_count >= candidates.0.len() as u32, - Error::::TooLowCandidateCountToLeaveCandidates - ); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); - } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateScheduledExit { - exit_allowed_round: now, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) - } - - #[pallet::weight( - ::WeightInfo::execute_leave_candidates(*candidate_delegation_count) - )] - /// Execute leave candidates request - pub fn execute_leave_candidates( - origin: OriginFor, - candidate: T::AccountId, - candidate_delegation_count: u32, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - ensure!( - state.delegation_count <= candidate_delegation_count, - Error::::TooLowCandidateDelegationCountToLeaveCandidates - ); - state.can_leave::()?; - let return_stake = |bond: Bond>| -> DispatchResult { - // remove delegation from delegator state - let mut delegator = DelegatorState::::get(&bond.owner).expect( - "Collator state and delegator state are consistent. - Collator state has a record of this delegation. Therefore, - Delegator state also has a record. qed.", - ); - - if let Some(remaining) = delegator.rm_delegation::(&candidate) { - Self::delegation_remove_request_with_state( - &candidate, - &bond.owner, - &mut delegator, - ); - >::remove_auto_compound(&candidate, &bond.owner); - - if remaining.is_zero() { - // we do not remove the scheduled delegation requests from other collators - // since it is assumed that they were removed incrementally before only the - // last delegation was left. - >::remove(&bond.owner); - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); - } else { - >::insert(&bond.owner, delegator); - } - } else { - // TODO: review. we assume here that this delegator has no remaining staked - // balance, so we ensure the lock is cleared - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); - } - Ok(()) - }; - // total backing stake is at least the candidate self bond - let mut total_backing = state.bond; - // return all top delegations - let top_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in top_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(top_delegations.total); - // return all bottom delegations - let bottom_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in bottom_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(bottom_delegations.total); - // return stake to collator - T::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - let new_total_staked = >::get().saturating_sub(total_backing); - >::put(new_total_staked); - Self::deposit_event(Event::CandidateLeft { - ex_candidate: candidate, - unlocked_amount: total_backing, - new_total_amt_locked: new_total_staked, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] - /// Cancel open request to leave candidates - /// - only callable by collator account - /// - result upon successful call is the candidate is active in the candidate pool - pub fn cancel_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(state.is_leaving(), Error::::CandidateNotLeaving); - state.go_online(); - let mut candidates = >::get(); - ensure!( - candidates.0.len() as u32 <= candidate_count, - Error::::TooLowCandidateCountWeightHintCancelLeaveCandidates - ); - ensure!( - candidates.insert(Bond { - owner: collator.clone(), - amount: state.total_counted - }), - Error::::AlreadyActive - ); - >::put(candidates); - >::insert(&collator, state); - Self::deposit_event(Event::CancelledCandidateExit { - candidate: collator, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::go_offline())] - /// Temporarily leave the set of collator candidates without unbonding - pub fn go_offline(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(state.is_active(), Error::::AlreadyOffline); - state.go_offline(); - let mut candidates = >::get(); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); - } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateWentOffline { - candidate: collator, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::go_online())] - /// Rejoin the set of collator candidates if previously had called `go_offline` - pub fn go_online(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(!state.is_active(), Error::::AlreadyActive); - ensure!(!state.is_leaving(), Error::::CannotGoOnlineIfLeaving); - state.go_online(); - let mut candidates = >::get(); - ensure!( - candidates.insert(Bond { - owner: collator.clone(), - amount: state.total_counted - }), - Error::::AlreadyActive - ); - >::put(candidates); - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBackOnline { - candidate: collator, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::candidate_bond_more())] - /// Increase collator candidate self bond by `more` - pub fn candidate_bond_more( - origin: OriginFor, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - state.bond_more::(collator.clone(), more)?; - let (is_active, total_counted) = (state.is_active(), state.total_counted); - >::insert(&collator, state); - if is_active { - Self::update_active(collator, total_counted); - } - Ok(().into()) - } - #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] - /// Request by collator candidate to decrease self bond by `less` - pub fn schedule_candidate_bond_less( - origin: OriginFor, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let when = state.schedule_bond_less::(less)?; - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBondLessRequested { - candidate: collator, - amount_to_decrease: less, - execute_round: when, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::execute_candidate_bond_less())] - /// Execute pending request to adjust the collator candidate self bond - pub fn execute_candidate_bond_less( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; // we may want to reward this if caller != candidate - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.execute_bond_less::(candidate.clone())?; - >::insert(&candidate, state); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::cancel_candidate_bond_less())] - /// Cancel pending request to adjust the collator candidate self bond - pub fn cancel_candidate_bond_less(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - state.cancel_bond_less::(collator.clone())?; - >::insert(&collator, state); - Ok(().into()) - } - #[pallet::weight( - ::WeightInfo::delegate( - *candidate_delegation_count, - *delegation_count - ) - )] - /// If caller is not a delegator and not a collator, then join the set of delegators - /// If caller is a delegator, then makes delegation to change their delegation state - pub fn delegate( - origin: OriginFor, - candidate: T::AccountId, - amount: BalanceOf, - candidate_delegation_count: u32, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::delegate_with_auto_compound( - candidate, - delegator, - amount, - Percent::zero(), - candidate_delegation_count, - 0, - delegation_count, - ) - } - - /// If caller is not a delegator and not a collator, then join the set of delegators - /// If caller is a delegator, then makes delegation to change their delegation state - /// Sets the auto-compound config for the delegation - #[pallet::weight( - ::WeightInfo::delegate_with_auto_compound( - *candidate_delegation_count, - *candidate_auto_compounding_delegation_count, - *delegation_count, - ) - )] - pub fn delegate_with_auto_compound( - origin: OriginFor, - candidate: T::AccountId, - amount: BalanceOf, - auto_compound: Percent, - candidate_delegation_count: u32, - candidate_auto_compounding_delegation_count: u32, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::delegate_with_auto_compound( - candidate, - delegator, - amount, - auto_compound, - candidate_delegation_count, - candidate_auto_compounding_delegation_count, - delegation_count, - ) - } - - /// DEPRECATED use batch util with schedule_revoke_delegation for all delegations - /// Request to leave the set of delegators. If successful, the caller is scheduled to be - /// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations. - /// Success forbids future delegation requests until the request is invoked or cancelled. - #[pallet::weight(::WeightInfo::schedule_leave_delegators())] - pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegator_schedule_revoke_all(delegator) - } - - /// DEPRECATED use batch util with execute_delegation_request for all delegations - /// Execute the right to exit the set of delegators and revoke all ongoing delegations. - #[pallet::weight(::WeightInfo::execute_leave_delegators(*delegation_count))] - pub fn execute_leave_delegators( - origin: OriginFor, - delegator: T::AccountId, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count) - } - - /// DEPRECATED use batch util with cancel_delegation_request for all delegations - /// Cancel a pending request to exit the set of delegators. Success clears the pending exit - /// request (thereby resetting the delay upon another `leave_delegators` call). - #[pallet::weight(::WeightInfo::cancel_leave_delegators())] - pub fn cancel_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegator_cancel_scheduled_revoke_all(delegator) - } - - #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] - /// Request to revoke an existing delegation. If successful, the delegation is scheduled - /// to be allowed to be revoked via the `execute_delegation_request` extrinsic. - /// The delegation receives no rewards for the rounds while a revoke is pending. - /// A revoke may not be performed if any other scheduled request is pending. - pub fn schedule_revoke_delegation( - origin: OriginFor, - collator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_schedule_revoke(collator, delegator) - } - - #[pallet::weight(::WeightInfo::delegator_bond_more())] - /// Bond more for delegators wrt a specific collator candidate. - pub fn delegator_bond_more( - origin: OriginFor, - candidate: T::AccountId, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - let in_top = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - more.clone(), - )?; - Pallet::::deposit_event(Event::DelegationIncreased { - delegator, - candidate, - amount: more, - in_top, - }); - - Ok(().into()) - } - - #[pallet::weight(::WeightInfo::schedule_delegator_bond_less())] - /// Request bond less for delegators wrt a specific collator candidate. The delegation's - /// rewards for rounds while the request is pending use the reduced bonded amount. - /// A bond less may not be performed if any other scheduled request is pending. - pub fn schedule_delegator_bond_less( - origin: OriginFor, - candidate: T::AccountId, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_schedule_bond_decrease(candidate, delegator, less) - } - - #[pallet::weight(::WeightInfo::execute_delegator_bond_less())] - /// Execute pending request to change an existing delegation - pub fn execute_delegation_request( - origin: OriginFor, - delegator: T::AccountId, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; // we may want to reward caller if caller != delegator - Self::delegation_execute_scheduled_request(candidate, delegator) - } - - #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] - /// Cancel request to change an existing delegation. - pub fn cancel_delegation_request( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_cancel_request(candidate, delegator) - } - - /// Sets the auto-compounding reward percentage for a delegation. - #[pallet::weight(::WeightInfo::set_auto_compound( - *candidate_auto_compounding_delegation_count_hint, - *delegation_count_hint, - ))] - pub fn set_auto_compound( - origin: OriginFor, - candidate: T::AccountId, - value: Percent, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::set_auto_compound( - candidate, - delegator, - value, - candidate_auto_compounding_delegation_count_hint, - delegation_count_hint, - ) - } - - /// Hotfix to remove existing empty entries for candidates that have left. - #[pallet::weight( - T::DbWeight::get().reads_writes(2 * candidates.len() as u64, candidates.len() as u64) - )] - pub fn hotfix_remove_delegation_requests_exited_candidates( - origin: OriginFor, - candidates: Vec, - ) -> DispatchResult { - ensure_signed(origin)?; - ensure!(candidates.len() < 100, >::InsufficientBalance); - for candidate in &candidates { - ensure!( - >::get(&candidate).is_none(), - >::CandidateNotLeaving - ); - ensure!( - >::get(&candidate).is_empty(), - >::CandidateNotLeaving - ); - } - - for candidate in candidates { - >::remove(candidate); - } - - Ok(().into()) - } - } - - /// Represents a payout made via `pay_one_collator_reward`. - pub(crate) enum RewardPayment { - /// A collator was paid - Paid, - /// A collator was skipped for payment. This can happen if they haven't been awarded any - /// points, that is, they did not produce any blocks. - Skipped, - /// All collator payments have been processed. - Finished, - } - - impl Pallet { - pub fn is_delegator(acc: &T::AccountId) -> bool { - >::get(acc).is_some() - } - pub fn is_candidate(acc: &T::AccountId) -> bool { - >::get(acc).is_some() - } - pub fn is_selected_candidate(acc: &T::AccountId) -> bool { - >::get().binary_search(acc).is_ok() - } - /// Returns an account's free balance which is not locked in delegation staking - pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { - let mut balance = T::Currency::free_balance(acc); - if let Some(state) = >::get(acc) { - balance = balance.saturating_sub(state.total()); - } - balance - } - /// Returns an account's free balance which is not locked in collator staking - pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { - let mut balance = T::Currency::free_balance(acc); - if let Some(info) = >::get(acc) { - balance = balance.saturating_sub(info.bond); - } - balance - } - /// Returns a delegations auto-compound value. - pub fn delegation_auto_compound( - candidate: &T::AccountId, - delegator: &T::AccountId, - ) -> Percent { - >::auto_compound(candidate, delegator) - } - /// Caller must ensure candidate is active before calling - pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { - let mut candidates = >::get(); - candidates.remove(&Bond::from_owner(candidate.clone())); - candidates.insert(Bond { - owner: candidate, - amount: total, - }); - >::put(candidates); - } - /// Compute round issuance based on total staked for the given round - fn compute_issuance(staked: BalanceOf) -> BalanceOf { - let config = >::get(); - let round_issuance = crate::inflation::round_issuance_range::(config.round); - // TODO: consider interpolation instead of bounded range - if staked < config.expect.min { - round_issuance.min - } else if staked > config.expect.max { - round_issuance.max - } else { - round_issuance.ideal - } - } - /// Remove delegation from candidate state - /// Amount input should be retrieved from delegator and it informs the storage lookups - pub(crate) fn delegator_leaves_candidate( - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - ) -> DispatchResult { - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.rm_delegation_if_exists::(&candidate, delegator.clone(), amount)?; - let new_total_locked = >::get().saturating_sub(amount); - >::put(new_total_locked); - let new_total = state.total_counted; - >::insert(&candidate, state); - Self::deposit_event(Event::DelegatorLeftCandidate { - delegator: delegator, - candidate: candidate, - unstaked_amount: amount, - total_candidate_staked: new_total, - }); - Ok(()) - } - pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { - // payout is now - delay rounds ago => now - delay > 0 else return early - let delay = T::RewardPaymentDelay::get(); - if now <= delay { - return Weight::zero(); - } - let round_to_payout = now.saturating_sub(delay); - let total_points = >::get(round_to_payout); - if total_points.is_zero() { - return Weight::zero(); - } - let total_staked = >::take(round_to_payout); - let total_issuance = Self::compute_issuance(total_staked); - let mut left_issuance = total_issuance; - // reserve portion of issuance for parachain bond account - let bond_config = >::get(); - let parachain_bond_reserve = bond_config.percent * total_issuance; - if let Ok(imb) = - T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) - { - // update round issuance iff transfer succeeds - left_issuance = left_issuance.saturating_sub(imb.peek()); - Self::deposit_event(Event::ReservedForParachainBond { - account: bond_config.account, - value: imb.peek(), - }); - } - - let payout = DelayedPayout { - round_issuance: total_issuance, - total_staking_reward: left_issuance, - collator_commission: >::get(), - }; - - >::insert(round_to_payout, payout); - T::WeightInfo::prepare_staking_payouts() - } - - /// Wrapper around pay_one_collator_reward which handles the following logic: - /// * whether or not a payout needs to be made - /// * cleaning up when payouts are done - /// * returns the weight consumed by pay_one_collator_reward if applicable - fn handle_delayed_payouts(now: RoundIndex) -> Weight { - let delay = T::RewardPaymentDelay::get(); - - // don't underflow uint - if now < delay { - return Weight::from_ref_time(0u64); - } - - let paid_for_round = now.saturating_sub(delay); - - if let Some(payout_info) = >::get(paid_for_round) { - let result = Self::pay_one_collator_reward(paid_for_round, payout_info); - - // clean up storage items that we no longer need - if matches!(result.0, RewardPayment::Finished) { - >::remove(paid_for_round); - >::remove(paid_for_round); - } - result.1 // weight consumed by pay_one_collator_reward - } else { - Weight::from_ref_time(0u64) - } - } - - /// Payout a single collator from the given round. - /// - /// Returns an optional tuple of (Collator's AccountId, total paid) - /// or None if there were no more payouts to be made for the round. - pub(crate) fn pay_one_collator_reward( - paid_for_round: RoundIndex, - payout_info: DelayedPayout>, - ) -> (RewardPayment, Weight) { - // 'early_weight' tracks weight used for reads/writes done early in this fn before its - // early-exit codepaths. - let mut early_weight = Weight::zero(); - - // TODO: it would probably be optimal to roll Points into the DelayedPayouts storage - // item so that we do fewer reads each block - let total_points = >::get(paid_for_round); - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 0)); - - if total_points.is_zero() { - // TODO: this case is obnoxious... it's a value query, so it could mean one of two - // different logic errors: - // 1. we removed it before we should have - // 2. we called pay_one_collator_reward when we were actually done with deferred - // payouts - log::warn!("pay_one_collator_reward called with no > for the round!"); - return (RewardPayment::Finished, early_weight); - } - - let collator_fee = payout_info.collator_commission; - let collator_issuance = collator_fee * payout_info.round_issuance; - - if let Some((collator, state)) = - >::iter_prefix(paid_for_round).drain().next() - { - // read and kill AtStake - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - - // Take the awarded points for the collator - let pts = >::take(paid_for_round, &collator); - // read and kill AwardedPts - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - if pts == 0 { - return (RewardPayment::Skipped, early_weight); - } - - // 'extra_weight' tracks weight returned from fns that we delegate to which can't be - // known ahead of time. - let mut extra_weight = Weight::zero(); - let pct_due = Perbill::from_rational(pts, total_points); - let total_paid = pct_due * payout_info.total_staking_reward; - let mut amt_due = total_paid; - - let num_delegators = state.delegations.len(); - if state.delegations.is_empty() { - // solo collator with no delegators - extra_weight = extra_weight - .saturating_add(T::PayoutCollatorReward::payout_collator_reward( - paid_for_round, - collator.clone(), - amt_due, - )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator.clone(), - amt_due, - )); - } else { - // pay collator first; commission + due_portion - let collator_pct = Perbill::from_rational(state.bond, state.total); - let commission = pct_due * collator_issuance; - amt_due = amt_due.saturating_sub(commission); - let collator_reward = (collator_pct * amt_due).saturating_add(commission); - extra_weight = extra_weight - .saturating_add(T::PayoutCollatorReward::payout_collator_reward( - paid_for_round, - collator.clone(), - collator_reward, - )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator.clone(), - collator_reward, - )); - - // pay delegators due portion - for BondWithAutoCompound { - owner, - amount, - auto_compound, - } in state.delegations - { - let percent = Perbill::from_rational(amount, state.total); - let due = percent * amt_due; - if !due.is_zero() { - extra_weight = extra_weight.saturating_add(Self::mint_and_compound( - due, - auto_compound.clone(), - collator.clone(), - owner.clone(), - )); - } - } - } - - ( - RewardPayment::Paid, - T::WeightInfo::pay_one_collator_reward(num_delegators as u32) - .saturating_add(extra_weight), - ) - } else { - // Note that we don't clean up storage here; it is cleaned up in - // handle_delayed_payouts() - (RewardPayment::Finished, Weight::from_ref_time(0u64.into())) - } - } - - /// Compute the top `TotalSelected` candidates in the CandidatePool and return - /// a vec of their AccountIds (in the order of selection) - pub fn compute_top_candidates() -> Vec { - let mut candidates = >::get().0; - // order candidates by stake (least to greatest so requires `rev()`) - candidates.sort_by(|a, b| a.amount.cmp(&b.amount)); - let top_n = >::get() as usize; - // choose the top TotalSelected qualified candidates, ordered by stake - let mut collators = candidates - .into_iter() - .rev() - .take(top_n) - .filter(|x| x.amount >= T::MinCollatorStk::get()) - .map(|x| x.owner) - .collect::>(); - collators.sort(); - collators - } - /// Best as in most cumulatively supported in terms of stake - /// Returns [collator_count, delegation_count, total staked] - pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { - let (mut collator_count, mut delegation_count, mut total) = - (0u32, 0u32, BalanceOf::::zero()); - // choose the top TotalSelected qualified candidates, ordered by stake - let collators = Self::compute_top_candidates(); - if collators.is_empty() { - // SELECTION FAILED TO SELECT >=1 COLLATOR => select collators from previous round - let last_round = now.saturating_sub(1u32); - let mut total_per_candidate: BTreeMap> = BTreeMap::new(); - // set this round AtStake to last round AtStake - for (account, snapshot) in >::iter_prefix(last_round) { - collator_count = collator_count.saturating_add(1u32); - delegation_count = - delegation_count.saturating_add(snapshot.delegations.len() as u32); - total = total.saturating_add(snapshot.total); - total_per_candidate.insert(account.clone(), snapshot.total); - >::insert(now, account, snapshot); - } - // `SelectedCandidates` remains unchanged from last round - // emit CollatorChosen event for tools that use this event - for candidate in >::get() { - let snapshot_total = total_per_candidate - .get(&candidate) - .expect("all selected candidates have snapshots"); - Self::deposit_event(Event::CollatorChosen { - round: now, - collator_account: candidate, - total_exposed_amount: *snapshot_total, - }) - } - let weight = T::WeightInfo::select_top_candidates(0, 0); - return (weight, collator_count, delegation_count, total); - } - - // snapshot exposure for round for weighting reward distribution - for account in collators.iter() { - let state = >::get(account) - .expect("all members of CandidateQ must be candidates"); - - collator_count = collator_count.saturating_add(1u32); - delegation_count = delegation_count.saturating_add(state.delegation_count); - total = total.saturating_add(state.total_counted); - let CountedDelegations { - uncounted_stake, - rewardable_delegations, - } = Self::get_rewardable_delegators(&account); - let total_counted = state.total_counted.saturating_sub(uncounted_stake); - - let auto_compounding_delegations = >::get(&account) - .into_iter() - .map(|x| (x.delegator, x.value)) - .collect::>(); - let rewardable_delegations = rewardable_delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner.clone(), - amount: d.amount, - auto_compound: auto_compounding_delegations - .get(&d.owner) - .cloned() - .unwrap_or_else(|| Percent::zero()), - }) - .collect(); - - let snapshot = CollatorSnapshot { - bond: state.bond, - delegations: rewardable_delegations, - total: total_counted, - }; - >::insert(now, account, snapshot); - Self::deposit_event(Event::CollatorChosen { - round: now, - collator_account: account.clone(), - total_exposed_amount: state.total_counted, - }); - } - // insert canonical collator set - >::put(collators); - - let avg_delegator_count = delegation_count.checked_div(collator_count).unwrap_or(0); - let weight = T::WeightInfo::select_top_candidates(collator_count, avg_delegator_count); - (weight, collator_count, delegation_count, total) - } - - /// Apply the delegator intent for revoke and decrease in order to build the - /// effective list of delegators with their intended bond amount. - /// - /// This will: - /// - if [DelegationChange::Revoke] is outstanding, set the bond amount to 0. - /// - if [DelegationChange::Decrease] is outstanding, subtract the bond by specified amount. - /// - else, do nothing - /// - /// The intended bond amounts will be used while calculating rewards. - pub(crate) fn get_rewardable_delegators(collator: &T::AccountId) -> CountedDelegations { - let requests = >::get(collator) - .into_iter() - .map(|x| (x.delegator, x.action)) - .collect::>(); - let mut uncounted_stake = BalanceOf::::zero(); - let rewardable_delegations = >::get(collator) - .expect("all members of CandidateQ must be candidates") - .delegations - .into_iter() - .map(|mut bond| { - bond.amount = match requests.get(&bond.owner) { - None => bond.amount, - Some(DelegationAction::Revoke(_)) => { - uncounted_stake = uncounted_stake.saturating_add(bond.amount); - BalanceOf::::zero() - } - Some(DelegationAction::Decrease(amount)) => { - uncounted_stake = uncounted_stake.saturating_add(*amount); - bond.amount.saturating_sub(*amount) - } - }; - - bond - }) - .collect(); - CountedDelegations { - uncounted_stake, - rewardable_delegations, - } - } - - /// This function exists as a helper to delegator_bond_more & auto_compound functionality. - /// Any changes to this function must align with both user-initiated bond increases and - /// auto-compounding bond increases. - /// Any feature-specific preconditions should be validated before this function is invoked. - /// Any feature-specific events must be emitted after this function is invoked. - pub fn delegation_bond_more_without_event( - delegator: T::AccountId, - candidate: T::AccountId, - more: BalanceOf, - ) -> Result { - ensure!( - !Self::delegation_request_revoke_exists(&candidate, &delegator), - Error::::PendingDelegationRevoke - ); - let mut state = >::get(&delegator).ok_or(Error::::DelegatorDNE)?; - state.increase_delegation::(candidate.clone(), more) - } - - /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. - pub fn mint(amt: BalanceOf, to: T::AccountId) { - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { - Self::deposit_event(Event::Rewarded { - account: to.clone(), - rewards: amount_transferred.peek(), - }); - } - } - - /// Mint a specified reward amount to the collator's account. Emits the [Rewarded] event. - pub fn mint_collator_reward( - _paid_for_round: RoundIndex, - collator_id: T::AccountId, - amt: BalanceOf, - ) -> Weight { - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&collator_id, amt) { - Self::deposit_event(Event::Rewarded { - account: collator_id.clone(), - rewards: amount_transferred.peek(), - }); - } - T::WeightInfo::mint_collator_reward() - } - - /// Mint and compound delegation rewards. The function mints the amount towards the - /// delegator and tries to compound a specified percent of it back towards the delegation. - /// If a scheduled delegation revoke exists, then the amount is only minted, and nothing is - /// compounded. Emits the [Compounded] event. - pub fn mint_and_compound( - amt: BalanceOf, - compound_percent: Percent, - candidate: T::AccountId, - delegator: T::AccountId, - ) -> Weight { - let mut weight = T::WeightInfo::mint_collator_reward(); - if let Ok(amount_transferred) = - T::Currency::deposit_into_existing(&delegator, amt.clone()) - { - Self::deposit_event(Event::Rewarded { - account: delegator.clone(), - rewards: amount_transferred.peek(), - }); - - let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); - if compound_amount.is_zero() { - return weight; - } - - if let Err(err) = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - compound_amount.clone(), - ) { - log::debug!( - "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", - candidate, - delegator, - err - ); - return weight; - }; - weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); - - Pallet::::deposit_event(Event::Compounded { - delegator, - candidate, - amount: compound_amount.clone(), - }); - }; - - weight - } - } - - /// Add reward points to block authors: - /// * 20 points to the block producer for producing a block in the chain - impl Pallet { - fn award_points_to_block_author() { - let author = T::BlockAuthor::get(); - let now = >::get().current; - let score_plus_20 = >::get(now, &author).saturating_add(20); - >::insert(now, author, score_plus_20); - >::mutate(now, |x| *x = x.saturating_add(20)); - } - } - - impl nimbus_primitives::CanAuthor for Pallet { - fn can_author(account: &T::AccountId, _slot: &u32) -> bool { - Self::is_selected_candidate(account) - } - } - - impl Get> for Pallet { - fn get() -> Vec { - Self::selected_candidates() - } - } + use crate::{ + delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, + set::OrderedSet, + traits::*, + types::*, + AutoCompoundConfig, AutoCompoundDelegations, InflationInfo, Range, WeightInfo, + }; + use frame_support::{ + pallet_prelude::*, + traits::{ + tokens::WithdrawReasons, Currency, Get, Imbalance, LockIdentifier, LockableCurrency, + ReservableCurrency, + }, + }; + use frame_system::pallet_prelude::*; + use sp_runtime::{ + traits::{Saturating, Zero}, + Perbill, Percent, + }; + use sp_std::{collections::btree_map::BTreeMap, prelude::*}; + + /// Pallet for parachain staking + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + pub type RoundIndex = u32; + type RewardPoint = u32; + pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + pub const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol"; + pub const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel"; + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The currency type + type Currency: Currency + + ReservableCurrency + + LockableCurrency; + /// The origin for monetary governance + type MonetaryGovernanceOrigin: EnsureOrigin; + /// Minimum number of blocks per round + #[pallet::constant] + type MinBlocksPerRound: Get; + /// Number of rounds that candidates remain bonded before exit request is executable + #[pallet::constant] + type LeaveCandidatesDelay: Get; + /// Number of rounds candidate requests to decrease self-bond must wait to be executable + #[pallet::constant] + type CandidateBondLessDelay: Get; + /// Number of rounds that delegators remain bonded before exit request is executable + #[pallet::constant] + type LeaveDelegatorsDelay: Get; + /// Number of rounds that delegations remain bonded before revocation request is executable + #[pallet::constant] + type RevokeDelegationDelay: Get; + /// Number of rounds that delegation less requests must wait before executable + #[pallet::constant] + type DelegationBondLessDelay: Get; + /// Number of rounds after which block authors are rewarded + #[pallet::constant] + type RewardPaymentDelay: Get; + /// Minimum number of selected candidates every round + #[pallet::constant] + type MinSelectedCandidates: Get; + /// Maximum top delegations counted per candidate + #[pallet::constant] + type MaxTopDelegationsPerCandidate: Get; + /// Maximum bottom delegations (not counted) per candidate + #[pallet::constant] + type MaxBottomDelegationsPerCandidate: Get; + /// Maximum delegations per delegator + #[pallet::constant] + type MaxDelegationsPerDelegator: Get; + /// Minimum stake required for any candidate to be in `SelectedCandidates` for the round + #[pallet::constant] + type MinCollatorStk: Get>; + /// Minimum stake required for any account to be a collator candidate + #[pallet::constant] + type MinCandidateStk: Get>; + /// Minimum stake for any registered on-chain account to delegate + #[pallet::constant] + type MinDelegation: Get>; + /// Minimum stake for any registered on-chain account to be a delegator + #[pallet::constant] + type MinDelegatorStk: Get>; + /// Get the current block author + type BlockAuthor: Get; + /// Handler to notify the runtime when a collator is paid. + /// If you don't need it, you can specify the type `()`. + type OnCollatorPayout: OnCollatorPayout>; + /// Handler to distribute a collator's reward. + /// To use the default implementation of minting rewards, specify the type `()`. + type PayoutCollatorReward: PayoutCollatorReward; + /// Handler to notify the runtime when a new round begin. + /// If you don't need it, you can specify the type `()`. + type OnNewRound: OnNewRound; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + DelegatorDNE, + DelegatorDNEinTopNorBottom, + DelegatorDNEInDelegatorSet, + CandidateDNE, + DelegationDNE, + DelegatorExists, + CandidateExists, + CandidateBondBelowMin, + InsufficientBalance, + DelegatorBondBelowMin, + DelegationBelowMin, + AlreadyOffline, + AlreadyActive, + DelegatorAlreadyLeaving, + DelegatorNotLeaving, + DelegatorCannotLeaveYet, + CannotDelegateIfLeaving, + CandidateAlreadyLeaving, + CandidateNotLeaving, + CandidateCannotLeaveYet, + CannotGoOnlineIfLeaving, + ExceedMaxDelegationsPerDelegator, + AlreadyDelegatedCandidate, + InvalidSchedule, + CannotSetBelowMin, + RoundLengthMustBeGreaterThanTotalSelectedCollators, + NoWritingSameValue, + TooLowCandidateCountWeightHintJoinCandidates, + TooLowCandidateCountWeightHintCancelLeaveCandidates, + TooLowCandidateCountToLeaveCandidates, + TooLowDelegationCountToDelegate, + TooLowCandidateDelegationCountToDelegate, + TooLowCandidateDelegationCountToLeaveCandidates, + TooLowDelegationCountToLeaveDelegators, + PendingCandidateRequestsDNE, + PendingCandidateRequestAlreadyExists, + PendingCandidateRequestNotDueYet, + PendingDelegationRequestDNE, + PendingDelegationRequestAlreadyExists, + PendingDelegationRequestNotDueYet, + CannotDelegateLessThanOrEqualToLowestBottomWhenFull, + PendingDelegationRevoke, + TooLowDelegationCountToAutoCompound, + TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + TooLowCandidateAutoCompoundingDelegationCountToDelegate, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// Started new round. + NewRound { + starting_block: T::BlockNumber, + round: RoundIndex, + selected_collators_number: u32, + total_balance: BalanceOf, + }, + /// Account joined the set of collator candidates. + JoinedCollatorCandidates { + account: T::AccountId, + amount_locked: BalanceOf, + new_total_amt_locked: BalanceOf, + }, + /// Candidate selected for collators. Total Exposed Amount includes all delegations. + CollatorChosen { + round: RoundIndex, + collator_account: T::AccountId, + total_exposed_amount: BalanceOf, + }, + /// Candidate requested to decrease a self bond. + CandidateBondLessRequested { + candidate: T::AccountId, + amount_to_decrease: BalanceOf, + execute_round: RoundIndex, + }, + /// Candidate has increased a self bond. + CandidateBondedMore { + candidate: T::AccountId, + amount: BalanceOf, + new_total_bond: BalanceOf, + }, + /// Candidate has decreased a self bond. + CandidateBondedLess { + candidate: T::AccountId, + amount: BalanceOf, + new_bond: BalanceOf, + }, + /// Candidate temporarily leave the set of collator candidates without unbonding. + CandidateWentOffline { candidate: T::AccountId }, + /// Candidate rejoins the set of collator candidates. + CandidateBackOnline { candidate: T::AccountId }, + /// Candidate has requested to leave the set of candidates. + CandidateScheduledExit { + exit_allowed_round: RoundIndex, + candidate: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Cancelled request to leave the set of candidates. + CancelledCandidateExit { candidate: T::AccountId }, + /// Cancelled request to decrease candidate's bond. + CancelledCandidateBondLess { + candidate: T::AccountId, + amount: BalanceOf, + execute_round: RoundIndex, + }, + /// Candidate has left the set of candidates. + CandidateLeft { + ex_candidate: T::AccountId, + unlocked_amount: BalanceOf, + new_total_amt_locked: BalanceOf, + }, + /// Delegator requested to decrease a bond for the collator candidate. + DelegationDecreaseScheduled { + delegator: T::AccountId, + candidate: T::AccountId, + amount_to_decrease: BalanceOf, + execute_round: RoundIndex, + }, + // Delegation increased. + DelegationIncreased { + delegator: T::AccountId, + candidate: T::AccountId, + amount: BalanceOf, + in_top: bool, + }, + // Delegation decreased. + DelegationDecreased { + delegator: T::AccountId, + candidate: T::AccountId, + amount: BalanceOf, + in_top: bool, + }, + /// Delegator requested to leave the set of delegators. + DelegatorExitScheduled { + round: RoundIndex, + delegator: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Delegator requested to revoke delegation. + DelegationRevocationScheduled { + round: RoundIndex, + delegator: T::AccountId, + candidate: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Delegator has left the set of delegators. + DelegatorLeft { delegator: T::AccountId, unstaked_amount: BalanceOf }, + /// Delegation revoked. + DelegationRevoked { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Delegation kicked. + DelegationKicked { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Cancelled a pending request to exit the set of delegators. + DelegatorExitCancelled { delegator: T::AccountId }, + /// Cancelled request to change an existing delegation. + CancelledDelegationRequest { + delegator: T::AccountId, + cancelled_request: CancelledScheduledRequest>, + collator: T::AccountId, + }, + /// New delegation (increase of the existing one). + Delegation { + delegator: T::AccountId, + locked_amount: BalanceOf, + candidate: T::AccountId, + delegator_position: DelegatorAdded>, + auto_compound: Percent, + }, + /// Delegation from candidate state has been remove. + DelegatorLeftCandidate { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + total_candidate_staked: BalanceOf, + }, + /// Paid the account (delegator or collator) the balance as liquid rewards. + Rewarded { account: T::AccountId, rewards: BalanceOf }, + /// Transferred to account which holds funds reserved for parachain bond. + ReservedForParachainBond { account: T::AccountId, value: BalanceOf }, + /// Account (re)set for parachain bond treasury. + ParachainBondAccountSet { old: T::AccountId, new: T::AccountId }, + /// Percent of inflation reserved for parachain bond (re)set. + ParachainBondReservePercentSet { old: Percent, new: Percent }, + /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) + InflationSet { + annual_min: Perbill, + annual_ideal: Perbill, + annual_max: Perbill, + round_min: Perbill, + round_ideal: Perbill, + round_max: Perbill, + }, + /// Staking expectations set. + StakeExpectationsSet { + expect_min: BalanceOf, + expect_ideal: BalanceOf, + expect_max: BalanceOf, + }, + /// Set total selected candidates to this value. + TotalSelectedSet { old: u32, new: u32 }, + /// Set collator commission to this value. + CollatorCommissionSet { old: Perbill, new: Perbill }, + /// Set blocks per round + BlocksPerRoundSet { + current_round: RoundIndex, + first_block: T::BlockNumber, + old: u32, + new: u32, + new_per_round_inflation_min: Perbill, + new_per_round_inflation_ideal: Perbill, + new_per_round_inflation_max: Perbill, + }, + /// Auto-compounding reward percent was set for a delegation. + AutoCompoundSet { candidate: T::AccountId, delegator: T::AccountId, value: Percent }, + /// Compounded a portion of rewards towards the delegation. + Compounded { candidate: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(n: T::BlockNumber) -> Weight { + let mut weight = T::WeightInfo::base_on_initialize(); + + let mut round = >::get(); + if round.should_update(n) { + // mutate round + round.update(n); + // notify that new round begin + weight = weight.saturating_add(T::OnNewRound::on_new_round(round.current)); + // pay all stakers for T::RewardPaymentDelay rounds ago + weight = weight.saturating_add(Self::prepare_staking_payouts(round.current)); + // select top collator candidates for next round + let (extra_weight, collator_count, _delegation_count, total_staked) = + Self::select_top_candidates(round.current); + weight = weight.saturating_add(extra_weight); + // start next round + >::put(round); + // snapshot total stake + >::insert(round.current, >::get()); + Self::deposit_event(Event::NewRound { + starting_block: round.first, + round: round.current, + selected_collators_number: collator_count, + total_balance: total_staked, + }); + // account for Round and Staked writes + weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 2)); + } else { + weight = weight.saturating_add(Self::handle_delayed_payouts(round.current)); + } + + // add on_finalize weight + // read: Author, Points, AwardedPts + // write: Points, AwardedPts + weight = weight.saturating_add(T::DbWeight::get().reads_writes(3, 2)); + weight + } + fn on_finalize(_n: T::BlockNumber) { + Self::award_points_to_block_author(); + } + } + + #[pallet::storage] + #[pallet::getter(fn collator_commission)] + /// Commission percent taken off of rewards for all collators + type CollatorCommission = StorageValue<_, Perbill, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total_selected)] + /// The total candidates selected every round + pub(crate) type TotalSelected = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn parachain_bond_info)] + /// Parachain bond config info { account, percent_of_inflation } + pub(crate) type ParachainBondInfo = + StorageValue<_, ParachainBondConfig, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn round)] + /// Current round index and next round scheduled transition + pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn delegator_state)] + /// Get delegator state associated with an account if account is delegating else None + pub(crate) type DelegatorState = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegator>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn candidate_info)] + /// Get collator candidate info associated with an account if account is candidate else None + pub(crate) type CandidateInfo = + StorageMap<_, Twox64Concat, T::AccountId, CandidateMetadata>, OptionQuery>; + + /// Stores outstanding delegation requests per collator. + #[pallet::storage] + #[pallet::getter(fn delegation_scheduled_requests)] + pub(crate) type DelegationScheduledRequests = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec>>, + ValueQuery, + >; + + /// Stores auto-compounding configuration per collator. + #[pallet::storage] + #[pallet::getter(fn auto_compounding_delegations)] + pub(crate) type AutoCompoundingDelegations = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec>, + ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn top_delegations)] + /// Top delegations for collator candidate + pub(crate) type TopDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn bottom_delegations)] + /// Bottom delegations for collator candidate + pub(crate) type BottomDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn selected_candidates)] + /// The collator candidates selected for the current round + type SelectedCandidates = StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total)] + /// Total capital locked by this staking pallet + pub(crate) type Total = StorageValue<_, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn candidate_pool)] + /// The pool of collator candidates, each with their total backing stake + pub(crate) type CandidatePool = + StorageValue<_, OrderedSet>>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn at_stake)] + /// Snapshot of collator delegation stake at the start of the round + pub type AtStake = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + CollatorSnapshot>, + ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn delayed_payouts)] + /// Delayed payouts + pub type DelayedPayouts = + StorageMap<_, Twox64Concat, RoundIndex, DelayedPayout>, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn staked)] + /// Total counted stake for selected candidates in the round + pub type Staked = StorageMap<_, Twox64Concat, RoundIndex, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn inflation_config)] + /// Inflation configuration + pub type InflationConfig = StorageValue<_, InflationInfo>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn points)] + /// Total points awarded to collators for block production in the round + pub type Points = StorageMap<_, Twox64Concat, RoundIndex, RewardPoint, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn awarded_pts)] + /// Points for each collator per round + pub type AwardedPts = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + RewardPoint, + ValueQuery, + >; + + #[pallet::genesis_config] + pub struct GenesisConfig { + /// Initialize balance and register all as collators: `(collator AccountId, balance Amount)` + pub candidates: Vec<(T::AccountId, BalanceOf)>, + /// Initialize balance and make delegations: + /// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding Percent)` + pub delegations: Vec<(T::AccountId, T::AccountId, BalanceOf, Percent)>, + /// Inflation configuration + pub inflation_config: InflationInfo>, + /// Default fixed percent a collator takes off the top of due rewards + pub collator_commission: Perbill, + /// Default percent of inflation set aside for parachain bond every round + pub parachain_bond_reserve_percent: Percent, + /// Default number of blocks in a round + pub blocks_per_round: u32, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + candidates: vec![], + delegations: vec![], + inflation_config: Default::default(), + collator_commission: Default::default(), + parachain_bond_reserve_percent: Default::default(), + blocks_per_round: 1u32, + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + assert!(self.blocks_per_round > 0, "Blocks per round must be > 0"); + >::put(self.inflation_config.clone()); + let mut candidate_count = 0u32; + // Initialize the candidates + for &(ref candidate, balance) in &self.candidates { + assert!( + >::get_collator_stakable_free_balance(candidate) >= balance, + "Account does not have enough balance to bond as a candidate." + ); + if let Err(error) = >::join_candidates( + T::RuntimeOrigin::from(Some(candidate.clone()).into()), + balance, + candidate_count, + ) { + log::warn!("Join candidates failed in genesis with error {:?}", error); + } else { + candidate_count = candidate_count.saturating_add(1u32); + } + } + + let mut col_delegator_count: BTreeMap = BTreeMap::new(); + let mut col_auto_compound_delegator_count: BTreeMap = + BTreeMap::new(); + let mut del_delegation_count: BTreeMap = BTreeMap::new(); + // Initialize the delegations + for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { + assert!( + >::get_delegator_stakable_free_balance(delegator) >= balance, + "Account does not have enough balance to place delegation." + ); + let cd_count = + if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; + let dd_count = + if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; + let cd_auto_compound_count = + col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); + if let Err(error) = >::delegate_with_auto_compound( + T::RuntimeOrigin::from(Some(delegator.clone()).into()), + target.clone(), + balance, + auto_compound, + cd_count, + cd_auto_compound_count, + dd_count, + ) { + log::warn!("Delegate failed in genesis with error {:?}", error); + } else { + if let Some(x) = col_delegator_count.get_mut(target) { + *x = x.saturating_add(1u32); + } else { + col_delegator_count.insert(target.clone(), 1u32); + }; + if let Some(x) = del_delegation_count.get_mut(delegator) { + *x = x.saturating_add(1u32); + } else { + del_delegation_count.insert(delegator.clone(), 1u32); + }; + if !auto_compound.is_zero() { + col_auto_compound_delegator_count + .entry(target.clone()) + .and_modify(|x| *x = x.saturating_add(1)) + .or_insert(1); + } + } + } + // Set collator commission to default config + >::put(self.collator_commission); + // Set parachain bond config to default config + >::put(ParachainBondConfig { + // must be set soon; if not => due inflation will be sent to collators/delegators + account: T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + percent: self.parachain_bond_reserve_percent, + }); + // Set total selected candidates to minimum config + >::put(T::MinSelectedCandidates::get()); + // Choose top TotalSelected collator candidates + let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); + // Start Round 1 at Block 0 + let round: RoundInfo = + RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); + >::put(round); + // Snapshot total stake + >::insert(1u32, >::get()); + >::deposit_event(Event::NewRound { + starting_block: T::BlockNumber::zero(), + round: 1u32, + selected_collators_number: v_count, + total_balance: total_staked, + }); + } + } + + #[pallet::call] + impl Pallet { + #[pallet::weight(::WeightInfo::set_staking_expectations())] + /// Set the expectations for total staked. These expectations determine the issuance for + /// the round according to logic in `fn compute_issuance` + pub fn set_staking_expectations( + origin: OriginFor, + expectations: Range>, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + ensure!(expectations.is_valid(), Error::::InvalidSchedule); + let mut config = >::get(); + ensure!(config.expect != expectations, Error::::NoWritingSameValue); + config.set_expectations(expectations); + Self::deposit_event(Event::StakeExpectationsSet { + expect_min: config.expect.min, + expect_ideal: config.expect.ideal, + expect_max: config.expect.max, + }); + >::put(config); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_inflation())] + /// Set the annual inflation rate to derive per-round inflation + pub fn set_inflation( + origin: OriginFor, + schedule: Range, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + ensure!(schedule.is_valid(), Error::::InvalidSchedule); + let mut config = >::get(); + ensure!(config.annual != schedule, Error::::NoWritingSameValue); + config.annual = schedule; + config.set_round_from_annual::(schedule); + Self::deposit_event(Event::InflationSet { + annual_min: config.annual.min, + annual_ideal: config.annual.ideal, + annual_max: config.annual.max, + round_min: config.round.min, + round_ideal: config.round.ideal, + round_max: config.round.max, + }); + >::put(config); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_parachain_bond_account())] + /// Set the account that will hold funds set aside for parachain bond + pub fn set_parachain_bond_account( + origin: OriginFor, + new: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + let ParachainBondConfig { account: old, percent } = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(ParachainBondConfig { account: new.clone(), percent }); + Self::deposit_event(Event::ParachainBondAccountSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] + /// Set the percent of inflation set aside for parachain bond + pub fn set_parachain_bond_reserve_percent( + origin: OriginFor, + new: Percent, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + let ParachainBondConfig { account, percent: old } = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(ParachainBondConfig { account, percent: new }); + Self::deposit_event(Event::ParachainBondReservePercentSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_total_selected())] + /// Set the total number of collator candidates selected per round + /// - changes are not applied until the start of the next round + pub fn set_total_selected(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + ensure!(new >= T::MinSelectedCandidates::get(), Error::::CannotSetBelowMin); + let old = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + ensure!( + new <= >::get().length, + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + >::put(new); + Self::deposit_event(Event::TotalSelectedSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_collator_commission())] + /// Set the commission for all collators + pub fn set_collator_commission( + origin: OriginFor, + new: Perbill, + ) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + let old = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(new); + Self::deposit_event(Event::CollatorCommissionSet { old, new }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::set_blocks_per_round())] + /// Set blocks per round + /// - if called with `new` less than length of current round, will transition immediately + /// in the next block + /// - also updates per-round inflation config + pub fn set_blocks_per_round(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); + let mut round = >::get(); + let (now, first, old) = (round.current, round.first, round.length); + ensure!(old != new, Error::::NoWritingSameValue); + ensure!( + new >= >::get(), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + round.length = new; + // update per-round inflation given new rounds per year + let mut inflation_config = >::get(); + inflation_config.reset_round(new); + >::put(round); + Self::deposit_event(Event::BlocksPerRoundSet { + current_round: now, + first_block: first, + old, + new, + new_per_round_inflation_min: inflation_config.round.min, + new_per_round_inflation_ideal: inflation_config.round.ideal, + new_per_round_inflation_max: inflation_config.round.max, + }); + >::put(inflation_config); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::join_candidates(*candidate_count))] + /// Join the set of collator candidates + pub fn join_candidates( + origin: OriginFor, + bond: BalanceOf, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let acc = ensure_signed(origin)?; + ensure!(!Self::is_candidate(&acc), Error::::CandidateExists); + ensure!(!Self::is_delegator(&acc), Error::::DelegatorExists); + ensure!(bond >= T::MinCandidateStk::get(), Error::::CandidateBondBelowMin); + let mut candidates = >::get(); + let old_count = candidates.0.len() as u32; + ensure!( + candidate_count >= old_count, + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + ensure!( + candidates.insert(Bond { owner: acc.clone(), amount: bond }), + Error::::CandidateExists + ); + ensure!( + Self::get_collator_stakable_free_balance(&acc) >= bond, + Error::::InsufficientBalance, + ); + T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); + let candidate = CandidateMetadata::new(bond); + >::insert(&acc, candidate); + let empty_delegations: Delegations> = Default::default(); + // insert empty top delegations + >::insert(&acc, empty_delegations.clone()); + // insert empty bottom delegations + >::insert(&acc, empty_delegations); + >::put(candidates); + let new_total = >::get().saturating_add(bond); + >::put(new_total); + Self::deposit_event(Event::JoinedCollatorCandidates { + account: acc, + amount_locked: bond, + new_total_amt_locked: new_total, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] + /// Request to leave the set of candidates. If successful, the account is immediately + /// removed from the candidate pool to prevent selection as a collator. + pub fn schedule_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let (now, when) = state.schedule_leave::()?; + let mut candidates = >::get(); + ensure!( + candidate_count >= candidates.0.len() as u32, + Error::::TooLowCandidateCountToLeaveCandidates + ); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateScheduledExit { + exit_allowed_round: now, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + #[pallet::weight( + ::WeightInfo::execute_leave_candidates(*candidate_delegation_count) + )] + /// Execute leave candidates request + pub fn execute_leave_candidates( + origin: OriginFor, + candidate: T::AccountId, + candidate_delegation_count: u32, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + ensure!( + state.delegation_count <= candidate_delegation_count, + Error::::TooLowCandidateDelegationCountToLeaveCandidates + ); + state.can_leave::()?; + let return_stake = |bond: Bond>| -> DispatchResult { + // remove delegation from delegator state + let mut delegator = DelegatorState::::get(&bond.owner).expect( + "Collator state and delegator state are consistent. + Collator state has a record of this delegation. Therefore, + Delegator state also has a record. qed.", + ); + + if let Some(remaining) = delegator.rm_delegation::(&candidate) { + Self::delegation_remove_request_with_state( + &candidate, + &bond.owner, + &mut delegator, + ); + >::remove_auto_compound(&candidate, &bond.owner); + + if remaining.is_zero() { + // we do not remove the scheduled delegation requests from other collators + // since it is assumed that they were removed incrementally before only the + // last delegation was left. + >::remove(&bond.owner); + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); + } else { + >::insert(&bond.owner, delegator); + } + } else { + // TODO: review. we assume here that this delegator has no remaining staked + // balance, so we ensure the lock is cleared + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); + } + Ok(()) + }; + // total backing stake is at least the candidate self bond + let mut total_backing = state.bond; + // return all top delegations + let top_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in top_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(top_delegations.total); + // return all bottom delegations + let bottom_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in bottom_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(bottom_delegations.total); + // return stake to collator + T::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + let new_total_staked = >::get().saturating_sub(total_backing); + >::put(new_total_staked); + Self::deposit_event(Event::CandidateLeft { + ex_candidate: candidate, + unlocked_amount: total_backing, + new_total_amt_locked: new_total_staked, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] + /// Cancel open request to leave candidates + /// - only callable by collator account + /// - result upon successful call is the candidate is active in the candidate pool + pub fn cancel_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(state.is_leaving(), Error::::CandidateNotLeaving); + state.go_online(); + let mut candidates = >::get(); + ensure!( + candidates.0.len() as u32 <= candidate_count, + Error::::TooLowCandidateCountWeightHintCancelLeaveCandidates + ); + ensure!( + candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), + Error::::AlreadyActive + ); + >::put(candidates); + >::insert(&collator, state); + Self::deposit_event(Event::CancelledCandidateExit { candidate: collator }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::go_offline())] + /// Temporarily leave the set of collator candidates without unbonding + pub fn go_offline(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(state.is_active(), Error::::AlreadyOffline); + state.go_offline(); + let mut candidates = >::get(); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateWentOffline { candidate: collator }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::go_online())] + /// Rejoin the set of collator candidates if previously had called `go_offline` + pub fn go_online(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(!state.is_active(), Error::::AlreadyActive); + ensure!(!state.is_leaving(), Error::::CannotGoOnlineIfLeaving); + state.go_online(); + let mut candidates = >::get(); + ensure!( + candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), + Error::::AlreadyActive + ); + >::put(candidates); + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBackOnline { candidate: collator }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::candidate_bond_more())] + /// Increase collator candidate self bond by `more` + pub fn candidate_bond_more( + origin: OriginFor, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + state.bond_more::(collator.clone(), more)?; + let (is_active, total_counted) = (state.is_active(), state.total_counted); + >::insert(&collator, state); + if is_active { + Self::update_active(collator, total_counted); + } + Ok(().into()) + } + #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] + /// Request by collator candidate to decrease self bond by `less` + pub fn schedule_candidate_bond_less( + origin: OriginFor, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let when = state.schedule_bond_less::(less)?; + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBondLessRequested { + candidate: collator, + amount_to_decrease: less, + execute_round: when, + }); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::execute_candidate_bond_less())] + /// Execute pending request to adjust the collator candidate self bond + pub fn execute_candidate_bond_less( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; // we may want to reward this if caller != candidate + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.execute_bond_less::(candidate.clone())?; + >::insert(&candidate, state); + Ok(().into()) + } + #[pallet::weight(::WeightInfo::cancel_candidate_bond_less())] + /// Cancel pending request to adjust the collator candidate self bond + pub fn cancel_candidate_bond_less(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + state.cancel_bond_less::(collator.clone())?; + >::insert(&collator, state); + Ok(().into()) + } + #[pallet::weight( + ::WeightInfo::delegate( + *candidate_delegation_count, + *delegation_count + ) + )] + /// If caller is not a delegator and not a collator, then join the set of delegators + /// If caller is a delegator, then makes delegation to change their delegation state + pub fn delegate( + origin: OriginFor, + candidate: T::AccountId, + amount: BalanceOf, + candidate_delegation_count: u32, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::delegate_with_auto_compound( + candidate, + delegator, + amount, + Percent::zero(), + candidate_delegation_count, + 0, + delegation_count, + ) + } + + /// If caller is not a delegator and not a collator, then join the set of delegators + /// If caller is a delegator, then makes delegation to change their delegation state + /// Sets the auto-compound config for the delegation + #[pallet::weight( + ::WeightInfo::delegate_with_auto_compound( + *candidate_delegation_count, + *candidate_auto_compounding_delegation_count, + *delegation_count, + ) + )] + pub fn delegate_with_auto_compound( + origin: OriginFor, + candidate: T::AccountId, + amount: BalanceOf, + auto_compound: Percent, + candidate_delegation_count: u32, + candidate_auto_compounding_delegation_count: u32, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::delegate_with_auto_compound( + candidate, + delegator, + amount, + auto_compound, + candidate_delegation_count, + candidate_auto_compounding_delegation_count, + delegation_count, + ) + } + + /// DEPRECATED use batch util with schedule_revoke_delegation for all delegations + /// Request to leave the set of delegators. If successful, the caller is scheduled to be + /// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations. + /// Success forbids future delegation requests until the request is invoked or cancelled. + #[pallet::weight(::WeightInfo::schedule_leave_delegators())] + pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegator_schedule_revoke_all(delegator) + } + + /// DEPRECATED use batch util with execute_delegation_request for all delegations + /// Execute the right to exit the set of delegators and revoke all ongoing delegations. + #[pallet::weight(::WeightInfo::execute_leave_delegators(*delegation_count))] + pub fn execute_leave_delegators( + origin: OriginFor, + delegator: T::AccountId, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count) + } + + /// DEPRECATED use batch util with cancel_delegation_request for all delegations + /// Cancel a pending request to exit the set of delegators. Success clears the pending exit + /// request (thereby resetting the delay upon another `leave_delegators` call). + #[pallet::weight(::WeightInfo::cancel_leave_delegators())] + pub fn cancel_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegator_cancel_scheduled_revoke_all(delegator) + } + + #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] + /// Request to revoke an existing delegation. If successful, the delegation is scheduled + /// to be allowed to be revoked via the `execute_delegation_request` extrinsic. + /// The delegation receives no rewards for the rounds while a revoke is pending. + /// A revoke may not be performed if any other scheduled request is pending. + pub fn schedule_revoke_delegation( + origin: OriginFor, + collator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_schedule_revoke(collator, delegator) + } + + #[pallet::weight(::WeightInfo::delegator_bond_more())] + /// Bond more for delegators wrt a specific collator candidate. + pub fn delegator_bond_more( + origin: OriginFor, + candidate: T::AccountId, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + let in_top = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + more, + )?; + Pallet::::deposit_event(Event::DelegationIncreased { + delegator, + candidate, + amount: more, + in_top, + }); + + Ok(().into()) + } + + #[pallet::weight(::WeightInfo::schedule_delegator_bond_less())] + /// Request bond less for delegators wrt a specific collator candidate. The delegation's + /// rewards for rounds while the request is pending use the reduced bonded amount. + /// A bond less may not be performed if any other scheduled request is pending. + pub fn schedule_delegator_bond_less( + origin: OriginFor, + candidate: T::AccountId, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_schedule_bond_decrease(candidate, delegator, less) + } + + #[pallet::weight(::WeightInfo::execute_delegator_bond_less())] + /// Execute pending request to change an existing delegation + pub fn execute_delegation_request( + origin: OriginFor, + delegator: T::AccountId, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; // we may want to reward caller if caller != delegator + Self::delegation_execute_scheduled_request(candidate, delegator) + } + + #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] + /// Cancel request to change an existing delegation. + pub fn cancel_delegation_request( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_cancel_request(candidate, delegator) + } + + /// Sets the auto-compounding reward percentage for a delegation. + #[pallet::weight(::WeightInfo::set_auto_compound( + *candidate_auto_compounding_delegation_count_hint, + *delegation_count_hint, + ))] + pub fn set_auto_compound( + origin: OriginFor, + candidate: T::AccountId, + value: Percent, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::set_auto_compound( + candidate, + delegator, + value, + candidate_auto_compounding_delegation_count_hint, + delegation_count_hint, + ) + } + + /// Hotfix to remove existing empty entries for candidates that have left. + #[pallet::weight( + T::DbWeight::get().reads_writes(2 * candidates.len() as u64, candidates.len() as u64) + )] + pub fn hotfix_remove_delegation_requests_exited_candidates( + origin: OriginFor, + candidates: Vec, + ) -> DispatchResult { + ensure_signed(origin)?; + ensure!(candidates.len() < 100, >::InsufficientBalance); + for candidate in &candidates { + ensure!( + >::get(candidate).is_none(), + >::CandidateNotLeaving + ); + ensure!( + >::get(candidate).is_empty(), + >::CandidateNotLeaving + ); + } + + for candidate in candidates { + >::remove(candidate); + } + + Ok(()) + } + } + + /// Represents a payout made via `pay_one_collator_reward`. + pub(crate) enum RewardPayment { + /// A collator was paid + Paid, + /// A collator was skipped for payment. This can happen if they haven't been awarded any + /// points, that is, they did not produce any blocks. + Skipped, + /// All collator payments have been processed. + Finished, + } + + impl Pallet { + pub fn is_delegator(acc: &T::AccountId) -> bool { + >::get(acc).is_some() + } + pub fn is_candidate(acc: &T::AccountId) -> bool { + >::get(acc).is_some() + } + pub fn is_selected_candidate(acc: &T::AccountId) -> bool { + >::get().binary_search(acc).is_ok() + } + /// Returns an account's free balance which is not locked in delegation staking + pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { + let mut balance = T::Currency::free_balance(acc); + if let Some(state) = >::get(acc) { + balance = balance.saturating_sub(state.total()); + } + balance + } + /// Returns an account's free balance which is not locked in collator staking + pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { + let mut balance = T::Currency::free_balance(acc); + if let Some(info) = >::get(acc) { + balance = balance.saturating_sub(info.bond); + } + balance + } + /// Returns a delegations auto-compound value. + pub fn delegation_auto_compound( + candidate: &T::AccountId, + delegator: &T::AccountId, + ) -> Percent { + >::auto_compound(candidate, delegator) + } + /// Caller must ensure candidate is active before calling + pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { + let mut candidates = >::get(); + candidates.remove(&Bond::from_owner(candidate.clone())); + candidates.insert(Bond { owner: candidate, amount: total }); + >::put(candidates); + } + /// Compute round issuance based on total staked for the given round + fn compute_issuance(staked: BalanceOf) -> BalanceOf { + let config = >::get(); + let round_issuance = crate::inflation::round_issuance_range::(config.round); + // TODO: consider interpolation instead of bounded range + if staked < config.expect.min { + round_issuance.min + } else if staked > config.expect.max { + round_issuance.max + } else { + round_issuance.ideal + } + } + /// Remove delegation from candidate state + /// Amount input should be retrieved from delegator and it informs the storage lookups + pub(crate) fn delegator_leaves_candidate( + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.rm_delegation_if_exists::(&candidate, delegator.clone(), amount)?; + let new_total_locked = >::get().saturating_sub(amount); + >::put(new_total_locked); + let new_total = state.total_counted; + >::insert(&candidate, state); + Self::deposit_event(Event::DelegatorLeftCandidate { + delegator, + candidate, + unstaked_amount: amount, + total_candidate_staked: new_total, + }); + Ok(()) + } + pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { + // payout is now - delay rounds ago => now - delay > 0 else return early + let delay = T::RewardPaymentDelay::get(); + if now <= delay { + return Weight::zero(); + } + let round_to_payout = now.saturating_sub(delay); + let total_points = >::get(round_to_payout); + if total_points.is_zero() { + return Weight::zero(); + } + let total_staked = >::take(round_to_payout); + let total_issuance = Self::compute_issuance(total_staked); + let mut left_issuance = total_issuance; + // reserve portion of issuance for parachain bond account + let bond_config = >::get(); + let parachain_bond_reserve = bond_config.percent * total_issuance; + if let Ok(imb) = + T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) + { + // update round issuance iff transfer succeeds + left_issuance = left_issuance.saturating_sub(imb.peek()); + Self::deposit_event(Event::ReservedForParachainBond { + account: bond_config.account, + value: imb.peek(), + }); + } + + let payout = DelayedPayout { + round_issuance: total_issuance, + total_staking_reward: left_issuance, + collator_commission: >::get(), + }; + + >::insert(round_to_payout, payout); + T::WeightInfo::prepare_staking_payouts() + } + + /// Wrapper around pay_one_collator_reward which handles the following logic: + /// * whether or not a payout needs to be made + /// * cleaning up when payouts are done + /// * returns the weight consumed by pay_one_collator_reward if applicable + fn handle_delayed_payouts(now: RoundIndex) -> Weight { + let delay = T::RewardPaymentDelay::get(); + + // don't underflow uint + if now < delay { + return Weight::from_ref_time(0u64); + } + + let paid_for_round = now.saturating_sub(delay); + + if let Some(payout_info) = >::get(paid_for_round) { + let result = Self::pay_one_collator_reward(paid_for_round, payout_info); + + // clean up storage items that we no longer need + if matches!(result.0, RewardPayment::Finished) { + >::remove(paid_for_round); + >::remove(paid_for_round); + } + result.1 // weight consumed by pay_one_collator_reward + } else { + Weight::from_ref_time(0u64) + } + } + + /// Payout a single collator from the given round. + /// + /// Returns an optional tuple of (Collator's AccountId, total paid) + /// or None if there were no more payouts to be made for the round. + pub(crate) fn pay_one_collator_reward( + paid_for_round: RoundIndex, + payout_info: DelayedPayout>, + ) -> (RewardPayment, Weight) { + // 'early_weight' tracks weight used for reads/writes done early in this fn before its + // early-exit codepaths. + let mut early_weight = Weight::zero(); + + // TODO: it would probably be optimal to roll Points into the DelayedPayouts storage + // item so that we do fewer reads each block + let total_points = >::get(paid_for_round); + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 0)); + + if total_points.is_zero() { + // TODO: this case is obnoxious... it's a value query, so it could mean one of two + // different logic errors: + // 1. we removed it before we should have + // 2. we called pay_one_collator_reward when we were actually done with deferred + // payouts + log::warn!("pay_one_collator_reward called with no > for the round!"); + return (RewardPayment::Finished, early_weight); + } + + let collator_fee = payout_info.collator_commission; + let collator_issuance = collator_fee * payout_info.round_issuance; + + if let Some((collator, state)) = + >::iter_prefix(paid_for_round).drain().next() + { + // read and kill AtStake + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + + // Take the awarded points for the collator + let pts = >::take(paid_for_round, &collator); + // read and kill AwardedPts + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + if pts == 0 { + return (RewardPayment::Skipped, early_weight); + } + + // 'extra_weight' tracks weight returned from fns that we delegate to which can't be + // known ahead of time. + let mut extra_weight = Weight::zero(); + let pct_due = Perbill::from_rational(pts, total_points); + let total_paid = pct_due * payout_info.total_staking_reward; + let mut amt_due = total_paid; + + let num_delegators = state.delegations.len(); + if state.delegations.is_empty() { + // solo collator with no delegators + extra_weight = extra_weight + .saturating_add(T::PayoutCollatorReward::payout_collator_reward( + paid_for_round, + collator.clone(), + amt_due, + )) + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator, + amt_due, + )); + } else { + // pay collator first; commission + due_portion + let collator_pct = Perbill::from_rational(state.bond, state.total); + let commission = pct_due * collator_issuance; + amt_due = amt_due.saturating_sub(commission); + let collator_reward = (collator_pct * amt_due).saturating_add(commission); + extra_weight = extra_weight + .saturating_add(T::PayoutCollatorReward::payout_collator_reward( + paid_for_round, + collator.clone(), + collator_reward, + )) + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator.clone(), + collator_reward, + )); + + // pay delegators due portion + for BondWithAutoCompound { owner, amount, auto_compound } in state.delegations { + let percent = Perbill::from_rational(amount, state.total); + let due = percent * amt_due; + if !due.is_zero() { + extra_weight = extra_weight.saturating_add(Self::mint_and_compound( + due, + auto_compound, + collator.clone(), + owner.clone(), + )); + } + } + } + + ( + RewardPayment::Paid, + T::WeightInfo::pay_one_collator_reward(num_delegators as u32) + .saturating_add(extra_weight), + ) + } else { + // Note that we don't clean up storage here; it is cleaned up in + // handle_delayed_payouts() + (RewardPayment::Finished, Weight::from_ref_time(0u64)) + } + } + + /// Compute the top `TotalSelected` candidates in the CandidatePool and return + /// a vec of their AccountIds (in the order of selection) + pub fn compute_top_candidates() -> Vec { + let mut candidates = >::get().0; + // order candidates by stake (least to greatest so requires `rev()`) + candidates.sort_by(|a, b| a.amount.cmp(&b.amount)); + let top_n = >::get() as usize; + // choose the top TotalSelected qualified candidates, ordered by stake + let mut collators = candidates + .into_iter() + .rev() + .take(top_n) + .filter(|x| x.amount >= T::MinCollatorStk::get()) + .map(|x| x.owner) + .collect::>(); + collators.sort(); + collators + } + /// Best as in most cumulatively supported in terms of stake + /// Returns [collator_count, delegation_count, total staked] + pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { + let (mut collator_count, mut delegation_count, mut total) = + (0u32, 0u32, BalanceOf::::zero()); + // choose the top TotalSelected qualified candidates, ordered by stake + let collators = Self::compute_top_candidates(); + if collators.is_empty() { + // SELECTION FAILED TO SELECT >=1 COLLATOR => select collators from previous round + let last_round = now.saturating_sub(1u32); + let mut total_per_candidate: BTreeMap> = BTreeMap::new(); + // set this round AtStake to last round AtStake + for (account, snapshot) in >::iter_prefix(last_round) { + collator_count = collator_count.saturating_add(1u32); + delegation_count = + delegation_count.saturating_add(snapshot.delegations.len() as u32); + total = total.saturating_add(snapshot.total); + total_per_candidate.insert(account.clone(), snapshot.total); + >::insert(now, account, snapshot); + } + // `SelectedCandidates` remains unchanged from last round + // emit CollatorChosen event for tools that use this event + for candidate in >::get() { + let snapshot_total = total_per_candidate + .get(&candidate) + .expect("all selected candidates have snapshots"); + Self::deposit_event(Event::CollatorChosen { + round: now, + collator_account: candidate, + total_exposed_amount: *snapshot_total, + }) + } + let weight = T::WeightInfo::select_top_candidates(0, 0); + return (weight, collator_count, delegation_count, total); + } + + // snapshot exposure for round for weighting reward distribution + for account in collators.iter() { + let state = >::get(account) + .expect("all members of CandidateQ must be candidates"); + + collator_count = collator_count.saturating_add(1u32); + delegation_count = delegation_count.saturating_add(state.delegation_count); + total = total.saturating_add(state.total_counted); + let CountedDelegations { uncounted_stake, rewardable_delegations } = + Self::get_rewardable_delegators(account); + let total_counted = state.total_counted.saturating_sub(uncounted_stake); + + let auto_compounding_delegations = >::get(account) + .into_iter() + .map(|x| (x.delegator, x.value)) + .collect::>(); + let rewardable_delegations = rewardable_delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner.clone(), + amount: d.amount, + auto_compound: auto_compounding_delegations + .get(&d.owner) + .cloned() + .unwrap_or(Percent::zero()), + }) + .collect(); + + let snapshot = CollatorSnapshot { + bond: state.bond, + delegations: rewardable_delegations, + total: total_counted, + }; + >::insert(now, account, snapshot); + Self::deposit_event(Event::CollatorChosen { + round: now, + collator_account: account.clone(), + total_exposed_amount: state.total_counted, + }); + } + // insert canonical collator set + >::put(collators); + + let avg_delegator_count = delegation_count.checked_div(collator_count).unwrap_or(0); + let weight = T::WeightInfo::select_top_candidates(collator_count, avg_delegator_count); + (weight, collator_count, delegation_count, total) + } + + /// Apply the delegator intent for revoke and decrease in order to build the + /// effective list of delegators with their intended bond amount. + /// + /// This will: + /// - if [DelegationChange::Revoke] is outstanding, set the bond amount to 0. + /// - if [DelegationChange::Decrease] is outstanding, subtract the bond by specified amount. + /// - else, do nothing + /// + /// The intended bond amounts will be used while calculating rewards. + pub(crate) fn get_rewardable_delegators(collator: &T::AccountId) -> CountedDelegations { + let requests = >::get(collator) + .into_iter() + .map(|x| (x.delegator, x.action)) + .collect::>(); + let mut uncounted_stake = BalanceOf::::zero(); + let rewardable_delegations = >::get(collator) + .expect("all members of CandidateQ must be candidates") + .delegations + .into_iter() + .map(|mut bond| { + bond.amount = match requests.get(&bond.owner) { + None => bond.amount, + Some(DelegationAction::Revoke(_)) => { + uncounted_stake = uncounted_stake.saturating_add(bond.amount); + BalanceOf::::zero() + } + Some(DelegationAction::Decrease(amount)) => { + uncounted_stake = uncounted_stake.saturating_add(*amount); + bond.amount.saturating_sub(*amount) + } + }; + + bond + }) + .collect(); + CountedDelegations { uncounted_stake, rewardable_delegations } + } + + /// This function exists as a helper to delegator_bond_more & auto_compound functionality. + /// Any changes to this function must align with both user-initiated bond increases and + /// auto-compounding bond increases. + /// Any feature-specific preconditions should be validated before this function is invoked. + /// Any feature-specific events must be emitted after this function is invoked. + pub fn delegation_bond_more_without_event( + delegator: T::AccountId, + candidate: T::AccountId, + more: BalanceOf, + ) -> Result { + ensure!( + !Self::delegation_request_revoke_exists(&candidate, &delegator), + Error::::PendingDelegationRevoke + ); + let mut state = >::get(&delegator).ok_or(Error::::DelegatorDNE)?; + state.increase_delegation::(candidate, more) + } + + /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. + pub fn mint(amt: BalanceOf, to: T::AccountId) { + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { + Self::deposit_event(Event::Rewarded { + account: to.clone(), + rewards: amount_transferred.peek(), + }); + } + } + + /// Mint a specified reward amount to the collator's account. Emits the [Rewarded] event. + pub fn mint_collator_reward( + _paid_for_round: RoundIndex, + collator_id: T::AccountId, + amt: BalanceOf, + ) -> Weight { + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&collator_id, amt) { + Self::deposit_event(Event::Rewarded { + account: collator_id.clone(), + rewards: amount_transferred.peek(), + }); + } + T::WeightInfo::mint_collator_reward() + } + + /// Mint and compound delegation rewards. The function mints the amount towards the + /// delegator and tries to compound a specified percent of it back towards the delegation. + /// If a scheduled delegation revoke exists, then the amount is only minted, and nothing is + /// compounded. Emits the [Compounded] event. + pub fn mint_and_compound( + amt: BalanceOf, + compound_percent: Percent, + candidate: T::AccountId, + delegator: T::AccountId, + ) -> Weight { + let mut weight = T::WeightInfo::mint_collator_reward(); + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&delegator, amt) { + Self::deposit_event(Event::Rewarded { + account: delegator.clone(), + rewards: amount_transferred.peek(), + }); + + let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); + if compound_amount.is_zero() { + return weight; + } + + if let Err(err) = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + compound_amount, + ) { + log::debug!( + "skipped compounding staking reward towards candidate '{:?}' for \ + delegator '{:?}': {:?}", + candidate, + delegator, + err + ); + return weight; + }; + weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); + + Pallet::::deposit_event(Event::Compounded { + delegator, + candidate, + amount: compound_amount, + }); + }; + + weight + } + } + + /// Add reward points to block authors: + /// * 20 points to the block producer for producing a block in the chain + impl Pallet { + fn award_points_to_block_author() { + let author = T::BlockAuthor::get(); + let now = >::get().current; + let score_plus_20 = >::get(now, &author).saturating_add(20); + >::insert(now, author, score_plus_20); + >::mutate(now, |x| *x = x.saturating_add(20)); + } + } + + impl nimbus_primitives::CanAuthor for Pallet { + fn can_author(account: &T::AccountId, _slot: &u32) -> bool { + Self::is_selected_candidate(account) + } + } + + impl Get> for Pallet { + fn get() -> Vec { + Self::selected_candidates() + } + } } diff --git a/external/pallets/parachain-staking/src/migrations.rs b/external/pallets/parachain-staking/src/migrations.rs index db7128f88..7fbc98064 100644 --- a/external/pallets/parachain-staking/src/migrations.rs +++ b/external/pallets/parachain-staking/src/migrations.rs @@ -17,18 +17,19 @@ //! # Migrations #![allow(unused)] +#![allow(clippy::type_complexity)] -use crate::delegation_requests::{DelegationAction, ScheduledRequest}; -use crate::pallet::{DelegationScheduledRequests, DelegatorState, Total}; #[allow(deprecated)] use crate::types::deprecated::{ - CollatorSnapshot as OldCollatorSnapshot, DelegationChange, Delegator as OldDelegator, + CollatorSnapshot as OldCollatorSnapshot, DelegationChange, Delegator as OldDelegator, }; -use crate::types::{CollatorSnapshot, Delegator}; use crate::{ - AtStake, BalanceOf, Bond, BondWithAutoCompound, BottomDelegations, CandidateInfo, - CandidateMetadata, CapacityStatus, CollatorCandidate, Config, DelayedPayouts, Delegations, - Event, Pallet, Points, Round, RoundIndex, Staked, TopDelegations, + delegation_requests::{DelegationAction, ScheduledRequest}, + pallet::{DelegationScheduledRequests, DelegatorState, Total}, + types::{CollatorSnapshot, Delegator}, + AtStake, BalanceOf, Bond, BondWithAutoCompound, BottomDelegations, CandidateInfo, + CandidateMetadata, CapacityStatus, CollatorCandidate, Config, DelayedPayouts, Delegations, + Event, Pallet, Points, Round, RoundIndex, Staked, TopDelegations, }; use frame_support::Twox64Concat; use parity_scale_codec::{Decode, Encode}; @@ -36,147 +37,145 @@ extern crate alloc; #[cfg(feature = "try-runtime")] use alloc::{format, string::ToString}; use frame_support::{ - migration::storage_key_iter, - pallet_prelude::PhantomData, - storage, - traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, - weights::Weight, + migration::storage_key_iter, + pallet_prelude::PhantomData, + storage, + traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, + weights::Weight, }; #[cfg(feature = "try-runtime")] use scale_info::prelude::string::String; -use sp_runtime::traits::{Saturating, Zero}; -use sp_runtime::Percent; +use sp_runtime::{ + traits::{Saturating, Zero}, + Percent, +}; use sp_std::{convert::TryInto, vec, vec::Vec}; /// Migrate `AtStake` storage item to include auto-compound value for unpaid rounds. pub struct MigrateAtStakeAutoCompound(PhantomData); impl MigrateAtStakeAutoCompound { - /// Get keys for the `AtStake` storage for the rounds up to `RewardPaymentDelay` rounds ago. - /// We migrate only the last unpaid rounds due to the presence of stale entries in `AtStake` - /// which significantly increase the PoV size. - fn unpaid_rounds_keys() -> impl Iterator)> { - let current_round = >::get().current; - let max_unpaid_round = current_round.saturating_sub(T::RewardPaymentDelay::get()); - (max_unpaid_round..=current_round) - .into_iter() - .flat_map(|round| { - >::iter_key_prefix(round).map(move |candidate| { - let key = >::hashed_key_for(round.clone(), candidate.clone()); - (round, candidate, key) - }) - }) - } + /// Get keys for the `AtStake` storage for the rounds up to `RewardPaymentDelay` rounds ago. + /// We migrate only the last unpaid rounds due to the presence of stale entries in `AtStake` + /// which significantly increase the PoV size. + fn unpaid_rounds_keys() -> impl Iterator)> { + let current_round = >::get().current; + let max_unpaid_round = current_round.saturating_sub(T::RewardPaymentDelay::get()); + (max_unpaid_round..=current_round).into_iter().flat_map(|round| { + >::iter_key_prefix(round).map(move |candidate| { + let key = >::hashed_key_for(round, candidate.clone()); + (round, candidate, key) + }) + }) + } } impl OnRuntimeUpgrade for MigrateAtStakeAutoCompound { - #[allow(deprecated)] - fn on_runtime_upgrade() -> Weight { - log::info!( - target: "MigrateAtStakeAutoCompound", - "running migration to add auto-compound values" - ); - let mut reads = 0u64; - let mut writes = 0u64; - for (round, candidate, key) in Self::unpaid_rounds_keys() { - let old_state: OldCollatorSnapshot> = - storage::unhashed::get(&key).expect("unable to decode value"); - reads = reads.saturating_add(1); - writes = writes.saturating_add(1); - log::info!( - target: "MigrateAtStakeAutoCompound", - "migration from old format round {:?}, candidate {:?}", round, candidate - ); - let new_state = CollatorSnapshot { - bond: old_state.bond, - delegations: old_state - .delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner, - amount: d.amount, - auto_compound: Percent::zero(), - }) - .collect(), - total: old_state.total, - }; - storage::unhashed::put(&key, &new_state); - } - - T::DbWeight::get().reads_writes(reads, writes) - } - - #[allow(deprecated)] - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - let mut num_to_update = 0u32; - let mut rounds_candidates: Vec<(RoundIndex, T::AccountId)> = vec![]; - use sp_std::collections::btree_map::BTreeMap; - let mut state_map: BTreeMap = BTreeMap::new(); - - for (round, candidate, key) in Self::unpaid_rounds_keys() { - let state: OldCollatorSnapshot> = - storage::unhashed::get(&key).expect("unable to decode value"); - - num_to_update = num_to_update.saturating_add(1); - rounds_candidates.push((round.clone(), candidate.clone())); - let mut delegation_str = vec![]; - for d in state.delegations { - delegation_str.push(format!( - "owner={:?}_amount={:?}_autoCompound=0%", - d.owner, d.amount - )); - } - state_map.insert( - (&*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string(), - format!( - "bond={:?}_total={:?}_delegations={:?}", - state.bond, state.total, delegation_str - ), - ); - } - - rounds_candidates.sort(); - Ok((state_map, rounds_candidates, num_to_update).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let (state_map, rounds_candidates_received, num_updated_received): ( - BTreeMap, - Vec<(RoundIndex, T::AccountId)>, - u32, - ) = Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - let mut num_updated = 0u32; - let mut rounds_candidates = vec![]; - for (round, candidate, _) in Self::unpaid_rounds_keys() { - let state = >::get(&round, &candidate); - num_updated = num_updated.saturating_add(1); - rounds_candidates.push((round.clone(), candidate.clone())); - let mut delegation_str = vec![]; - for d in state.delegations { - delegation_str.push(format!( - "owner={:?}_amount={:?}_autoCompound={:?}", - d.owner, d.amount, d.auto_compound - )); - } - assert_eq!( - Some(&format!( - "bond={:?}_total={:?}_delegations={:?}", - state.bond, state.total, delegation_str - )), - state_map - .get(&((&*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string())), - "incorrect delegations migration for round_{:?}_candidate_{:?}", - round, - candidate, - ); - } - - rounds_candidates.sort(); - assert_eq!(rounds_candidates, rounds_candidates_received); - assert_eq!(num_updated, num_updated_received); - Ok(()) - } + #[allow(deprecated)] + fn on_runtime_upgrade() -> Weight { + log::info!( + target: "MigrateAtStakeAutoCompound", + "running migration to add auto-compound values" + ); + let mut reads = 0u64; + let mut writes = 0u64; + for (round, candidate, key) in Self::unpaid_rounds_keys() { + let old_state: OldCollatorSnapshot> = + storage::unhashed::get(&key).expect("unable to decode value"); + reads = reads.saturating_add(1); + writes = writes.saturating_add(1); + log::info!( + target: "MigrateAtStakeAutoCompound", + "migration from old format round {:?}, candidate {:?}", round, candidate + ); + let new_state = CollatorSnapshot { + bond: old_state.bond, + delegations: old_state + .delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner, + amount: d.amount, + auto_compound: Percent::zero(), + }) + .collect(), + total: old_state.total, + }; + storage::unhashed::put(&key, &new_state); + } + + T::DbWeight::get().reads_writes(reads, writes) + } + + #[allow(deprecated)] + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let mut num_to_update = 0u32; + let mut rounds_candidates: Vec<(RoundIndex, T::AccountId)> = vec![]; + use sp_std::collections::btree_map::BTreeMap; + let mut state_map: BTreeMap = BTreeMap::new(); + + for (round, candidate, key) in Self::unpaid_rounds_keys() { + let state: OldCollatorSnapshot> = + storage::unhashed::get(&key).expect("unable to decode value"); + + num_to_update = num_to_update.saturating_add(1); + rounds_candidates.push((round, candidate.clone())); + let mut delegation_str = vec![]; + for d in state.delegations { + delegation_str + .push(format!("owner={:?}_amount={:?}_autoCompound=0%", d.owner, d.amount)); + } + state_map.insert( + (*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string(), + format!( + "bond={:?}_total={:?}_delegations={:?}", + state.bond, state.total, delegation_str + ), + ); + } + + rounds_candidates.sort(); + Ok((state_map, rounds_candidates, num_to_update).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + use sp_std::collections::btree_map::BTreeMap; + + let (state_map, rounds_candidates_received, num_updated_received): ( + BTreeMap, + Vec<(RoundIndex, T::AccountId)>, + u32, + ) = Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); + + let mut num_updated = 0u32; + let mut rounds_candidates = vec![]; + for (round, candidate, _) in Self::unpaid_rounds_keys() { + let state = >::get(round, &candidate); + num_updated = num_updated.saturating_add(1); + rounds_candidates.push((round, candidate.clone())); + let mut delegation_str = vec![]; + for d in state.delegations { + delegation_str.push(format!( + "owner={:?}_amount={:?}_autoCompound={:?}", + d.owner, d.amount, d.auto_compound + )); + } + assert_eq!( + Some(&format!( + "bond={:?}_total={:?}_delegations={:?}", + state.bond, state.total, delegation_str + )), + state_map + .get(&((*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string())), + "incorrect delegations migration for round_{:?}_candidate_{:?}", + round, + candidate, + ); + } + + rounds_candidates.sort(); + assert_eq!(rounds_candidates, rounds_candidates_received); + assert_eq!(num_updated, num_updated_received); + Ok(()) + } } diff --git a/external/pallets/parachain-staking/src/mock.rs b/external/pallets/parachain-staking/src/mock.rs index da794efa7..5aed26987 100644 --- a/external/pallets/parachain-staking/src/mock.rs +++ b/external/pallets/parachain-staking/src/mock.rs @@ -17,19 +17,19 @@ //! Test utilities use crate as pallet_parachain_staking; use crate::{ - pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, - COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, + pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, + COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, }; use frame_support::{ - construct_runtime, parameter_types, - traits::{Everything, GenesisBuild, LockIdentifier, OnFinalize, OnInitialize}, - weights::{constants::RocksDbWeight, Weight}, + construct_runtime, parameter_types, + traits::{Everything, GenesisBuild, LockIdentifier, OnFinalize, OnInitialize}, + weights::{constants::RocksDbWeight, Weight}, }; use sp_core::H256; -use sp_io; +// use sp_io; use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - Perbill, Percent, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, Percent, }; pub type AccountId = u64; @@ -41,273 +41,263 @@ type Block = frame_system::mocking::MockBlock; // Configure a mock runtime to test the pallet. construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Config, Event}, - BlockAuthor: block_author::{Pallet, Storage}, - } + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Config, Event}, + BlockAuthor: block_author::{Pallet, Storage}, + } ); parameter_types! { - pub const BlockHashCount: u32 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const SS58Prefix: u8 = 42; + pub const BlockHashCount: u32 = 250; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const SS58Prefix: u8 = 42; } impl frame_system::Config for Test { - type BaseCallFilter = Everything; - type DbWeight = RocksDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = sp_runtime::generic::Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type BaseCallFilter = Everything; + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { - pub const ExistentialDeposit: u128 = 1; + pub const ExistentialDeposit: u128 = 1; } impl pallet_balances::Config for Test { - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type MaxLocks = (); - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); } impl block_author::Config for Test {} const GENESIS_BLOCKS_PER_ROUND: u32 = 5; const GENESIS_COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20); const GENESIS_PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30); parameter_types! { - pub const MinBlocksPerRound: u32 = 3; - pub const LeaveCandidatesDelay: u32 = 2; - pub const CandidateBondLessDelay: u32 = 2; - pub const LeaveDelegatorsDelay: u32 = 2; - pub const RevokeDelegationDelay: u32 = 2; - pub const DelegationBondLessDelay: u32 = 2; - pub const RewardPaymentDelay: u32 = 2; - pub const MinSelectedCandidates: u32 = 5; - pub const MaxTopDelegationsPerCandidate: u32 = 4; - pub const MaxBottomDelegationsPerCandidate: u32 = 4; - pub const MaxDelegationsPerDelegator: u32 = 4; - pub const MinCollatorStk: u128 = 10; - pub const MinDelegatorStk: u128 = 5; - pub const MinDelegation: u128 = 3; + pub const MinBlocksPerRound: u32 = 3; + pub const LeaveCandidatesDelay: u32 = 2; + pub const CandidateBondLessDelay: u32 = 2; + pub const LeaveDelegatorsDelay: u32 = 2; + pub const RevokeDelegationDelay: u32 = 2; + pub const DelegationBondLessDelay: u32 = 2; + pub const RewardPaymentDelay: u32 = 2; + pub const MinSelectedCandidates: u32 = 5; + pub const MaxTopDelegationsPerCandidate: u32 = 4; + pub const MaxBottomDelegationsPerCandidate: u32 = 4; + pub const MaxDelegationsPerDelegator: u32 = 4; + pub const MinCollatorStk: u128 = 10; + pub const MinDelegatorStk: u128 = 5; + pub const MinDelegation: u128 = 3; } impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; - type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; - type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; - type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MinCollatorStk = MinCollatorStk; - type MinCandidateStk = MinCollatorStk; - type MinDelegatorStk = MinDelegatorStk; - type MinDelegation = MinDelegation; - type BlockAuthor = BlockAuthor; - type OnCollatorPayout = (); - type PayoutCollatorReward = (); - type OnNewRound = (); - type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; + type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; + type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; + type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MinCollatorStk = MinCollatorStk; + type MinCandidateStk = MinCollatorStk; + type MinDelegatorStk = MinDelegatorStk; + type MinDelegation = MinDelegation; + type BlockAuthor = BlockAuthor; + type OnCollatorPayout = (); + type PayoutCollatorReward = (); + type OnNewRound = (); + type WeightInfo = (); } pub(crate) struct ExtBuilder { - // endowed accounts with balances - balances: Vec<(AccountId, Balance)>, - // [collator, amount] - collators: Vec<(AccountId, Balance)>, - // [delegator, collator, delegation_amount, auto_compound_percent] - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - // inflation config - inflation: InflationInfo, + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, delegation_amount, auto_compound_percent] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // inflation config + inflation: InflationInfo, } impl Default for ExtBuilder { - fn default() -> ExtBuilder { - ExtBuilder { - balances: vec![], - delegations: vec![], - collators: vec![], - inflation: InflationInfo { - expect: Range { - min: 700, - ideal: 700, - max: 700, - }, - // not used - annual: Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50), - }, - // unrealistically high parameterization, only for testing - round: Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }, - }, - } - } + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + delegations: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { min: 700, ideal: 700, max: 700 }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + } + } } impl ExtBuilder { - pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { - self.balances = balances; - self - } - - pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { - self.collators = collators; - self - } - - pub(crate) fn with_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance)>, - ) -> Self { - self.delegations = delegations - .into_iter() - .map(|d| (d.0, d.1, d.2, Percent::zero())) - .collect(); - self - } - - pub(crate) fn with_auto_compounding_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - ) -> Self { - self.delegations = delegations; - self - } - - #[allow(dead_code)] - pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { - self.inflation = inflation; - self - } - - pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: self.balances, - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - pallet_parachain_staking::GenesisConfig:: { - candidates: self.collators, - delegations: self.delegations, - inflation_config: self.inflation, - collator_commission: GENESIS_COLLATOR_COMMISSION, - parachain_bond_reserve_percent: GENESIS_PARACHAIN_BOND_RESERVE_PERCENT, - blocks_per_round: GENESIS_BLOCKS_PER_ROUND, - } - .assimilate_storage(&mut t) - .expect("Parachain Staking's storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub(crate) fn with_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance)>, + ) -> Self { + self.delegations = + delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); + self + } + + pub(crate) fn with_auto_compounding_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + ) -> Self { + self.delegations = delegations; + self + } + + #[allow(dead_code)] + pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { balances: self.balances } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + collator_commission: GENESIS_COLLATOR_COMMISSION, + parachain_bond_reserve_percent: GENESIS_PARACHAIN_BOND_RESERVE_PERCENT, + blocks_per_round: GENESIS_BLOCKS_PER_ROUND, + } + .assimilate_storage(&mut t) + .expect("Parachain Staking's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } } /// Rolls forward one block. Returns the new block number. fn roll_one_block() -> BlockNumber { - Balances::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - System::reset_events(); - System::on_initialize(System::block_number()); - Balances::on_initialize(System::block_number()); - ParachainStaking::on_initialize(System::block_number()); - System::block_number() + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::reset_events(); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + System::block_number() } /// Rolls to the desired block. Returns the number of blocks played. pub(crate) fn roll_to(n: BlockNumber) -> u32 { - let mut num_blocks = 0; - let mut block = System::block_number(); - while block < n { - block = roll_one_block(); - num_blocks += 1; - } - num_blocks + let mut num_blocks = 0; + let mut block = System::block_number(); + while block < n { + block = roll_one_block(); + num_blocks += 1; + } + num_blocks } /// Rolls desired number of blocks. Returns the final block. pub(crate) fn roll_blocks(num_blocks: u32) -> BlockNumber { - let mut block = System::block_number(); - for _ in 0..num_blocks { - block = roll_one_block(); - } - block + let mut block = System::block_number(); + for _ in 0..num_blocks { + block = roll_one_block(); + } + block } /// Rolls block-by-block to the beginning of the specified round. /// This will complete the block in which the round change occurs. /// Returns the number of blocks played. pub(crate) fn roll_to_round_begin(round: BlockNumber) -> BlockNumber { - let block = (round - 1) * GENESIS_BLOCKS_PER_ROUND; - roll_to(block) + let block = (round - 1) * GENESIS_BLOCKS_PER_ROUND; + roll_to(block) } /// Rolls block-by-block to the end of the specified round. /// The block following will be the one in which the specified round change occurs. pub(crate) fn roll_to_round_end(round: BlockNumber) -> BlockNumber { - let block = round * GENESIS_BLOCKS_PER_ROUND - 1; - roll_to(block) + let block = round * GENESIS_BLOCKS_PER_ROUND - 1; + roll_to(block) } pub(crate) fn events() -> Vec> { - System::events() - .into_iter() - .map(|r| r.event) - .filter_map(|e| { - if let RuntimeEvent::ParachainStaking(inner) = e { - Some(inner) - } else { - None - } - }) - .collect::>() + System::events() + .into_iter() + .map(|r| r.event) + .filter_map( + |e| { + if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None } + }, + ) + .collect::>() } /// Asserts that some events were never emitted. @@ -319,9 +309,9 @@ pub(crate) fn events() -> Vec> { /// ``` #[macro_export] macro_rules! assert_no_events { - () => { - similar_asserts::assert_eq!(Vec::>::new(), crate::mock::events()) - }; + () => { + similar_asserts::assert_eq!(Vec::>::new(), $crate::mock::events()) + }; } /// Asserts that emitted events match exactly the given input. @@ -330,19 +320,19 @@ macro_rules! assert_no_events { /// /// ``` /// assert_events_eq!( -/// Foo { x: 1, y: 2 }, -/// Bar { value: "test" }, -/// Baz { a: 10, b: 20 }, +/// Foo { x: 1, y: 2 }, +/// Bar { value: "test" }, +/// Baz { a: 10, b: 20 }, /// ); /// ``` #[macro_export] macro_rules! assert_events_eq { - ($event:expr) => { - similar_asserts::assert_eq!(vec![$event], crate::mock::events()); - }; - ($($events:expr,)+) => { - similar_asserts::assert_eq!(vec![$($events,)+], crate::mock::events()); - }; + ($event:expr) => { + similar_asserts::assert_eq!(vec![$event], $crate::mock::events()); + }; + ($($events:expr,)+) => { + similar_asserts::assert_eq!(vec![$($events,)+], $crate::mock::events()); + }; } /// Asserts that some emitted events match the given input. @@ -351,28 +341,28 @@ macro_rules! assert_events_eq { /// /// ``` /// assert_events_emitted!( -/// Foo { x: 1, y: 2 }, -/// Baz { a: 10, b: 20 }, +/// Foo { x: 1, y: 2 }, +/// Baz { a: 10, b: 20 }, /// ); /// ``` #[macro_export] macro_rules! assert_events_emitted { - ($event:expr) => { - [$event].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x == &e).is_some(), - "Event {:?} was not found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; - ($($events:expr,)+) => { - [$($events,)+].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x == &e).is_some(), - "Event {:?} was not found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; + ($event:expr) => { + [$event].into_iter().for_each(|e| assert!( + $crate::mock::events().into_iter().find(|x| x == &e).is_some(), + "Event {:?} was not found in events: \n{:#?}", + e, + $crate::mock::events() + )); + }; + ($($events:expr,)+) => { + [$($events,)+].into_iter().for_each(|e| assert!( + $crate::mock::events().into_iter().find(|x| x == &e).is_some(), + "Event {:?} was not found in events: \n{:#?}", + e, + $crate::mock::events() + )); + }; } /// Asserts that some events were never emitted. @@ -381,28 +371,28 @@ macro_rules! assert_events_emitted { /// /// ``` /// assert_events_not_emitted!( -/// Foo { x: 1, y: 2 }, -/// Bar { value: "test" }, +/// Foo { x: 1, y: 2 }, +/// Bar { value: "test" }, /// ); /// ``` #[macro_export] macro_rules! assert_events_not_emitted { - ($event:expr) => { - [$event].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x != &e).is_some(), - "Event {:?} was unexpectedly found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; - ($($events:expr,)+) => { - [$($events,)+].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x != &e).is_some(), - "Event {:?} was unexpectedly found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; + ($event:expr) => { + [$event].into_iter().for_each(|e| assert!( + $crate::mock::events().into_iter().find(|x| x != &e).is_some(), + "Event {:?} was unexpectedly found in events: \n{:#?}", + e, + $crate::mock::events() + )); + }; + ($($events:expr,)+) => { + [$($events,)+].into_iter().for_each(|e| assert!( + $crate::mock::events().into_iter().find(|x| x != &e).is_some(), + "Event {:?} was unexpectedly found in events: \n{:#?}", + e, + $crate::mock::events() + )); + }; } /// Asserts that the emitted events are exactly equal to the input patterns. @@ -411,41 +401,41 @@ macro_rules! assert_events_not_emitted { /// /// ``` /// assert_events_eq_match!( -/// Foo { x: 1, .. }, -/// Bar { .. }, -/// Baz { a: 10, b: 20 }, +/// Foo { x: 1, .. }, +/// Bar { .. }, +/// Baz { a: 10, b: 20 }, /// ); /// ``` #[macro_export] macro_rules! assert_events_eq_match { - ($index:expr;) => { - assert_eq!( - $index, - crate::mock::events().len(), - "Found {} extra event(s): \n{:#?}", - crate::mock::events().len()-$index, - crate::mock::events() - ); - }; - ($index:expr; $event:pat_param, $($events:pat_param,)*) => { - assert!( - matches!( - crate::mock::events().get($index), - Some($event), - ), - "Event {:#?} was not found at index {}: \n{:#?}", - stringify!($event), - $index, - crate::mock::events() - ); - assert_events_eq_match!($index+1; $($events,)*); - }; - ($event:pat_param) => { - assert_events_eq_match!(0; $event,); - }; - ($($events:pat_param,)+) => { - assert_events_eq_match!(0; $($events,)+); - }; + ($index:expr;) => { + assert_eq!( + $index, + $crate::mock::events().len(), + "Found {} extra event(s): \n{:#?}", + $crate::mock::events().len()-$index, + $crate::mock::events() + ); + }; + ($index:expr; $event:pat_param, $($events:pat_param,)*) => { + assert!( + matches!( + $crate::mock::events().get($index), + Some($event), + ), + "Event {:#?} was not found at index {}: \n{:#?}", + stringify!($event), + $index, + $crate::mock::events() + ); + assert_events_eq_match!($index+1; $($events,)*); + }; + ($event:pat_param) => { + assert_events_eq_match!(0; $event,); + }; + ($($events:pat_param,)+) => { + assert_events_eq_match!(0; $($events,)+); + }; } /// Asserts that some emitted events match the input patterns. @@ -454,26 +444,26 @@ macro_rules! assert_events_eq_match { /// /// ``` /// assert_events_emitted_match!( -/// Foo { x: 1, .. }, -/// Baz { a: 10, b: 20 }, +/// Foo { x: 1, .. }, +/// Baz { a: 10, b: 20 }, /// ); /// ``` #[macro_export] macro_rules! assert_events_emitted_match { - ($event:pat_param) => { - assert!( - crate::mock::events().into_iter().any(|x| matches!(x, $event)), - "Event {:?} was not found in events: \n{:#?}", - stringify!($event), - crate::mock::events() - ); - }; - ($event:pat_param, $($events:pat_param,)+) => { - assert_events_emitted_match!($event); - $( - assert_events_emitted_match!($events); - )+ - }; + ($event:pat_param) => { + assert!( + $crate::mock::events().into_iter().any(|x| matches!(x, $event)), + "Event {:?} was not found in events: \n{:#?}", + stringify!($event), + $crate::mock::events() + ); + }; + ($event:pat_param, $($events:pat_param,)+) => { + assert_events_emitted_match!($event); + $( + assert_events_emitted_match!($events); + )+ + }; } /// Asserts that the input patterns match none of the emitted events. @@ -482,580 +472,500 @@ macro_rules! assert_events_emitted_match { /// /// ``` /// assert_events_not_emitted_match!( -/// Foo { x: 1, .. }, -/// Baz { a: 10, b: 20 }, +/// Foo { x: 1, .. }, +/// Baz { a: 10, b: 20 }, /// ); /// ``` #[macro_export] macro_rules! assert_events_not_emitted_match { - ($event:pat_param) => { - assert!( - crate::mock::events().into_iter().any(|x| !matches!(x, $event)), - "Event {:?} was unexpectedly found in events: \n{:#?}", - stringify!($event), - crate::mock::events() - ); - }; - ($event:pat_param, $($events:pat_param,)+) => { - assert_events_not_emitted_match!($event); - $( - assert_events_not_emitted_match!($events); - )+ - }; + ($event:pat_param) => { + assert!( + $crate::mock::events().into_iter().any(|x| !matches!(x, $event)), + "Event {:?} was unexpectedly found in events: \n{:#?}", + stringify!($event), + $crate::mock::events() + ); + }; + ($event:pat_param, $($events:pat_param,)+) => { + assert_events_not_emitted_match!($event); + $( + assert_events_not_emitted_match!($events); + )+ + }; } // Same storage changes as ParachainStaking::on_finalize pub(crate) fn set_author(round: BlockNumber, acc: u64, pts: u32) { - >::mutate(round, |p| *p += pts); - >::mutate(round, acc, |p| *p += pts); + >::mutate(round, |p| *p += pts); + >::mutate(round, acc, |p| *p += pts); } /// fn to query the lock amount pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option { - for lock in Balances::locks(&account_id) { - if lock.id == id { - return Some(lock.amount); - } - } - None + for lock in Balances::locks(&account_id) { + if lock.id == id { + return Some(lock.amount); + } + } + None } #[test] fn geneses() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - assert_eq!( - ParachainStaking::get_collator_stakable_free_balance(&1), - 500 - ); - assert_eq!(query_lock_amount(1, COLLATOR_LOCK_ID), Some(500)); - assert!(ParachainStaking::is_candidate(&1)); - assert_eq!(query_lock_amount(2, COLLATOR_LOCK_ID), Some(200)); - assert_eq!( - ParachainStaking::get_collator_stakable_free_balance(&2), - 100 - ); - assert!(ParachainStaking::is_candidate(&2)); - // delegators - for x in 3..7 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 0); - assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(100)); - } - // uninvolved - for x in 7..10 { - assert!(!ParachainStaking::is_delegator(&x)); - } - // no delegator staking locks - assert_eq!(query_lock_amount(7, DELEGATOR_LOCK_ID), None); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&7), - 100 - ); - assert_eq!(query_lock_amount(8, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&8), 9); - assert_eq!(query_lock_amount(9, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&9), 4); - // no collator staking locks - assert_eq!( - ParachainStaking::get_collator_stakable_free_balance(&7), - 100 - ); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&8), 9); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&9), 4); - }); - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![ - (6, 1, 10), - (7, 1, 10), - (8, 2, 10), - (9, 2, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - for x in 1..5 { - assert!(ParachainStaking::is_candidate(&x)); - assert_eq!(query_lock_amount(x, COLLATOR_LOCK_ID), Some(20)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&x), 80); - } - assert!(ParachainStaking::is_candidate(&5)); - assert_eq!(query_lock_amount(5, COLLATOR_LOCK_ID), Some(10)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&5), 90); - // delegators - for x in 6..11 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(10)); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&x), - 90 - ); - } - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 500); + assert_eq!(query_lock_amount(1, COLLATOR_LOCK_ID), Some(500)); + assert!(ParachainStaking::is_candidate(&1)); + assert_eq!(query_lock_amount(2, COLLATOR_LOCK_ID), Some(200)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&2), 100); + assert!(ParachainStaking::is_candidate(&2)); + // delegators + for x in 3..7 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 0); + assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(100)); + } + // uninvolved + for x in 7..10 { + assert!(!ParachainStaking::is_delegator(&x)); + } + // no delegator staking locks + assert_eq!(query_lock_amount(7, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 100); + assert_eq!(query_lock_amount(8, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&8), 9); + assert_eq!(query_lock_amount(9, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&9), 4); + // no collator staking locks + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&7), 100); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&8), 9); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&9), 4); + }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + for x in 1..5 { + assert!(ParachainStaking::is_candidate(&x)); + assert_eq!(query_lock_amount(x, COLLATOR_LOCK_ID), Some(20)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&x), 80); + } + assert!(ParachainStaking::is_candidate(&5)); + assert_eq!(query_lock_amount(5, COLLATOR_LOCK_ID), Some(10)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&5), 90); + // delegators + for x in 6..11 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(10)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 90); + } + }); } #[frame_support::pallet] pub mod block_author { - use super::*; - use frame_support::pallet_prelude::*; - use frame_support::traits::Get; - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::storage] - #[pallet::getter(fn block_author)] - pub(super) type BlockAuthor = StorageValue<_, AccountId, ValueQuery>; - - impl Get for Pallet { - fn get() -> AccountId { - >::get() - } - } + use super::*; + use frame_support::{pallet_prelude::*, traits::Get}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn block_author)] + pub(super) type BlockAuthor = StorageValue<_, AccountId, ValueQuery>; + + impl Get for Pallet { + fn get() -> AccountId { + >::get() + } + } } #[test] fn roll_to_round_begin_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_begin(1); - assert_eq!(System::block_number(), 1); // no-op, we're already on this round - assert_eq!(num_blocks, 0); - - let num_blocks = roll_to_round_begin(2); - assert_eq!(System::block_number(), 5); - assert_eq!(num_blocks, 4); - - let num_blocks = roll_to_round_begin(3); - assert_eq!(System::block_number(), 10); - assert_eq!(num_blocks, 5); - }); + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_begin(1); + assert_eq!(System::block_number(), 1); // no-op, we're already on this round + assert_eq!(num_blocks, 0); + + let num_blocks = roll_to_round_begin(2); + assert_eq!(System::block_number(), 5); + assert_eq!(num_blocks, 4); + + let num_blocks = roll_to_round_begin(3); + assert_eq!(System::block_number(), 10); + assert_eq!(num_blocks, 5); + }); } #[test] fn roll_to_round_end_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_end(1); - assert_eq!(System::block_number(), 4); - assert_eq!(num_blocks, 3); - - let num_blocks = roll_to_round_end(2); - assert_eq!(System::block_number(), 9); - assert_eq!(num_blocks, 5); - - let num_blocks = roll_to_round_end(3); - assert_eq!(System::block_number(), 14); - assert_eq!(num_blocks, 5); - }); + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_end(1); + assert_eq!(System::block_number(), 4); + assert_eq!(num_blocks, 3); + + let num_blocks = roll_to_round_end(2); + assert_eq!(System::block_number(), 9); + assert_eq!(num_blocks, 5); + + let num_blocks = roll_to_round_end(3); + assert_eq!(System::block_number(), 14); + assert_eq!(num_blocks, 5); + }); } #[test] #[should_panic] fn test_assert_events_eq_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_fails_if_event_extra() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 200, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 200 }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_fails_if_event_wrong_order() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 50, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }, + ); + }); } #[test] fn test_assert_events_eq_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }); - - assert_events_eq!(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }); - }); + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_eq!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + }); } #[test] fn test_assert_events_eq_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); } #[test] #[should_panic] fn test_assert_events_emitted_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!(ParachainStakingEvent::DelegatorExitScheduled { - round: 2, - delegator: 3, - scheduled_exit: 4, - }); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!(ParachainStakingEvent::DelegatorExitScheduled { + round: 2, + delegator: 3, + scheduled_exit: 4, + }); + }); } #[test] #[should_panic] fn test_assert_events_emitted_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 50, - }); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }); + }); } #[test] fn test_assert_events_emitted_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }); - - assert_events_emitted!(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }); - }); + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + }); } #[test] fn test_assert_events_emitted_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_match_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_match_fails_if_event_extra() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ParachainStakingEvent::Rewarded { .. }, - ParachainStakingEvent::Rewarded { .. }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ParachainStakingEvent::Rewarded { .. }, + ParachainStakingEvent::Rewarded { .. }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_match_fails_if_event_wrong_order() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::Rewarded { .. }, - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::Rewarded { .. }, + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ); + }); } #[test] #[should_panic] fn test_assert_events_eq_match_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ParachainStakingEvent::Rewarded { rewards: 50, .. }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ParachainStakingEvent::Rewarded { rewards: 50, .. }, + ); + }); } #[test] fn test_assert_events_eq_match_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }); - - assert_events_eq_match!(ParachainStakingEvent::Rewarded { account: 1, .. }); - }); + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_eq_match!(ParachainStakingEvent::Rewarded { account: 1, .. }); + }); } #[test] fn test_assert_events_eq_match_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - .. - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - .. - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { round: 2, collator_account: 1, .. }, + ParachainStakingEvent::NewRound { starting_block: 10, .. }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); } #[test] #[should_panic] fn test_assert_events_emitted_match_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!(ParachainStakingEvent::DelegatorExitScheduled { - round: 2, - .. - }); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!(ParachainStakingEvent::DelegatorExitScheduled { + round: 2, + .. + }); + }); } #[test] #[should_panic] fn test_assert_events_emitted_match_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); - assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 50, .. }); - }); + assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 50, .. }); + }); } #[test] fn test_assert_events_emitted_match_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }); - - assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 100, .. }); - }); + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 100, .. }); + }); } #[test] fn test_assert_events_emitted_match_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!( - ParachainStakingEvent::CollatorChosen { - total_exposed_amount: 10, - .. - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ); - }); + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!( + ParachainStakingEvent::CollatorChosen { total_exposed_amount: 10, .. }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); } fn inject_test_events() { - [ - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { - account: 1, - rewards: 100, - }, - ] - .into_iter() - .for_each(System::deposit_event); + [ + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ] + .into_iter() + .for_each(System::deposit_event); } diff --git a/external/pallets/parachain-staking/src/set.rs b/external/pallets/parachain-staking/src/set.rs index 8e4e29648..d4775eba8 100644 --- a/external/pallets/parachain-staking/src/set.rs +++ b/external/pallets/parachain-staking/src/set.rs @@ -28,62 +28,62 @@ use sp_std::prelude::*; pub struct OrderedSet(pub Vec); impl OrderedSet { - /// Create a new empty set - pub fn new() -> Self { - Self(Vec::new()) - } + /// Create a new empty set + pub fn new() -> Self { + Self(Vec::new()) + } - /// Create a set from a `Vec`. - /// `v` will be sorted and dedup first. - pub fn from(mut v: Vec) -> Self { - v.sort(); - v.dedup(); - Self::from_sorted_set(v) - } + /// Create a set from a `Vec`. + /// `v` will be sorted and dedup first. + pub fn from(mut v: Vec) -> Self { + v.sort(); + v.dedup(); + Self::from_sorted_set(v) + } - /// Create a set from a `Vec`. - /// Assume `v` is sorted and contain unique elements. - pub fn from_sorted_set(v: Vec) -> Self { - Self(v) - } + /// Create a set from a `Vec`. + /// Assume `v` is sorted and contain unique elements. + pub fn from_sorted_set(v: Vec) -> Self { + Self(v) + } - /// Insert an element. - /// Return true if insertion happened. - pub fn insert(&mut self, value: T) -> bool { - match self.0.binary_search(&value) { - Ok(_) => false, - Err(loc) => { - self.0.insert(loc, value); - true - } - } - } + /// Insert an element. + /// Return true if insertion happened. + pub fn insert(&mut self, value: T) -> bool { + match self.0.binary_search(&value) { + Ok(_) => false, + Err(loc) => { + self.0.insert(loc, value); + true + } + } + } - /// Remove an element. - /// Return true if removal happened. - pub fn remove(&mut self, value: &T) -> bool { - match self.0.binary_search(value) { - Ok(loc) => { - self.0.remove(loc); - true - } - Err(_) => false, - } - } + /// Remove an element. + /// Return true if removal happened. + pub fn remove(&mut self, value: &T) -> bool { + match self.0.binary_search(value) { + Ok(loc) => { + self.0.remove(loc); + true + } + Err(_) => false, + } + } - /// Return if the set contains `value` - pub fn contains(&self, value: &T) -> bool { - self.0.binary_search(value).is_ok() - } + /// Return if the set contains `value` + pub fn contains(&self, value: &T) -> bool { + self.0.binary_search(value).is_ok() + } - /// Clear the set - pub fn clear(&mut self) { - self.0.clear(); - } + /// Clear the set + pub fn clear(&mut self) { + self.0.clear(); + } } impl From> for OrderedSet { - fn from(v: Vec) -> Self { - Self::from(v) - } + fn from(v: Vec) -> Self { + Self::from(v) + } } diff --git a/external/pallets/parachain-staking/src/tests.rs b/external/pallets/parachain-staking/src/tests.rs index 113c21e96..464129f84 100644 --- a/external/pallets/parachain-staking/src/tests.rs +++ b/external/pallets/parachain-staking/src/tests.rs @@ -22,16 +22,16 @@ //! 3. Public (Collator, Nominator) //! 4. Miscellaneous Property-Based Tests -use crate::auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}; -use crate::delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}; -use crate::mock::{ - roll_blocks, roll_to, roll_to_round_begin, roll_to_round_end, set_author, Balances, - BlockNumber, ExtBuilder, ParachainStaking, RuntimeOrigin, Test, -}; use crate::{ - assert_events_emitted, assert_events_emitted_match, assert_events_eq, assert_no_events, - AtStake, Bond, CollatorStatus, DelegationScheduledRequests, DelegatorAdded, DelegatorState, - DelegatorStatus, Error, Event, Range, DELEGATOR_LOCK_ID, + assert_events_emitted, assert_events_emitted_match, assert_events_eq, assert_no_events, + auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}, + delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, + mock::{ + roll_blocks, roll_to, roll_to_round_begin, roll_to_round_end, set_author, Balances, + BlockNumber, ExtBuilder, ParachainStaking, RuntimeOrigin, Test, + }, + AtStake, Bond, CollatorStatus, DelegationScheduledRequests, DelegatorAdded, DelegatorState, + DelegatorStatus, Error, Event, Range, DELEGATOR_LOCK_ID, }; use frame_support::{assert_noop, assert_ok}; use sp_runtime::{traits::Zero, DispatchError, ModuleError, Perbill, Percent}; @@ -40,629 +40,510 @@ use sp_runtime::{traits::Zero, DispatchError, ModuleError, Perbill, Percent}; #[test] fn invalid_root_origin_fails() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::signed(45), 6u32), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_collator_commission( - RuntimeOrigin::signed(45), - Perbill::from_percent(5) - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::signed(45), 3u32), - sp_runtime::DispatchError::BadOrigin - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::signed(45), 6u32), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_collator_commission( + RuntimeOrigin::signed(45), + Perbill::from_percent(5) + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::signed(45), 3u32), + sp_runtime::DispatchError::BadOrigin + ); + }); } // SET TOTAL SELECTED #[test] fn set_total_selected_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - // before we can bump total_selected we must bump the blocks per round - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 6u32 - )); - roll_blocks(1); - assert_ok!(ParachainStaking::set_total_selected( - RuntimeOrigin::root(), - 6u32 - )); - assert_events_eq!(Event::TotalSelectedSet { - old: 5u32, - new: 6u32 - }); - }); + ExtBuilder::default().build().execute_with(|| { + // before we can bump total_selected we must bump the blocks per round + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + roll_blocks(1); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); + assert_events_eq!(Event::TotalSelectedSet { old: 5u32, new: 6u32 }); + }); } #[test] fn set_total_selected_fails_if_above_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); // test relies on this - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); // test relies on this + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); } #[test] fn set_total_selected_passes_if_equal_to_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 10u32 - )); - assert_ok!(ParachainStaking::set_total_selected( - RuntimeOrigin::root(), - 10u32 - )); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 10u32)); + }); } #[test] fn set_total_selected_passes_if_below_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 10u32 - )); - assert_ok!(ParachainStaking::set_total_selected( - RuntimeOrigin::root(), - 9u32 - )); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); + }); } #[test] fn set_blocks_per_round_fails_if_below_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 20u32 - )); - assert_ok!(ParachainStaking::set_total_selected( - RuntimeOrigin::root(), - 15u32 - )); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 14u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 20u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 15u32)); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 14u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); } #[test] fn set_blocks_per_round_passes_if_equal_to_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 10u32 - )); - assert_ok!(ParachainStaking::set_total_selected( - RuntimeOrigin::root(), - 9u32 - )); - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 9u32 - )); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 9u32)); + }); } #[test] fn set_blocks_per_round_passes_if_above_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); // test relies on this - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 6u32 - )); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); // test relies on this + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + }); } #[test] fn set_total_selected_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - // round length must be >= total_selected, so update that first - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 10u32 - )); + ExtBuilder::default().build().execute_with(|| { + // round length must be >= total_selected, so update that first + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_eq!(ParachainStaking::total_selected(), 5u32); - assert_ok!(ParachainStaking::set_total_selected( - RuntimeOrigin::root(), - 6u32 - )); - assert_eq!(ParachainStaking::total_selected(), 6u32); - }); + assert_eq!(ParachainStaking::total_selected(), 5u32); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); + assert_eq!(ParachainStaking::total_selected(), 6u32); + }); } #[test] fn cannot_set_total_selected_to_current_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 5u32), - Error::::NoWritingSameValue - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 5u32), + Error::::NoWritingSameValue + ); + }); } #[test] fn cannot_set_total_selected_below_module_min() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 4u32), - Error::::CannotSetBelowMin - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 4u32), + Error::::CannotSetBelowMin + ); + }); } // SET COLLATOR COMMISSION #[test] fn set_collator_commission_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(5) - )); - assert_events_eq!(Event::CollatorCommissionSet { - old: Perbill::from_percent(20), - new: Perbill::from_percent(5), - }); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(5) + )); + assert_events_eq!(Event::CollatorCommissionSet { + old: Perbill::from_percent(20), + new: Perbill::from_percent(5), + }); + }); } #[test] fn set_collator_commission_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!( - ParachainStaking::collator_commission(), - Perbill::from_percent(20) - ); - assert_ok!(ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(5) - )); - assert_eq!( - ParachainStaking::collator_commission(), - Perbill::from_percent(5) - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(20)); + assert_ok!(ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(5) + )); + assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(5)); + }); } #[test] fn cannot_set_collator_commission_to_current_collator_commission() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(20) - ), - Error::::NoWritingSameValue - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(20) + ), + Error::::NoWritingSameValue + ); + }); } // SET BLOCKS PER ROUND #[test] fn set_blocks_per_round_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 6u32 - )); - assert_events_eq!(Event::BlocksPerRoundSet { - current_round: 1, - first_block: 0, - old: 5, - new: 6, - new_per_round_inflation_min: Perbill::from_parts(926), - new_per_round_inflation_ideal: Perbill::from_parts(926), - new_per_round_inflation_max: Perbill::from_parts(926), - }); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + assert_events_eq!(Event::BlocksPerRoundSet { + current_round: 1, + first_block: 0, + old: 5, + new: 6, + new_per_round_inflation_min: Perbill::from_parts(926), + new_per_round_inflation_ideal: Perbill::from_parts(926), + new_per_round_inflation_max: Perbill::from_parts(926), + }); + }); } #[test] fn set_blocks_per_round_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 6u32 - )); - assert_eq!(ParachainStaking::round().length, 6); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + assert_eq!(ParachainStaking::round().length, 6); + }); } #[test] fn cannot_set_blocks_per_round_below_module_min() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 2u32), - Error::::CannotSetBelowMin - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 2u32), + Error::::CannotSetBelowMin + ); + }); } #[test] fn cannot_set_blocks_per_round_to_current_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32), - Error::::NoWritingSameValue - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32), + Error::::NoWritingSameValue + ); + }); } #[test] fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // we can't lower the blocks per round because it must be above the number of collators, - // and we can't lower the number of collators because it must be above - // MinSelectedCandidates. so we first raise blocks per round, then lower it. - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 10u32 - )); - - roll_to(10); - assert_events_emitted!(Event::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 20 - },); - roll_to(17); - assert_ok!(ParachainStaking::set_blocks_per_round( - RuntimeOrigin::root(), - 5u32 - )); - roll_to(18); - assert_events_emitted!(Event::NewRound { - starting_block: 18, - round: 3, - selected_collators_number: 1, - total_balance: 20 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // we can't lower the blocks per round because it must be above the number of collators, + // and we can't lower the number of collators because it must be above + // MinSelectedCandidates. so we first raise blocks per round, then lower it. + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + + roll_to(10); + assert_events_emitted!(Event::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 20 + },); + roll_to(17); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32)); + roll_to(18); + assert_events_emitted!(Event::NewRound { + starting_block: 18, + round: 3, + selected_collators_number: 1, + total_balance: 20 + }); + }); } // ~~ MONETARY GOVERNANCE ~~ #[test] fn invalid_monetary_origin_fails() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::signed(45), - Range { - min: 3u32.into(), - ideal: 4u32.into(), - max: 5u32.into() - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_parachain_bond_account(RuntimeOrigin::signed(45), 11), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::signed(45), - Percent::from_percent(2) - ), - sp_runtime::DispatchError::BadOrigin - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::signed(45), + Range { min: 3u32.into(), ideal: 4u32.into(), max: 5u32.into() } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::signed(45), + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::signed(45), + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_parachain_bond_account(RuntimeOrigin::signed(45), 11), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::signed(45), + Percent::from_percent(2) + ), + sp_runtime::DispatchError::BadOrigin + ); + }); } // SET STAKING EXPECTATIONS #[test] fn set_staking_event_emits_event_correctly() { - ExtBuilder::default().build().execute_with(|| { - // valid call succeeds - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { - min: 3u128, - ideal: 4u128, - max: 5u128, - } - )); - assert_events_eq!(Event::StakeExpectationsSet { - expect_min: 3u128, - expect_ideal: 4u128, - expect_max: 5u128, - }); - }); + ExtBuilder::default().build().execute_with(|| { + // valid call succeeds + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + )); + assert_events_eq!(Event::StakeExpectationsSet { + expect_min: 3u128, + expect_ideal: 4u128, + expect_max: 5u128, + }); + }); } #[test] fn set_staking_updates_storage_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { - min: 700, - ideal: 700, - max: 700 - } - ); - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { - min: 3u128, - ideal: 4u128, - max: 5u128, - } - )); - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { - min: 3u128, - ideal: 4u128, - max: 5u128 - } - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { min: 700, ideal: 700, max: 700 } + ); + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + )); + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { min: 3u128, ideal: 4u128, max: 5u128 } + ); + }); } #[test] fn cannot_set_invalid_staking_expectations() { - ExtBuilder::default().build().execute_with(|| { - // invalid call fails - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { - min: 5u128, - ideal: 4u128, - max: 3u128 - } - ), - Error::::InvalidSchedule - ); - }); + ExtBuilder::default().build().execute_with(|| { + // invalid call fails + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 5u128, ideal: 4u128, max: 3u128 } + ), + Error::::InvalidSchedule + ); + }); } #[test] fn cannot_set_same_staking_expectations() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { - min: 3u128, - ideal: 4u128, - max: 5u128 - } - )); - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { - min: 3u128, - ideal: 4u128, - max: 5u128 - } - ), - Error::::NoWritingSameValue - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + )); + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + ), + Error::::NoWritingSameValue + ); + }); } // SET INFLATION #[test] fn set_inflation_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = ( - Perbill::from_percent(3), - Perbill::from_percent(4), - Perbill::from_percent(5), - ); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - )); - assert_events_eq!(Event::InflationSet { - annual_min: min, - annual_ideal: ideal, - annual_max: max, - round_min: Perbill::from_parts(57), - round_ideal: Perbill::from_parts(75), - round_max: Perbill::from_parts(93), - }); - }); + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = + (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + )); + assert_events_eq!(Event::InflationSet { + annual_min: min, + annual_ideal: ideal, + annual_max: max, + round_min: Perbill::from_parts(57), + round_ideal: Perbill::from_parts(75), + round_max: Perbill::from_parts(93), + }); + }); } #[test] fn set_inflation_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = ( - Perbill::from_percent(3), - Perbill::from_percent(4), - Perbill::from_percent(5), - ); - assert_eq!( - ParachainStaking::inflation_config().annual, - Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50) - } - ); - assert_eq!( - ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5) - } - ); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); - assert_eq!( - ParachainStaking::inflation_config().annual, - Range { min, ideal, max } - ); - assert_eq!( - ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_parts(57), - ideal: Perbill::from_parts(75), - max: Perbill::from_parts(93) - } - ); - }); + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = + (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); + assert_eq!( + ParachainStaking::inflation_config().annual, + Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50) + } + ); + assert_eq!( + ParachainStaking::inflation_config().round, + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5) + } + ); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); + assert_eq!(ParachainStaking::inflation_config().annual, Range { min, ideal, max }); + assert_eq!( + ParachainStaking::inflation_config().round, + Range { + min: Perbill::from_parts(57), + ideal: Perbill::from_parts(75), + max: Perbill::from_parts(93) + } + ); + }); } #[test] fn cannot_set_invalid_inflation() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(3) - } - ), - Error::::InvalidSchedule - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(3) + } + ), + Error::::InvalidSchedule + ); + }); } #[test] fn cannot_set_same_inflation() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = ( - Perbill::from_percent(3), - Perbill::from_percent(4), - Perbill::from_percent(5), - ); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); - assert_noop!( - ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), - Error::::NoWritingSameValue - ); - }); + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = + (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); + assert_noop!( + ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), + Error::::NoWritingSameValue + ); + }); } // SET PARACHAIN BOND ACCOUNT #[test] fn set_parachain_bond_account_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_parachain_bond_account( - RuntimeOrigin::root(), - 11 - )); - assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); + assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); + }); } #[test] fn set_parachain_bond_account_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::parachain_bond_info().account, 0); - assert_ok!(ParachainStaking::set_parachain_bond_account( - RuntimeOrigin::root(), - 11 - )); - assert_eq!(ParachainStaking::parachain_bond_info().account, 11); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::parachain_bond_info().account, 0); + assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); + assert_eq!(ParachainStaking::parachain_bond_info().account, 11); + }); } // SET PARACHAIN BOND RESERVE PERCENT #[test] fn set_parachain_bond_reserve_percent_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_events_eq!(Event::ParachainBondReservePercentSet { - old: Percent::from_percent(30), - new: Percent::from_percent(50), - }); - }); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_events_eq!(Event::ParachainBondReservePercentSet { + old: Percent::from_percent(30), + new: Percent::from_percent(50), + }); + }); } #[test] fn set_parachain_bond_reserve_percent_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!( - ParachainStaking::parachain_bond_info().percent, - Percent::from_percent(30) - ); - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_eq!( - ParachainStaking::parachain_bond_info().percent, - Percent::from_percent(50) - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(30)); + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(50)); + }); } #[test] fn cannot_set_same_parachain_bond_reserve_percent() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(30) - ), - Error::::NoWritingSameValue - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(30) + ), + Error::::NoWritingSameValue + ); + }); } // ~~ PUBLIC ~~ @@ -671,2444 +552,1999 @@ fn cannot_set_same_parachain_bond_reserve_percent() { #[test] fn join_candidates_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 10u128, - 0u32 - )); - assert_events_eq!(Event::JoinedCollatorCandidates { - account: 1, - amount_locked: 10u128, - new_total_amt_locked: 10u128, - }); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + assert_events_eq!(Event::JoinedCollatorCandidates { + account: 1, + amount_locked: 10u128, + new_total_amt_locked: 10u128, + }); + }); } #[test] fn join_candidates_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 10u128, - 0u32 - )); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); } #[test] fn join_candidates_increases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 0); - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 10u128, - 0u32 - )); - assert_eq!(ParachainStaking::total(), 10); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::total(), 0); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + assert_eq!(ParachainStaking::total(), 10); + }); } #[test] fn join_candidates_creates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::candidate_info(1).is_none()); - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 10u128, - 0u32 - )); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just joined => exists"); - assert_eq!(candidate_state.bond, 10u128); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert!(ParachainStaking::candidate_info(1).is_none()); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + let candidate_state = ParachainStaking::candidate_info(1).expect("just joined => exists"); + assert_eq!(candidate_state.bond, 10u128); + }); } #[test] fn join_candidates_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 10u128, - 0u32 - )); - let candidate_pool = ParachainStaking::candidate_pool(); - assert_eq!(candidate_pool.0[0].owner, 1); - assert_eq!(candidate_pool.0[0].amount, 10); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + let candidate_pool = ParachainStaking::candidate_pool(); + assert_eq!(candidate_pool.0[0].owner, 1); + assert_eq!(candidate_pool.0[0].amount, 10); + }); } #[test] fn cannot_join_candidates_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_candidates(vec![(1, 500)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), - Error::::CandidateExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_candidates(vec![(1, 500)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), + Error::::CandidateExists + ); + }); } #[test] fn cannot_join_candidates_if_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 50), (2, 20)]) - .with_candidates(vec![(1, 50)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(2), 10u128, 1u32), - Error::::DelegatorExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50), (2, 20)]) + .with_candidates(vec![(1, 50)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(2), 10u128, 1u32), + Error::::DelegatorExists + ); + }); } #[test] fn cannot_join_candidates_without_min_bond() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 9u128, 100u32), - Error::::CandidateBondBelowMin - ); - }); + ExtBuilder::default().with_balances(vec![(1, 1000)]).build().execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 9u128, 100u32), + Error::::CandidateBondBelowMin + ); + }); } #[test] fn cannot_join_candidates_with_more_than_available_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 500)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 501u128, 100u32), - DispatchError::Module(ModuleError { - index: 2, - error: [8, 0, 0, 0], - message: Some("InsufficientBalance") - }) - ); - }); + ExtBuilder::default().with_balances(vec![(1, 500)]).build().execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 501u128, 100u32), + DispatchError::Module(ModuleError { + index: 2, + error: [8, 0, 0, 0], + message: Some("InsufficientBalance") + }) + ); + }); } #[test] fn insufficient_join_candidates_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - for i in 0..5 { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 20, i), - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + for i in 0..5 { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 20, i), + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + } + }); } #[test] fn sufficient_join_candidates_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - let mut count = 5u32; - for i in 6..10 { - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(i), - 20, - count - )); - count += 1u32; - } - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + let mut count = 5u32; + for i in 6..10 { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(i), 20, count)); + count += 1u32; + } + }); } // SCHEDULE LEAVE CANDIDATES #[test] fn leave_candidates_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 1, - candidate: 1, - scheduled_exit: 3 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 1, + candidate: 1, + scheduled_exit: 3 + }); + }); } #[test] fn leave_candidates_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); } #[test] fn cannot_leave_candidates_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateDNE - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateDNE + ); + }); } #[test] fn cannot_leave_candidates_if_already_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateAlreadyLeaving - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateAlreadyLeaving + ); + }); } #[test] fn insufficient_leave_candidates_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - for i in 1..6 { - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 4u32), - Error::::TooLowCandidateCountToLeaveCandidates - ); - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + for i in 1..6 { + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 4u32), + Error::::TooLowCandidateCountToLeaveCandidates + ); + } + }); } #[test] fn sufficient_leave_candidates_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - let mut count = 5u32; - for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - count - )); - count -= 1u32; - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + let mut count = 5u32; + for i in 1..6 { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + count + )); + count -= 1u32; + } + }); } // EXECUTE LEAVE CANDIDATES #[test] fn execute_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 0 - )); - assert_events_emitted!(Event::CandidateLeft { - ex_candidate: 1, - unlocked_amount: 10, - new_total_amt_locked: 0 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_events_emitted!(Event::CandidateLeft { + ex_candidate: 1, + unlocked_amount: 10, + new_total_amt_locked: 0 + }); + }); } #[test] fn execute_leave_candidates_callable_by_any_signed() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(2), - 1, - 0 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); + }); } #[test] fn execute_leave_candidates_requires_correct_weight_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 10), (3, 10), (4, 10)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 10), (4, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - roll_to(10); - for i in 0..3 { - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, i), - Error::::TooLowCandidateDelegationCountToLeaveCandidates - ); - } - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(2), - 1, - 3 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 10), (3, 10), (4, 10)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 10), (4, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + for i in 0..3 { + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, i), + Error::::TooLowCandidateDelegationCountToLeaveCandidates + ); + } + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 3)); + }); } #[test] fn execute_leave_candidates_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 0 - )); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); } #[test] fn execute_leave_candidates_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 10); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 0 - )); - assert_eq!(ParachainStaking::total(), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 10); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::total(), 0); + }); } #[test] fn execute_leave_candidates_removes_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 0 - )); - assert!(ParachainStaking::candidate_info(1).is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert!(ParachainStaking::candidate_info(1).is_none()); + }); } #[test] fn execute_leave_candidates_removes_pending_delegation_requests() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 15)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 1 - )); - assert!(ParachainStaking::candidate_info(1).is_none()); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation request not removed" - ); - assert!( - !>::contains_key(&1), - "the key was not removed from storage" - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 15)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); + assert!(ParachainStaking::candidate_info(1).is_none()); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation request not removed" + ); + assert!( + !>::contains_key(1), + "the key was not removed from storage" + ); + }); } #[test] fn cannot_execute_leave_candidates_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(9); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(3), - 1, - 0 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(9); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); + }); } // CANCEL LEAVE CANDIDATES #[test] fn cancel_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert_ok!(ParachainStaking::cancel_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); + }); } #[test] fn cancel_leave_candidates_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert_ok!(ParachainStaking::cancel_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - let candidate = - ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); - assert!(candidate.is_active()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + let candidate = + ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); + assert!(candidate.is_active()); + }); } #[test] fn cancel_leave_candidates_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1u32 - )); - assert_ok!(ParachainStaking::cancel_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); + }); } // GO OFFLINE #[test] fn go_offline_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); + }); } #[test] fn go_offline_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); } #[test] fn go_offline_updates_candidate_state_to_idle() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("is candidate, just offline"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("is candidate, just offline"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + }); } #[test] fn cannot_go_offline_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); + }); } #[test] fn cannot_go_offline_if_already_offline() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(1)), - Error::::AlreadyOffline - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(1)), + Error::::AlreadyOffline + ); + }); } // GO ONLINE #[test] fn go_online_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - roll_blocks(1); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + roll_blocks(1); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); + }); } #[test] fn go_online_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); } #[test] fn go_online_storage_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("offline still exists"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("offline still exists"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + }); } #[test] fn cannot_go_online_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); + }); } #[test] fn cannot_go_online_if_already_online() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::AlreadyActive - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::AlreadyActive + ); + }); } #[test] fn cannot_go_online_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::CannotGoOnlineIfLeaving - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::CannotGoOnlineIfLeaving + ); + }); } // CANDIDATE BOND MORE #[test] fn candidate_bond_more_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::candidate_bond_more( - RuntimeOrigin::signed(1), - 30 - )); - assert_events_eq!(Event::CandidateBondedMore { - candidate: 1, - amount: 30, - new_total_bond: 50 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_events_eq!(Event::CandidateBondedMore { + candidate: 1, + amount: 30, + new_total_bond: 50 + }); + }); } #[test] fn candidate_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); - assert_ok!(ParachainStaking::candidate_bond_more( - RuntimeOrigin::signed(1), - 30 - )); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); } #[test] fn candidate_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::candidate_bond_more( - RuntimeOrigin::signed(1), - 30 - )); - total += 30; - assert_eq!(ParachainStaking::total(), total); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + total += 30; + assert_eq!(ParachainStaking::total(), total); + }); } #[test] fn candidate_bond_more_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - assert_ok!(ParachainStaking::candidate_bond_more( - RuntimeOrigin::signed(1), - 30 - )); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 50); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 50); + }); } #[test] fn candidate_bond_more_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - assert_ok!(ParachainStaking::candidate_bond_more( - RuntimeOrigin::signed(1), - 30 - )); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); + }); } // SCHEDULE CANDIDATE BOND LESS #[test] fn schedule_candidate_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_events_eq!(Event::CandidateBondLessRequested { - candidate: 1, - amount_to_decrease: 10, - execute_round: 3, - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_events_eq!(Event::CandidateBondLessRequested { + candidate: 1, + amount_to_decrease: 10, + execute_round: 3, + }); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_request_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 5 - )); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), - Error::::PendingCandidateRequestAlreadyExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), + Error::::PendingCandidateRequestAlreadyExists + ); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(6), 50), - Error::::CandidateDNE - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(6), 50), + Error::::CandidateDNE + ); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), - Error::::CandidateBondBelowMin - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), + Error::::CandidateBondBelowMin + ); + }); } #[test] fn can_schedule_candidate_bond_less_if_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_exited_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 0 - )); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), - Error::::CandidateDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), + Error::::CandidateDNE + ); + }); } // 2. EXECUTE BOND LESS REQUEST #[test] fn execute_candidate_bond_less_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 50)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 30 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_candidate_bond_less( - RuntimeOrigin::signed(1), - 1 - )); - assert_events_eq!(Event::CandidateBondedLess { - candidate: 1, - amount: 30, - new_bond: 20 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 50)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 30 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_events_eq!(Event::CandidateBondedLess { + candidate: 1, + amount: 30, + new_bond: 20 + }); + }); } #[test] fn execute_candidate_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less( - RuntimeOrigin::signed(1), - 1 - )); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); } #[test] fn execute_candidate_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less( - RuntimeOrigin::signed(1), - 1 - )); - total -= 10; - assert_eq!(ParachainStaking::total(), total); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + total -= 10; + assert_eq!(ParachainStaking::total(), total); + }); } #[test] fn execute_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less( - RuntimeOrigin::signed(1), - 1 - )); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + }); } #[test] fn execute_candidate_bond_less_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less( - RuntimeOrigin::signed(1), - 1 - )); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); } // CANCEL CANDIDATE BOND LESS REQUEST #[test] fn cancel_candidate_bond_less_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less( - RuntimeOrigin::signed(1) - )); - assert_events_emitted!(Event::CancelledCandidateBondLess { - candidate: 1, - amount: 10, - execute_round: 3, - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert_events_emitted!(Event::CancelledCandidateBondLess { + candidate: 1, + amount: 10, + execute_round: 3, + }); + }); } #[test] fn cancel_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less( - RuntimeOrigin::signed(1) - )); - assert!(ParachainStaking::candidate_info(&1) - .unwrap() - .request - .is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); + }); } #[test] fn only_candidate_can_cancel_candidate_bond_less_request() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_noop!( - ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), - Error::::CandidateDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_noop!( + ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), + Error::::CandidateDNE + ); + }); } // DELEGATE #[test] fn delegate_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 10, - 0, - 0 - )); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }); + }); } #[test] fn delegate_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 10 - ); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 10, - 0, - 0 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); } #[test] fn delegate_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_none()); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 10, - 0, - 0 - )); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); - assert_eq!(delegator_state.total(), 10); - assert_eq!(delegator_state.delegations.0[0].owner, 1); - assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_none()); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); + assert_eq!(delegator_state.total(), 10); + assert_eq!(delegator_state.delegations.0[0].owner, 1); + assert_eq!(delegator_state.delegations.0[0].amount, 10); + }); } #[test] fn delegate_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); - assert!(top_delegations.delegations.is_empty()); - assert!(top_delegations.total.is_zero()); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 10, - 0, - 0 - )); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); - assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); - assert_eq!(top_delegations.delegations[0].owner, 2); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); + assert!(top_delegations.delegations.is_empty()); + assert!(top_delegations.total.is_zero()); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); + assert_eq!(candidate_state.total_counted, 40); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); + assert_eq!(top_delegations.delegations[0].owner, 2); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + }); } #[test] fn can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 20, - 0 - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 20, - 0, - 0 - )); - }); + ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); + }); } #[test] fn can_delegate_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 4, - 10, - 0, - 2 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 4, 10, 0, 2)); + }); } #[test] fn cannot_delegate_if_full_and_new_delegation_less_than_or_equal_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 10, 8, 0), - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 10, 8, 0), + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + }); } #[test] fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 11), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(11), - 1, - 11, - 8, - 0 - )); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); - assert_events_emitted!(Event::DelegatorLeft { - delegator: 10, - unstaked_amount: 10 - }); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 11), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 11, 8, 0)); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); + }); } #[test] fn can_still_delegate_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 3, - 10, - 0, - 1 - ),); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 3, 10, 0, 1),); + }); } #[test] fn cannot_delegate_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0), - Error::::CandidateExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0), + Error::::CandidateExists + ); + }); } #[test] fn cannot_delegate_if_already_delegated() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 1), - Error::::AlreadyDelegatedCandidate - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 1), + Error::::AlreadyDelegatedCandidate + ); + }); } #[test] fn cannot_delegate_more_than_max_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 6, 10, 0, 4), - Error::::ExceedMaxDelegationsPerDelegator, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 6, 10, 0, 4), + Error::::ExceedMaxDelegationsPerDelegator, + ); + }); } #[test] fn sufficient_delegate_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - let mut count = 4u32; - for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); - count += 1u32; - } - let mut count = 0u32; - for i in 3..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 2, - 10, - count, - 1u32 - )); - count += 1u32; - } - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + // let mut count = 4u32; + for (count, i) in (7..11).enumerate() { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count as u32, + 0u32 + )); + // count += 1u32; + } + // let mut count = 0u32; + for (count, i) in (3..11).enumerate() { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 2, + 10, + count as u32, + 1u32 + )); + // count += 1u32; + } + }); } #[test] fn insufficient_delegate_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - let mut count = 3u32; - for i in 7..11 { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32), - Error::::TooLowCandidateDelegationCountToDelegate - ); - } - // to set up for next error test - count = 4u32; - for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); - count += 1u32; - } - count = 0u32; - for i in 3..11 { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 0u32), - Error::::TooLowDelegationCountToDelegate - ); - count += 1u32; - } - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + let mut count = 3u32; + for i in 7..11 { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32), + Error::::TooLowCandidateDelegationCountToDelegate + ); + } + // to set up for next error test + count = 4u32; + for i in 7..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); + count += 1u32; + } + count = 0u32; + for i in 3..11 { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 0u32), + Error::::TooLowDelegationCountToDelegate + ); + count += 1u32; + } + }); } // SCHEDULE LEAVE DELEGATORS #[test] fn schedule_leave_delegators_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); + }); } #[test] fn cannot_schedule_leave_delegators_if_already_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorAlreadyLeaving - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorAlreadyLeaving + ); + }); } #[test] fn cannot_schedule_leave_delegators_if_not_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorDNE + ); + }); } // EXECUTE LEAVE DELEGATORS #[test] fn execute_leave_delegators_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeft { - delegator: 2, - unstaked_amount: 10 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + }); } #[test] fn execute_leave_delegators_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 00 - ); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 10 - ); - assert_eq!(crate::mock::query_lock_amount(2, DELEGATOR_LOCK_ID), None); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 00); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + assert_eq!(crate::mock::query_lock_amount(2, DELEGATOR_LOCK_ID), None); + }); } #[test] fn execute_leave_delegators_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 30); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_eq!(ParachainStaking::total(), 30); + }); } #[test] fn execute_leave_delegators_removes_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_some()); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::delegator_state(2).is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_some()); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert!(ParachainStaking::delegator_state(2).is_none()); + }); } #[test] fn execute_leave_delegators_removes_pending_delegation_requests() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 15)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::delegator_state(2).is_none()); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation request not removed" - ) - }); + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 15)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert!(ParachainStaking::delegator_state(2).is_none()); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation request not removed" + ) + }); } #[test] fn execute_leave_delegators_removes_delegations_from_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(2, 20), (3, 20), (4, 20), (5, 20)]) - .with_delegations(vec![(1, 2, 10), (1, 3, 10), (1, 4, 10), (1, 5, 10)]) - .build() - .execute_with(|| { - for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); - assert_eq!(top_delegations.delegations[0].owner, 1); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - } - assert_eq!( - ParachainStaking::delegator_state(1) - .unwrap() - .delegations - .0 - .len(), - 4usize - ); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(1) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(1), - 1, - 10 - )); - for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); - assert_eq!(candidate_state.total_counted, 20); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); - assert!(top_delegations.delegations.is_empty()); - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(2, 20), (3, 20), (4, 20), (5, 20)]) + .with_delegations(vec![(1, 2, 10), (1, 3, 10), (1, 4, 10), (1, 5, 10)]) + .build() + .execute_with(|| { + for i in 2..6 { + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + assert_eq!(top_delegations.delegations[0].owner, 1); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + } + assert_eq!(ParachainStaking::delegator_state(1).unwrap().delegations.0.len(), 4usize); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(1))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(1), 1, 10)); + for i in 2..6 { + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + assert_eq!(candidate_state.total_counted, 20); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + assert!(top_delegations.delegations.is_empty()); + } + }); } #[test] fn cannot_execute_leave_delegators_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorCannotLeaveYet - ); - // can execute after delay - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorCannotLeaveYet + ); + // can execute after delay + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + }); } #[test] fn cannot_execute_leave_delegators_if_single_delegation_revoke_manually_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 3 - )); - roll_to(10); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2), - Error::::DelegatorNotLeaving - ); - // can execute after manually scheduling revoke, and the round delay after which - // all revokes can be executed - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 3 - )); - roll_to(20); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 2 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); + roll_to(10); + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2), + Error::::DelegatorNotLeaving + ); + // can execute after manually scheduling revoke, and the round delay after which + // all revokes can be executed + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + roll_to(20); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); + }); } #[test] fn insufficient_execute_leave_delegators_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for i in 3..7 { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(i) - )); - } - roll_to(10); - for i in 3..7 { - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 0), - Error::::TooLowDelegationCountToLeaveDelegators - ); - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + for i in 3..7 { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); + } + roll_to(10); + for i in 3..7 { + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 0), + Error::::TooLowDelegationCountToLeaveDelegators + ); + } + }); } #[test] fn sufficient_execute_leave_delegators_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for i in 3..7 { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(i) - )); - } - roll_to(10); - for i in 3..7 { - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(i), - i, - 1 - )); - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + for i in 3..7 { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); + } + roll_to(10); + for i in 3..7 { + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(i), + i, + 1 + )); + } + }); } // CANCEL LEAVE DELEGATORS #[test] fn cancel_leave_delegators_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_ok!(ParachainStaking::cancel_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_events_emitted!(Event::DelegatorExitCancelled { delegator: 2 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_emitted!(Event::DelegatorExitCancelled { delegator: 2 }); + }); } #[test] fn cancel_leave_delegators_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_ok!(ParachainStaking::cancel_leave_delegators( - RuntimeOrigin::signed(2) - )); - let delegator = - ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); - assert!(delegator.is_active()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + let delegator = + ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); + assert!(delegator.is_active()); + }); } #[test] fn cannot_cancel_leave_delegators_if_single_delegation_revoke_manually_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 3 - )); - roll_to(10); - assert_noop!( - ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorNotLeaving - ); - // can execute after manually scheduling revoke, without waiting for round delay after - // which all revokes can be executed - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 3 - )); - assert_ok!(ParachainStaking::cancel_leave_delegators( - RuntimeOrigin::signed(2) - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); + roll_to(10); + assert_noop!( + ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorNotLeaving + ); + // can execute after manually scheduling revoke, without waiting for round delay after + // which all revokes can be executed + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + }); } // SCHEDULE REVOKE DELEGATION #[test] fn revoke_delegation_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - roll_to_round_begin(3); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_eq!( - Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }, - Event::DelegationRevoked { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + roll_to_round_begin(3); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_eq!( + Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }, + Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, + ); + }); } #[test] fn can_revoke_delegation_if_revoking_another_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - // this is an exit implicitly because last delegation revoked - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 3 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + // this is an exit implicitly because last delegation revoked + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + }); } #[test] fn delegator_not_allowed_revoke_if_already_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), - >::PendingDelegationRequestAlreadyExists, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), + >::PendingDelegationRequestAlreadyExists, + ); + }); } #[test] fn cannot_revoke_delegation_if_not_delegator() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1), - Error::::DelegatorDNE - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1), + Error::::DelegatorDNE + ); + }); } #[test] fn cannot_revoke_delegation_that_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), - Error::::DelegationDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), + Error::::DelegationDNE + ); + }); } #[test] // See `cannot_execute_revoke_delegation_below_min_delegator_stake` for where the "must be above // MinDelegatorStk" rule is now enforced. fn can_schedule_revoke_delegation_below_min_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 8), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 8), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + }); } // DELEGATOR BOND MORE #[test] fn delegator_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); } #[test] fn delegator_bond_more_increases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_eq!(ParachainStaking::total(), 45); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::total(), 45); + }); } #[test] fn delegator_bond_more_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::delegator_state(2) - .expect("exists") - .total(), - 10 - ); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_eq!( - ParachainStaking::delegator_state(2) - .expect("exists") - .total(), - 15 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 15); + }); } #[test] fn delegator_bond_more_updates_candidate_state_top_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, - 10 - ); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, - 15 - ); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 15); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 15); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 15); + }); } #[test] fn delegator_bond_more_updates_candidate_state_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - ]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::bottom_delegations(1) - .expect("exists") - .delegations[0] - .owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1) - .expect("exists") - .delegations[0] - .amount, - 10 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_events_eq!(Event::DelegationIncreased { - delegator: 2, - candidate: 1, - amount: 5, - in_top: false - }); - assert_eq!( - ParachainStaking::bottom_delegations(1) - .expect("exists") - .delegations[0] - .owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1) - .expect("exists") - .delegations[0] - .amount, - 15 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 20), (4, 1, 20), (5, 1, 20), (6, 1, 20)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, + 10 + ); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_events_eq!(Event::DelegationIncreased { + delegator: 2, + candidate: 1, + amount: 5, + in_top: false + }); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, + 15 + ); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); + }); } #[test] fn delegator_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_eq!(ParachainStaking::total(), 45); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::total(), 45); + }); } #[test] fn can_delegator_bond_more_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + }); } #[test] fn delegator_bond_more_disallowed_when_revoke_scheduled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_noop!( - ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5), - >::PendingDelegationRevoke - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_noop!( + ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5), + >::PendingDelegationRevoke + ); + }); } #[test] fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5, - )); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 1, - 5 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5, + )); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + }); } // DELEGATOR BOND LESS #[test] fn delegator_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - delegator: 2, - candidate: 1, - amount_to_decrease: 5, - execute_round: 3, - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + delegator: 2, + candidate: 1, + amount_to_decrease: 5, + execute_round: 3, + }); + }); } #[test] fn delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + }); } #[test] fn delegator_not_allowed_bond_less_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), - >::PendingDelegationRequestAlreadyExists, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), + >::PendingDelegationRequestAlreadyExists, + ); + }); } #[test] fn cannot_delegator_bond_less_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), - Error::::PendingDelegationRequestAlreadyExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), + Error::::PendingDelegationRequestAlreadyExists + ); + }); } #[test] fn cannot_delegator_bond_less_if_not_delegator() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5), - Error::::DelegatorDNE - ); - }); + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5), + Error::::DelegatorDNE + ); + }); } #[test] fn cannot_delegator_bond_less_if_candidate_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), - Error::::DelegationDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), + Error::::DelegationDNE + ); + }); } #[test] fn cannot_delegator_bond_less_if_delegation_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), - Error::::DelegationDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), + Error::::DelegationDNE + ); + }); } #[test] fn cannot_delegator_bond_less_below_min_collator_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 6), - Error::::DelegatorBondBelowMin - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 6), + Error::::DelegatorBondBelowMin + ); + }); } #[test] fn cannot_delegator_bond_less_more_than_total_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 11), - Error::::DelegatorBondBelowMin - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 11), + Error::::DelegatorBondBelowMin + ); + }); } #[test] fn cannot_delegator_bond_less_below_min_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 8), - Error::::DelegationBelowMin - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 8), + Error::::DelegationBelowMin + ); + }); } // EXECUTE PENDING DELEGATION REQUEST @@ -3117,781 +2553,636 @@ fn cannot_delegator_bond_less_below_min_delegation() { #[test] fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { - // last delegation is revocation - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - assert_events_emitted!(Event::DelegatorLeft { - delegator: 2, - unstaked_amount: 10 - }); - }); + // last delegation is revocation + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + }); } #[test] fn cannot_execute_revoke_delegation_below_min_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 8), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_noop!( - ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorBondBelowMin - ); - // but delegator can cancel the request and request to leave instead: - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(20); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 2 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 8), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_noop!( + ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorBondBelowMin + ); + // but delegator can cancel the request and request to leave instead: + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(20); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); + }); } #[test] fn revoke_delegation_executes_exit_if_last_delegation() { - // last delegation is revocation - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - assert_events_emitted!(Event::DelegatorLeft { - delegator: 2, - unstaked_amount: 10 - }); - }); + // last delegation is revocation + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + }); } #[test] fn execute_revoke_delegation_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + }); } #[test] fn execute_revoke_delegation_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 10 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + }); } #[test] fn execute_revoke_delegation_adds_revocation_to_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert!(ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2) + ); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert!( + ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2) + ); + }); } #[test] fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execution() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2) + ); + }); } #[test] fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation_leave() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation was not removed" - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation was not removed" + ); + }); } #[test] fn execute_revoke_delegation_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 30); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 30); + }); } #[test] fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_some()); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - // this will be confusing for people - // if status is leaving, then execute_delegation_request works if last delegation - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::delegator_state(2).is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_some()); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + // this will be confusing for people + // if status is leaving, then execute_delegation_request works if last delegation + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::delegator_state(2).is_none()); + }); } #[test] fn execute_revoke_delegation_removes_delegation_from_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::candidate_info(1) - .expect("exists") - .delegation_count, - 1u32 - ); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::candidate_info(1) - .expect("exists") - .delegation_count - .is_zero()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_info(1).expect("exists").delegation_count, 1u32); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + ParachainStaking::candidate_info(1).expect("exists").delegation_count.is_zero() + ); + }); } #[test] fn can_execute_revoke_delegation_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - // can execute delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + // can execute delegation request for leaving candidate + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); } #[test] fn can_execute_leave_candidates_if_revoking_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - // revocation executes during execute leave candidates (callable by anyone) - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 1 - )); - assert!(!ParachainStaking::is_delegator(&2)); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::free_balance(&2), 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + // revocation executes during execute leave candidates (callable by anyone) + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); + assert!(!ParachainStaking::is_delegator(&2)); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 10); + }); } #[test] fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(2), - 3, - 10 - )); - roll_to(100); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::is_delegator(&2)); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 10 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 3, 10)); + roll_to(100); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::is_delegator(&2)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + }); } #[test] fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), - Error::::PendingDelegationRequestAlreadyExists - ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 3, - 2 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); - assert_events_eq!( - Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30, - }, - Event::DelegationRevoked { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - }, - Event::DelegationDecreased { - delegator: 2, - candidate: 3, - amount: 2, - in_top: true - }, - ); - assert!(ParachainStaking::is_delegator(&2)); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 22 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), + Error::::PendingDelegationRequestAlreadyExists + ); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 3, + 2 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); + assert_events_eq!( + Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30, + }, + Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, + Event::DelegationDecreased { delegator: 2, candidate: 3, amount: 2, in_top: true }, + ); + assert!(ParachainStaking::is_delegator(&2)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 22); + }); } // 2. EXECUTE BOND LESS #[test] fn execute_delegator_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); + }); } #[test] fn execute_delegator_bond_less_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 35); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 35); + }); } #[test] fn execute_delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::delegator_state(2) - .expect("exists") - .total(), - 10 - ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::delegator_state(2) - .expect("exists") - .total(), - 5 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 5); + }); } #[test] fn execute_delegator_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, - 10 - ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, - 5 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 5); + }); } #[test] fn execute_delegator_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 35); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 35); + }); } #[test] fn execute_delegator_bond_less_updates_just_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 11), - (4, 1, 12), - (5, 1, 14), - (6, 1, 15), - ]) - .build() - .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let pre_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 2 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let post_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - let mut not_equal = false; - for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { - owner: post_owner, - amount: post_amount, - } in &post_call_bottom_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - not_equal = true; - break; - } - } - } - } - assert!(not_equal); - let mut equal = true; - for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { - owner: post_owner, - amount: post_amount, - } in &post_call_top_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - equal = false; - break; - } - } - } - } - assert!(equal); - assert_eq!( - pre_call_candidate_info.total_counted, - post_call_candidate_info.total_counted - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) + .build() + .execute_with(|| { + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 2 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let post_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + let mut not_equal = false; + for Bond { owner, amount } in pre_call_bottom_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_bottom_delegations.delegations + { + if &owner == post_owner && &amount != post_amount { + not_equal = true; + break; + } + } + } + assert!(not_equal); + let mut equal = true; + for Bond { owner, amount } in pre_call_top_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_top_delegations.delegations + { + if &owner == post_owner && &amount != post_amount { + equal = false; + break; + } + } + } + assert!(equal); + assert_eq!( + pre_call_candidate_info.total_counted, + post_call_candidate_info.total_counted + ); + }); } #[test] fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 11), - (4, 1, 12), - (5, 1, 14), - (6, 1, 15), - ]) - .build() - .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let pre_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 4 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let post_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - let mut equal = true; - for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { - owner: post_owner, - amount: post_amount, - } in &post_call_bottom_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - equal = false; - break; - } - } - } - } - assert!(equal); - let mut not_equal = false; - for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { - owner: post_owner, - amount: post_amount, - } in &post_call_top_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - not_equal = true; - break; - } - } - } - } - assert!(not_equal); - assert_eq!( - pre_call_candidate_info.total_counted - 4, - post_call_candidate_info.total_counted - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) + .build() + .execute_with(|| { + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 4 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let post_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + let mut equal = true; + for Bond { owner, amount } in pre_call_bottom_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_bottom_delegations.delegations + { + if &owner == post_owner && &amount != post_amount { + equal = false; + break; + } + } + } + assert!(equal); + let mut not_equal = false; + for Bond { owner, amount } in pre_call_top_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_top_delegations.delegations + { + if &owner == post_owner && &amount != post_amount { + not_equal = true; + break; + } + } + } + assert!(not_equal); + assert_eq!( + pre_call_candidate_info.total_counted - 4, + post_call_candidate_info.total_counted + ); + }); } #[test] fn can_execute_delegator_bond_less_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 1 - )); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - // can execute bond more delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + // can execute bond more delegation request for leaving candidate + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); } // CANCEL PENDING DELEGATION REQUEST @@ -3899,5127 +3190,3726 @@ fn can_execute_delegator_bond_less_for_leaving_candidate() { #[test] fn cancel_revoke_delegation_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - assert_events_emitted!(Event::CancelledDelegationRequest { - delegator: 2, - collator: 1, - cancelled_request: CancelledScheduledRequest { - when_executable: 3, - action: DelegationAction::Revoke(10), - }, - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert_events_emitted!(Event::CancelledDelegationRequest { + delegator: 2, + collator: 1, + cancelled_request: CancelledScheduledRequest { + when_executable: 3, + action: DelegationAction::Revoke(10), + }, + }); + }); } #[test] fn cancel_revoke_delegation_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(10), - }], - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10 - ); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(10), + }], + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10 + ); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2) + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); } // 2. CANCEL DELEGATOR BOND LESS #[test] fn cancel_delegator_bond_less_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - assert_events_emitted!(Event::CancelledDelegationRequest { - delegator: 2, - collator: 1, - cancelled_request: CancelledScheduledRequest { - when_executable: 3, - action: DelegationAction::Decrease(5), - }, - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert_events_emitted!(Event::CancelledDelegationRequest { + delegator: 2, + collator: 1, + cancelled_request: CancelledScheduledRequest { + when_executable: 3, + action: DelegationAction::Decrease(5), + }, + }); + }); } #[test] fn cancel_delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 5 - ); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 5 + ); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2) + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); } // ~~ PROPERTY-BASED TESTS ~~ #[test] fn delegator_schedule_revocation_total() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10 - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 5, - 10, - 0, - 2 - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 3 - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 4 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 20, - ); - roll_to(20); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10, - ); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 4 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10 + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 5, 10, 0, 2)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 4)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 20, + ); + roll_to(20); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10, + ); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 4 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); } #[ignore] #[test] fn parachain_bond_inflation_reserve_matches_config() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - (11, 1), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![ - (6, 1, 10), - (7, 1, 10), - (8, 2, 10), - (9, 2, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_eq!(Balances::free_balance(&11), 1); - // set parachain bond account so DefaultParachainBondReservePercent = 30% of inflation - // is allocated to this account hereafter - assert_ok!(ParachainStaking::set_parachain_bond_account( - RuntimeOrigin::root(), - 11 - )); - assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 2, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, - ); - assert_eq!(Balances::free_balance(&11), 1); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - // distribute total issuance to collator 1 and its delegators 6, 7, 19 - assert_eq!(Balances::free_balance(&11), 16); - // ~ set block author as 1 for all blocks this round - set_author(3, 1, 100); - set_author(4, 1, 100); - set_author(5, 1, 100); - // 1. ensure delegators are paid for 2 rounds after they leave - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), - Error::::DelegatorDNE - ); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(6) - )); - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 15, - }, - Event::CollatorChosen { - round: 4, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 4, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 4, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 4, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 4, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 5, - total_balance: 140, - }, - Event::DelegatorExitScheduled { - round: 4, - delegator: 6, - scheduled_exit: 6, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 20, - }, - Event::Rewarded { - account: 6, - rewards: 5, - }, - Event::Rewarded { - account: 7, - rewards: 5, - }, - Event::Rewarded { - account: 10, - rewards: 5, - }, - ); - // fast forward to block in which delegator 6 exit executes - roll_to_round_begin(5); - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 16, - }, - Event::CollatorChosen { - round: 5, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 5, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 5, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 5, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 5, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 21, - }, - Event::Rewarded { - account: 6, - rewards: 5, - }, - Event::Rewarded { - account: 7, - rewards: 5, - }, - Event::Rewarded { - account: 10, - rewards: 5, - }, - ); - roll_to_round_begin(6); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(6), - 6, - 10 - )); - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 16, - }, - Event::CollatorChosen { - round: 6, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 6, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 6, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 6, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 6, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 140, - }, - Event::DelegatorLeftCandidate { - delegator: 6, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 40, - }, - Event::DelegatorLeft { - delegator: 6, - unstaked_amount: 10, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 22, - }, - Event::Rewarded { - account: 6, - rewards: 6, - }, - Event::Rewarded { - account: 7, - rewards: 6, - }, - Event::Rewarded { - account: 10, - rewards: 6, - }, - ); - roll_to_round_begin(7); - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 17, - }, - Event::CollatorChosen { - round: 7, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 7, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 7, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 7, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 7, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 26, - }, - Event::Rewarded { - account: 7, - rewards: 7, - }, - Event::Rewarded { - account: 10, - rewards: 7, - }, - ); - assert_eq!(Balances::free_balance(&11), 65); - roll_blocks(1); - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_events_eq!(Event::ParachainBondReservePercentSet { - old: Percent::from_percent(30), - new: Percent::from_percent(50), - }); - // 6 won't be paid for this round because they left already - set_author(6, 1, 100); - roll_to_round_begin(8); - // keep paying 6 - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 30, - }, - Event::CollatorChosen { - round: 8, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 8, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 8, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 8, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 8, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 21, - }, - Event::Rewarded { - account: 7, - rewards: 5, - }, - Event::Rewarded { - account: 10, - rewards: 5, - }, - ); - assert_eq!(Balances::free_balance(&11), 95); - set_author(7, 1, 100); - roll_to_round_begin(9); - // no more paying 6 - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 32, - }, - Event::CollatorChosen { - round: 9, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 9, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 9, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 9, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 9, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 22, - }, - Event::Rewarded { - account: 7, - rewards: 5, - }, - Event::Rewarded { - account: 10, - rewards: 5, - }, - ); - assert_eq!(Balances::free_balance(&11), 127); - set_author(8, 1, 100); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(8), - 1, - 10, - 10, - 10 - )); - assert_events_eq!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - roll_to_round_begin(10); - // new delegation is not rewarded yet - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 33, - }, - Event::CollatorChosen { - round: 10, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 10, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 10, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 10, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 10, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 23, - }, - Event::Rewarded { - account: 7, - rewards: 5, - }, - Event::Rewarded { - account: 10, - rewards: 5, - }, - ); - assert_eq!(Balances::free_balance(&11), 160); - set_author(9, 1, 100); - set_author(10, 1, 100); - roll_to_round_begin(11); - // new delegation is still not rewarded yet - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 35, - }, - Event::CollatorChosen { - round: 11, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 11, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 11, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 11, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 11, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 24, - }, - Event::Rewarded { - account: 7, - rewards: 5, - }, - Event::Rewarded { - account: 10, - rewards: 5, - }, - ); - assert_eq!(Balances::free_balance(&11), 195); - roll_to_round_begin(12); - // new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2) - assert_events_eq!( - Event::ReservedForParachainBond { - account: 11, - value: 37, - }, - Event::CollatorChosen { - round: 12, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 12, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 12, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 12, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 12, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 24, - }, - Event::Rewarded { - account: 7, - rewards: 4, - }, - Event::Rewarded { - account: 10, - rewards: 4, - }, - Event::Rewarded { - account: 8, - rewards: 4, - }, - ); - assert_eq!(Balances::free_balance(&11), 232); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + (11, 1), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1); + // set parachain bond account so DefaultParachainBondReservePercent = 30% of inflation + // is allocated to this account hereafter + assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); + assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, + ); + assert_eq!(Balances::free_balance(&11), 1); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + // distribute total issuance to collator 1 and its delegators 6, 7, 19 + assert_eq!(Balances::free_balance(&11), 16); + // ~ set block author as 1 for all blocks this round + set_author(3, 1, 100); + set_author(4, 1, 100); + set_author(5, 1, 100); + // 1. ensure delegators are paid for 2 rounds after they leave + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), + Error::::DelegatorDNE + ); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 15 }, + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 5, + total_balance: 140, + }, + Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 20 }, + Event::Rewarded { account: 6, rewards: 5 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + // fast forward to block in which delegator 6 exit executes + roll_to_round_begin(5); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 16 }, + Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 5, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 21 }, + Event::Rewarded { account: 6, rewards: 5 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + roll_to_round_begin(6); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 16 }, + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 6, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 140, + }, + Event::DelegatorLeftCandidate { + delegator: 6, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 40, + }, + Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 22 }, + Event::Rewarded { account: 6, rewards: 6 }, + Event::Rewarded { account: 7, rewards: 6 }, + Event::Rewarded { account: 10, rewards: 6 }, + ); + roll_to_round_begin(7); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 17 }, + Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 26 }, + Event::Rewarded { account: 7, rewards: 7 }, + Event::Rewarded { account: 10, rewards: 7 }, + ); + assert_eq!(Balances::free_balance(&11), 65); + roll_blocks(1); + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_events_eq!(Event::ParachainBondReservePercentSet { + old: Percent::from_percent(30), + new: Percent::from_percent(50), + }); + // 6 won't be paid for this round because they left already + set_author(6, 1, 100); + roll_to_round_begin(8); + // keep paying 6 + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 30 }, + Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 8, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 21 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 95); + set_author(7, 1, 100); + roll_to_round_begin(9); + // no more paying 6 + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 32 }, + Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 9, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 22 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 127); + set_author(8, 1, 100); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); + assert_events_eq!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + roll_to_round_begin(10); + // new delegation is not rewarded yet + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 33 }, + Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 10, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 23 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 160); + set_author(9, 1, 100); + set_author(10, 1, 100); + roll_to_round_begin(11); + // new delegation is still not rewarded yet + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 35 }, + Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 11, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 24 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 195); + roll_to_round_begin(12); + // new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2) + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 37 }, + Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 12, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 24 }, + Event::Rewarded { account: 7, rewards: 4 }, + Event::Rewarded { account: 10, rewards: 4 }, + Event::Rewarded { account: 8, rewards: 4 }, + ); + assert_eq!(Balances::free_balance(&11), 232); + }); } #[test] fn paid_collator_commission_matches_config() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(4), - 20u128, - 100u32 - )); - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 1, - total_balance: 40, - }, - Event::JoinedCollatorCandidates { - account: 4, - amount_locked: 20, - new_total_amt_locked: 60, - }, - ); - - roll_blocks(1); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(5), - 4, - 10, - 10, - 10 - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(6), - 4, - 10, - 10, - 10 - )); - assert_events_eq!( - Event::Delegation { - delegator: 5, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }, - ); - - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { - round: 3, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 3, - collator_account: 4, - total_exposed_amount: 40, - }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 80, - }, - ); - // only reward author with id 4 - set_author(3, 4, 100); - roll_to_round_begin(5); - // 20% of 10 is commission + due_portion (0) = 2 + 4 = 6 - // all delegator payouts are 10-2 = 8 * stake_pct - assert_events_eq!( - Event::CollatorChosen { - round: 5, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 5, - collator_account: 4, - total_exposed_amount: 40, - }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 2, - total_balance: 80, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 4, - rewards: 18, - }, - Event::Rewarded { - account: 5, - rewards: 6, - }, - Event::Rewarded { - account: 6, - rewards: 6, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(4), 20u128, 100u32)); + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 40 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 1, + total_balance: 40, + }, + Event::JoinedCollatorCandidates { + account: 4, + amount_locked: 20, + new_total_amt_locked: 60, + }, + ); + + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 4, 10, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); + assert_events_eq!( + Event::Delegation { + delegator: 5, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }, + ); + + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 3, collator_account: 4, total_exposed_amount: 40 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 80, + }, + ); + // only reward author with id 4 + set_author(3, 4, 100); + roll_to_round_begin(5); + // 20% of 10 is commission + due_portion (0) = 2 + 4 = 6 + // all delegator payouts are 10-2 = 8 * stake_pct + assert_events_eq!( + Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 40 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 2, + total_balance: 80, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 4, rewards: 18 }, + Event::Rewarded { account: 5, rewards: 6 }, + Event::Rewarded { account: 6, rewards: 6 }, + ); + }); } #[test] fn collator_exit_executes_after_delay() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - roll_to(11); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(2), - 2 - )); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 3, - candidate: 2, - scheduled_exit: 5, - }); - let info = ParachainStaking::candidate_info(&2).unwrap(); - assert_eq!(info.status, CollatorStatus::Leaving(5)); - roll_to(21); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(2), - 2, - 2 - )); - // we must exclude leaving collators from rewards while - // holding them retroactively accountable for previous faults - // (within the last T::SlashingWindow blocks) - assert_events_eq!(Event::CandidateLeft { - ex_candidate: 2, - unlocked_amount: 400, - new_total_amt_locked: 700, - },); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + roll_to(11); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 3, + candidate: 2, + scheduled_exit: 5, + }); + let info = ParachainStaking::candidate_info(&2).unwrap(); + assert_eq!(info.status, CollatorStatus::Leaving(5)); + roll_to(21); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); + // we must exclude leaving collators from rewards while + // holding them retroactively accountable for previous faults + // (within the last T::SlashingWindow blocks) + assert_events_eq!(Event::CandidateLeft { + ex_candidate: 2, + unlocked_amount: 400, + new_total_amt_locked: 700, + },); + }); } #[test] fn collator_selection_chooses_top_candidates() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 33), - (8, 33), - (9, 33), - ]) - .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(6), - 6 - )); - // should choose top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 100, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 90, - }, - Event::CollatorChosen { - round: 2, - collator_account: 3, - total_exposed_amount: 80, - }, - Event::CollatorChosen { - round: 2, - collator_account: 4, - total_exposed_amount: 70, - }, - Event::CollatorChosen { - round: 2, - collator_account: 5, - total_exposed_amount: 60, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 400, - }, - Event::CandidateScheduledExit { - exit_allowed_round: 2, - candidate: 6, - scheduled_exit: 4 - }, - ); - roll_to_round_begin(4); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(6), - 6, - 0 - )); - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(6), - 69u128, - 100u32 - )); - assert_events_eq!( - Event::CandidateLeft { - ex_candidate: 6, - unlocked_amount: 50, - new_total_amt_locked: 400, - }, - Event::JoinedCollatorCandidates { - account: 6, - amount_locked: 69u128, - new_total_amt_locked: 469u128, - }, - ); - roll_to_round_begin(6); - // should choose top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { - round: 6, - collator_account: 1, - total_exposed_amount: 100, - }, - Event::CollatorChosen { - round: 6, - collator_account: 2, - total_exposed_amount: 90, - }, - Event::CollatorChosen { - round: 6, - collator_account: 3, - total_exposed_amount: 80, - }, - Event::CollatorChosen { - round: 6, - collator_account: 4, - total_exposed_amount: 70, - }, - Event::CollatorChosen { - round: 6, - collator_account: 6, - total_exposed_amount: 69, - }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 409, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 33), + (8, 33), + (9, 33), + ]) + .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(6), 6)); + // should choose top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, + Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 60 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 400, + }, + Event::CandidateScheduledExit { + exit_allowed_round: 2, + candidate: 6, + scheduled_exit: 4 + }, + ); + roll_to_round_begin(4); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(6), 6, 0)); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 69u128, 100u32)); + assert_events_eq!( + Event::CandidateLeft { + ex_candidate: 6, + unlocked_amount: 50, + new_total_amt_locked: 400, + }, + Event::JoinedCollatorCandidates { + account: 6, + amount_locked: 69u128, + new_total_amt_locked: 469u128, + }, + ); + roll_to_round_begin(6); + // should choose top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, + Event::CollatorChosen { round: 6, collator_account: 6, total_exposed_amount: 69 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 409, + }, + ); + }); } #[test] fn payout_distribution_to_solo_collators() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (7, 33), - (8, 33), - (9, 33), - ]) - .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // should choose top TotalCandidatesSelected (5), in order - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 100, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 90, - }, - Event::CollatorChosen { - round: 2, - collator_account: 3, - total_exposed_amount: 80, - }, - Event::CollatorChosen { - round: 2, - collator_account: 4, - total_exposed_amount: 70, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 340, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - assert_events_eq!( - Event::CollatorChosen { - round: 4, - collator_account: 1, - total_exposed_amount: 100, - }, - Event::CollatorChosen { - round: 4, - collator_account: 2, - total_exposed_amount: 90, - }, - Event::CollatorChosen { - round: 4, - collator_account: 3, - total_exposed_amount: 80, - }, - Event::CollatorChosen { - round: 4, - collator_account: 4, - total_exposed_amount: 70, - }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 340, - }, - ); - // pay total issuance to 1 at 2nd block - roll_blocks(3); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 205, - }); - // ~ set block author as 1 for 3 blocks this round - set_author(4, 1, 60); - // ~ set block author as 2 for 2 blocks this round - set_author(4, 2, 40); - roll_to_round_begin(6); - // pay 60% total issuance to 1 and 40% total issuance to 2 - assert_events_eq!( - Event::CollatorChosen { - round: 6, - collator_account: 1, - total_exposed_amount: 100, - }, - Event::CollatorChosen { - round: 6, - collator_account: 2, - total_exposed_amount: 90, - }, - Event::CollatorChosen { - round: 6, - collator_account: 3, - total_exposed_amount: 80, - }, - Event::CollatorChosen { - round: 6, - collator_account: 4, - total_exposed_amount: 70, - }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 340, - }, - ); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 129, - }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 2, - rewards: 86, - },); - // ~ each collator produces 1 block this round - set_author(6, 1, 20); - set_author(6, 2, 20); - set_author(6, 3, 20); - set_author(6, 4, 20); - roll_to_round_begin(8); - // pay 20% issuance for all collators - assert_events_eq!( - Event::CollatorChosen { - round: 8, - collator_account: 1, - total_exposed_amount: 100, - }, - Event::CollatorChosen { - round: 8, - collator_account: 2, - total_exposed_amount: 90, - }, - Event::CollatorChosen { - round: 8, - collator_account: 3, - total_exposed_amount: 80, - }, - Event::CollatorChosen { - round: 8, - collator_account: 4, - total_exposed_amount: 70, - }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 340, - }, - ); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 3, - rewards: 56, - }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 4, - rewards: 56, - }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 56, - }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 2, - rewards: 56, - }); - // check that distributing rewards clears awarded pts - assert!(ParachainStaking::awarded_pts(1, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(4, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(4, 2).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 2).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 3).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 4).is_zero()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 1000), (2, 1000), (3, 1000), (4, 1000), (7, 33), (8, 33), (9, 33)]) + .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // should choose top TotalCandidatesSelected (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 340, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 340, + }, + ); + // pay total issuance to 1 at 2nd block + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 205 }); + // ~ set block author as 1 for 3 blocks this round + set_author(4, 1, 60); + // ~ set block author as 2 for 2 blocks this round + set_author(4, 2, 40); + roll_to_round_begin(6); + // pay 60% total issuance to 1 and 40% total issuance to 2 + assert_events_eq!( + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 340, + }, + ); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 129 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 86 },); + // ~ each collator produces 1 block this round + set_author(6, 1, 20); + set_author(6, 2, 20); + set_author(6, 3, 20); + set_author(6, 4, 20); + roll_to_round_begin(8); + // pay 20% issuance for all collators + assert_events_eq!( + Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 340, + }, + ); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 3, rewards: 56 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 4, rewards: 56 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 56 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 56 }); + // check that distributing rewards clears awarded pts + assert!(ParachainStaking::awarded_pts(1, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(4, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(4, 2).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 2).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 3).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 4).is_zero()); + }); } #[test] fn multiple_delegations() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![ - (6, 1, 10), - (7, 1, 10), - (8, 2, 10), - (9, 2, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 2, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(6), - 2, - 10, - 10, - 10 - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(6), - 3, - 10, - 10, - 10 - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(6), - 4, - 10, - 10, - 10 - )); - assert_events_eq!( - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 2, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 3, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - ); - roll_to_round_begin(6); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(7), - 2, - 80, - 10, - 10 - )); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(10), - 2, - 10, - 10, - 10 - )); - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(2), - 5 - )); - assert_events_eq!( - Event::Delegation { - delegator: 7, - locked_amount: 80, - candidate: 2, - delegator_position: DelegatorAdded::AddedToTop { new_total: 130 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 10, - locked_amount: 10, - candidate: 2, - delegator_position: DelegatorAdded::AddedToBottom, - auto_compound: Percent::zero(), - }, - Event::CandidateScheduledExit { - exit_allowed_round: 6, - candidate: 2, - scheduled_exit: 8 - }, - ); - roll_to_round_begin(7); - assert_events_eq!( - Event::CollatorChosen { - round: 7, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 7, - collator_account: 3, - total_exposed_amount: 30, - }, - Event::CollatorChosen { - round: 7, - collator_account: 4, - total_exposed_amount: 30, - }, - Event::CollatorChosen { - round: 7, - collator_account: 5, - total_exposed_amount: 10, - }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, - ); - // verify that delegations are removed after collator leaves, not before - assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); - assert_eq!( - ParachainStaking::delegator_state(7) - .unwrap() - .delegations - .0 - .len(), - 2usize - ); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 40); - assert_eq!( - ParachainStaking::delegator_state(6) - .unwrap() - .delegations - .0 - .len(), - 4usize - ); - assert_eq!(Balances::locks(&6)[0].amount, 40); - assert_eq!(Balances::locks(&7)[0].amount, 90); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&6), - 60 - ); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&7), - 10 - ); - roll_to_round_begin(8); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(2), - 2, - 5 - )); - assert_events_eq!(Event::CandidateLeft { - ex_candidate: 2, - unlocked_amount: 140, - new_total_amt_locked: 120, - }); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 10); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 30); - assert_eq!( - ParachainStaking::delegator_state(7) - .unwrap() - .delegations - .0 - .len(), - 1usize - ); - assert_eq!( - ParachainStaking::delegator_state(6) - .unwrap() - .delegations - .0 - .len(), - 3usize - ); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&6), - 70 - ); - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&7), - 90 - ); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 2, 10, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 3, 10, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); + assert_events_eq!( + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 2, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 3, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + ); + roll_to_round_begin(6); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 2, 80, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 2, 10, 10, 10)); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 5)); + assert_events_eq!( + Event::Delegation { + delegator: 7, + locked_amount: 80, + candidate: 2, + delegator_position: DelegatorAdded::AddedToTop { new_total: 130 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 10, + locked_amount: 10, + candidate: 2, + delegator_position: DelegatorAdded::AddedToBottom, + auto_compound: Percent::zero(), + }, + Event::CandidateScheduledExit { + exit_allowed_round: 6, + candidate: 2, + scheduled_exit: 8 + }, + ); + roll_to_round_begin(7); + assert_events_eq!( + Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 30 }, + Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 30 }, + Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, + ); + // verify that delegations are removed after collator leaves, not before + assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 2usize); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 40); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 4usize); + assert_eq!(Balances::locks(&6)[0].amount, 40); + assert_eq!(Balances::locks(&7)[0].amount, 90); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 60); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 10); + roll_to_round_begin(8); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 5)); + assert_events_eq!(Event::CandidateLeft { + ex_candidate: 2, + unlocked_amount: 140, + new_total_amt_locked: 120, + }); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 10); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 30); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 1usize); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 3usize); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 70); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 90); + }); } #[test] // The test verifies that the pending revoke request is removed by 2's exit so there is no dangling // revoke request after 2 exits fn execute_leave_candidate_removes_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (3, 2, 10), (4, 1, 10), (4, 2, 10)]) - .build() - .execute_with(|| { - // Verifies the revocation request is initially empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); - - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(2), - 2 - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(3), - 2 - )); - // Verifies the revocation request is present - assert!(ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); - - roll_to(16); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(2), - 2, - 2 - )); - // Verifies the revocation request is again empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (3, 2, 10), (4, 1, 10), (4, 2, 10)]) + .build() + .execute_with(|| { + // Verifies the revocation request is initially empty + assert!( + !ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3) + ); + + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); + // Verifies the revocation request is present + assert!( + ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3) + ); + + roll_to(16); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); + // Verifies the revocation request is again empty + assert!( + !ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3) + ); + }); } #[test] fn payouts_follow_delegation_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) - .with_delegations(vec![ - (6, 1, 10), - (7, 1, 10), - (8, 2, 10), - (9, 2, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 2, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 130, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - // distribute total issuance to collator 1 and its delegators 6, 7, 19 - assert_events_eq!( - Event::CollatorChosen { - round: 4, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 4, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 4, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 4, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 23, - }, - Event::Rewarded { - account: 6, - rewards: 7, - }, - Event::Rewarded { - account: 7, - rewards: 7, - }, - Event::Rewarded { - account: 10, - rewards: 7, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(3, 1, 100); - set_author(4, 1, 100); - set_author(5, 1, 100); - set_author(6, 1, 100); - - roll_blocks(1); - // 1. ensure delegators are paid for 2 rounds after they leave - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), - Error::::DelegatorDNE - ); - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(6) - )); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 4, - delegator: 6, - scheduled_exit: 6, - }); - // fast forward to block in which delegator 6 exit executes - roll_to_round_begin(5); - assert_events_eq!( - Event::CollatorChosen { - round: 5, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 5, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 5, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 5, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 24, - }, - Event::Rewarded { - account: 6, - rewards: 8, - }, - Event::Rewarded { - account: 7, - rewards: 8, - }, - Event::Rewarded { - account: 10, - rewards: 8, - }, - ); - // keep paying 6 (note: inflation is in terms of total issuance so that's why 1 is 21) - roll_to_round_begin(6); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(6), - 6, - 10 - )); - assert_events_eq!( - Event::CollatorChosen { - round: 6, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 6, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 6, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 6, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 130, - }, - Event::DelegatorLeftCandidate { - delegator: 6, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 40, - }, - Event::DelegatorLeft { - delegator: 6, - unstaked_amount: 10, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 26, - }, - Event::Rewarded { - account: 6, - rewards: 8, - }, - Event::Rewarded { - account: 7, - rewards: 8, - }, - Event::Rewarded { - account: 10, - rewards: 8, - }, - ); - // 6 won't be paid for this round because they left already - set_author(7, 1, 100); - roll_to_round_begin(7); - // keep paying 6 - assert_events_eq!( - Event::CollatorChosen { - round: 7, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 7, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 7, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 7, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 31, - }, - Event::Rewarded { - account: 7, - rewards: 10, - }, - Event::Rewarded { - account: 10, - rewards: 10, - }, - ); - roll_to_round_begin(8); - assert_events_eq!( - Event::CollatorChosen { - round: 8, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 8, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 8, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 8, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 33, - }, - Event::Rewarded { - account: 7, - rewards: 11, - }, - Event::Rewarded { - account: 10, - rewards: 11, - }, - ); - set_author(8, 1, 100); - roll_to_round_begin(9); - // no more paying 6 - assert_events_eq!( - Event::CollatorChosen { - round: 9, - collator_account: 1, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 9, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 9, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 9, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 34, - }, - Event::Rewarded { - account: 7, - rewards: 11, - }, - Event::Rewarded { - account: 10, - rewards: 11, - }, - ); - roll_blocks(1); - set_author(9, 1, 100); - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(8), - 1, - 10, - 10, - 10 - )); - assert_events_eq!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - - roll_to_round_begin(10); - // new delegation is not rewarded yet - assert_events_eq!( - Event::CollatorChosen { - round: 10, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 10, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 10, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 10, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 36, - }, - Event::Rewarded { - account: 7, - rewards: 12, - }, - Event::Rewarded { - account: 10, - rewards: 12, - }, - ); - set_author(10, 1, 100); - roll_to_round_begin(11); - // new delegation not rewarded yet - assert_events_eq!( - Event::CollatorChosen { - round: 11, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 11, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 11, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 11, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 38, - }, - Event::Rewarded { - account: 7, - rewards: 12, - }, - Event::Rewarded { - account: 10, - rewards: 12, - }, - ); - roll_to_round_begin(12); - // new delegation is rewarded for first time - // 2 rounds after joining (`RewardPaymentDelay` = 2) - assert_events_eq!( - Event::CollatorChosen { - round: 12, - collator_account: 1, - total_exposed_amount: 50, - }, - Event::CollatorChosen { - round: 12, - collator_account: 2, - total_exposed_amount: 40, - }, - Event::CollatorChosen { - round: 12, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 12, - collator_account: 4, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 34, - }, - Event::Rewarded { - account: 7, - rewards: 11, - }, - Event::Rewarded { - account: 10, - rewards: 11, - }, - Event::Rewarded { - account: 8, - rewards: 11, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 130, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + // distribute total issuance to collator 1 and its delegators 6, 7, 19 + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 23 }, + Event::Rewarded { account: 6, rewards: 7 }, + Event::Rewarded { account: 7, rewards: 7 }, + Event::Rewarded { account: 10, rewards: 7 }, + ); + // ~ set block author as 1 for all blocks this round + set_author(3, 1, 100); + set_author(4, 1, 100); + set_author(5, 1, 100); + set_author(6, 1, 100); + + roll_blocks(1); + // 1. ensure delegators are paid for 2 rounds after they leave + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), + Error::::DelegatorDNE + ); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 4, + delegator: 6, + scheduled_exit: 6, + }); + // fast forward to block in which delegator 6 exit executes + roll_to_round_begin(5); + assert_events_eq!( + Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 24 }, + Event::Rewarded { account: 6, rewards: 8 }, + Event::Rewarded { account: 7, rewards: 8 }, + Event::Rewarded { account: 10, rewards: 8 }, + ); + // keep paying 6 (note: inflation is in terms of total issuance so that's why 1 is 21) + roll_to_round_begin(6); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); + assert_events_eq!( + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 130, + }, + Event::DelegatorLeftCandidate { + delegator: 6, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 40, + }, + Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 26 }, + Event::Rewarded { account: 6, rewards: 8 }, + Event::Rewarded { account: 7, rewards: 8 }, + Event::Rewarded { account: 10, rewards: 8 }, + ); + // 6 won't be paid for this round because they left already + set_author(7, 1, 100); + roll_to_round_begin(7); + // keep paying 6 + assert_events_eq!( + Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 31 }, + Event::Rewarded { account: 7, rewards: 10 }, + Event::Rewarded { account: 10, rewards: 10 }, + ); + roll_to_round_begin(8); + assert_events_eq!( + Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 33 }, + Event::Rewarded { account: 7, rewards: 11 }, + Event::Rewarded { account: 10, rewards: 11 }, + ); + set_author(8, 1, 100); + roll_to_round_begin(9); + // no more paying 6 + assert_events_eq!( + Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 34 }, + Event::Rewarded { account: 7, rewards: 11 }, + Event::Rewarded { account: 10, rewards: 11 }, + ); + roll_blocks(1); + set_author(9, 1, 100); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); + assert_events_eq!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + + roll_to_round_begin(10); + // new delegation is not rewarded yet + assert_events_eq!( + Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 36 }, + Event::Rewarded { account: 7, rewards: 12 }, + Event::Rewarded { account: 10, rewards: 12 }, + ); + set_author(10, 1, 100); + roll_to_round_begin(11); + // new delegation not rewarded yet + assert_events_eq!( + Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 38 }, + Event::Rewarded { account: 7, rewards: 12 }, + Event::Rewarded { account: 10, rewards: 12 }, + ); + roll_to_round_begin(12); + // new delegation is rewarded for first time + // 2 rounds after joining (`RewardPaymentDelay` = 2) + assert_events_eq!( + Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 34 }, + Event::Rewarded { account: 7, rewards: 11 }, + Event::Rewarded { account: 10, rewards: 11 }, + Event::Rewarded { account: 8, rewards: 11 }, + ); + }); } #[test] fn bottom_delegations_are_empty_when_top_delegations_not_full() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 10), (4, 10), (5, 10)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // no top delegators => no bottom delegators - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert!(top_delegations.delegations.is_empty()); - assert!(bottom_delegations.delegations.is_empty()); - // 1 delegator => 1 top delegator, 0 bottom delegators - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 10, - 10, - 10 - )); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 1usize); - assert!(bottom_delegations.delegations.is_empty()); - // 2 delegators => 2 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(3), - 1, - 10, - 10, - 10 - )); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 2usize); - assert!(bottom_delegations.delegations.is_empty()); - // 3 delegators => 3 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(4), - 1, - 10, - 10, - 10 - )); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 3usize); - assert!(bottom_delegations.delegations.is_empty()); - // 4 delegators => 4 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(5), - 1, - 10, - 10, - 10 - )); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 4usize); - assert!(bottom_delegations.delegations.is_empty()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 10), (4, 10), (5, 10)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // no top delegators => no bottom delegators + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert!(top_delegations.delegations.is_empty()); + assert!(bottom_delegations.delegations.is_empty()); + // 1 delegator => 1 top delegator, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 1usize); + assert!(bottom_delegations.delegations.is_empty()); + // 2 delegators => 2 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(3), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 2usize); + assert!(bottom_delegations.delegations.is_empty()); + // 3 delegators => 3 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(4), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 3usize); + assert!(bottom_delegations.delegations.is_empty()); + // 4 delegators => 4 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 4usize); + assert!(bottom_delegations.delegations.is_empty()); + }); } #[test] fn candidate_pool_updates_when_total_counted_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (3, 1, 11), - (4, 1, 12), - (5, 1, 13), - (6, 1, 14), - (7, 1, 15), - (8, 1, 16), - (9, 1, 17), - (10, 1, 18), - ]) - .build() - .execute_with(|| { - fn is_candidate_pool_bond(account: u64, bond: u128) { - let pool = ParachainStaking::candidate_pool(); - for candidate in pool.0 { - if candidate.owner == account { - assert_eq!( - candidate.amount, bond, - "Candidate Bond {:?} is Not Equal to Expected: {:?}", - candidate.amount, bond - ); - } - } - } - // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) - is_candidate_pool_bond(1, 86); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(3), - 1, - 8 - )); - // 3: 11 -> 19 => 3 is in top, bumps out 7 - // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) - is_candidate_pool_bond(1, 90); - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(4), - 1, - 8 - )); - // 4: 12 -> 20 => 4 is in top, bumps out 8 - // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) - is_candidate_pool_bond(1, 94); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(10), - 1, - 3 - )); - roll_to(30); - // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(10), - 10, - 1 - )); - // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) - is_candidate_pool_bond(1, 92); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(9), - 1, - 4 - )); - roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(9), - 9, - 1 - )); - // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) - is_candidate_pool_bond(1, 90); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (3, 1, 11), + (4, 1, 12), + (5, 1, 13), + (6, 1, 14), + (7, 1, 15), + (8, 1, 16), + (9, 1, 17), + (10, 1, 18), + ]) + .build() + .execute_with(|| { + fn is_candidate_pool_bond(account: u64, bond: u128) { + let pool = ParachainStaking::candidate_pool(); + for candidate in pool.0 { + if candidate.owner == account { + assert_eq!( + candidate.amount, bond, + "Candidate Bond {:?} is Not Equal to Expected: {:?}", + candidate.amount, bond + ); + } + } + } + // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) + is_candidate_pool_bond(1, 86); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); + // 3: 11 -> 19 => 3 is in top, bumps out 7 + // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) + is_candidate_pool_bond(1, 90); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); + // 4: 12 -> 20 => 4 is in top, bumps out 8 + // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) + is_candidate_pool_bond(1, 94); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(10), + 1, + 3 + )); + roll_to(30); + // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(10), + 10, + 1 + )); + // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) + is_candidate_pool_bond(1, 92); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(9), + 1, + 4 + )); + roll_to(40); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(9), + 9, + 1 + )); + // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) + is_candidate_pool_bond(1, 90); + }); } #[test] fn only_top_collators_are_counted() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (3, 1, 11), - (4, 1, 12), - (5, 1, 13), - (6, 1, 14), - (7, 1, 15), - (8, 1, 16), - (9, 1, 17), - (10, 1, 18), - ]) - .build() - .execute_with(|| { - // sanity check that 3-10 are delegators immediately - for i in 3..11 { - assert!(ParachainStaking::is_delegator(&i)); - } - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 86); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(3), - 1, - 8 - )); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 90); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(4), - 1, - 8 - )); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 4, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 94); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(5), - 1, - 8 - )); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 5, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 98); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(6), - 1, - 8 - )); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 6, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 102); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (3, 1, 11), + (4, 1, 12), + (5, 1, 13), + (6, 1, 14), + (7, 1, 15), + (8, 1, 16), + (9, 1, 17), + (10, 1, 18), + ]) + .build() + .execute_with(|| { + // sanity check that 3-10 are delegators immediately + for i in 3..11 { + assert!(ParachainStaking::is_delegator(&i)); + } + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 86); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 90); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 4, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 94); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(5), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 5, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 98); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 6, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 102); + }); } #[test] fn delegation_events_convey_correct_position() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 11), (4, 1, 12), (5, 1, 13), (6, 1, 14)]) - .build() - .execute_with(|| { - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 11 + 12 + 13 + 14 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 70); - // Top delegations are full, new highest delegation is made - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(7), - 1, - 15, - 10, - 10 - )); - assert_events_emitted!(Event::Delegation { - delegator: 7, - locked_amount: 15, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 74 }, - auto_compound: Percent::zero(), - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 74); - // New delegation is added to the bottom - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(8), - 1, - 10, - 10, - 10 - )); - assert_events_emitted!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToBottom, - auto_compound: Percent::zero(), - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 74); - // 8 increases delegation to the top - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(8), - 1, - 3 - )); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 8, - candidate: 1, - amount: 3, - in_top: true, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 75); - // 3 increases delegation but stays in bottom - assert_ok!(ParachainStaking::delegator_bond_more( - RuntimeOrigin::signed(3), - 1, - 1 - )); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 1, - in_top: false, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 75); - // 6 decreases delegation but stays in top - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 2 - )); - assert_events_emitted!(Event::DelegationDecreaseScheduled { - delegator: 6, - candidate: 1, - amount_to_decrease: 2, - execute_round: 3, - }); - roll_to(30); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 2, - in_top: true, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ - assert_eq!(collator1_state.total_counted, 73); - // 6 decreases delegation and is bumped to bottom - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 1 - )); - assert_events_emitted!(Event::DelegationDecreaseScheduled { - delegator: 6, - candidate: 1, - amount_to_decrease: 1, - execute_round: 9, - }); - roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 1, - in_top: false, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 73); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 11), (4, 1, 12), (5, 1, 13), (6, 1, 14)]) + .build() + .execute_with(|| { + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 11 + 12 + 13 + 14 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 70); + // Top delegations are full, new highest delegation is made + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 1, 15, 10, 10)); + assert_events_emitted!(Event::Delegation { + delegator: 7, + locked_amount: 15, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 74 }, + auto_compound: Percent::zero(), + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 74); + // New delegation is added to the bottom + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); + assert_events_emitted!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToBottom, + auto_compound: Percent::zero(), + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 74); + // 8 increases delegation to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(8), 1, 3)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 8, + candidate: 1, + amount: 3, + in_top: true, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 75); + // 3 increases delegation but stays in bottom + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 1)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 1, + in_top: false, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 75); + // 6 decreases delegation but stays in top + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 2 + )); + assert_events_emitted!(Event::DelegationDecreaseScheduled { + delegator: 6, + candidate: 1, + amount_to_decrease: 2, + execute_round: 3, + }); + roll_to(30); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 2, + in_top: true, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ + assert_eq!(collator1_state.total_counted, 73); + // 6 decreases delegation and is bumped to bottom + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 1 + )); + assert_events_emitted!(Event::DelegationDecreaseScheduled { + delegator: 6, + candidate: 1, + amount_to_decrease: 1, + execute_round: 9, + }); + roll_to(40); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 1, + in_top: false, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 73); + }); } #[test] fn no_rewards_paid_until_after_reward_payment_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // payouts for round 1 - set_author(1, 1, 1); - set_author(1, 2, 1); - set_author(1, 2, 1); - set_author(1, 3, 1); - set_author(1, 3, 1); - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 3, - total_balance: 60, - }, - ); - - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { - round: 3, - collator_account: 1, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 3, - collator_account: 2, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 3, - collator_account: 3, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 3, - total_balance: 60, - }, - ); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 3, - rewards: 1, - }); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 1, - }); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 2, - rewards: 1, - }); - - // there should be no more payments in this round... - let num_blocks_rolled = roll_to_round_end(3); - assert_no_events!(); - assert_eq!(num_blocks_rolled, 1); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // payouts for round 1 + set_author(1, 1, 1); + set_author(1, 2, 1); + set_author(1, 2, 1); + set_author(1, 3, 1); + set_author(1, 3, 1); + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 3, + total_balance: 60, + }, + ); + + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 3, collator_account: 3, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 3, + total_balance: 60, + }, + ); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 3, rewards: 1 }); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 }); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 }); + + // there should be no more payments in this round... + let num_blocks_rolled = roll_to_round_end(3); + assert_no_events!(); + assert_eq!(num_blocks_rolled, 1); + }); } #[test] fn deferred_payment_storage_items_are_cleaned_up() { - use crate::*; - - // this test sets up two collators, gives them points in round one, and focuses on the - // storage over the next several blocks to show that it is properly cleaned up - - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - set_author(1, 1, 1); - set_author(1, 2, 1); - - // reflects genesis? - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - roll_to_round_begin(2); - assert_events_eq!( - Event::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 2, - collator_account: 2, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - // we should have AtStake snapshots as soon as we start a round... - assert!(>::contains_key(2, 1)); - assert!(>::contains_key(2, 2)); - // ...and it should persist until the round is fully paid out - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - assert!( - !>::contains_key(1), - "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" - ); - assert!( - >::contains_key(1), - "Points should be populated during current round" - ); - assert!( - >::contains_key(1), - "Staked should be populated when round changes" - ); - - assert!( - !>::contains_key(2), - "Points should not be populated until author noted" - ); - assert!( - >::contains_key(2), - "Staked should be populated when round changes" - ); - - // first payout occurs in round 3 - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { - round: 3, - collator_account: 1, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 3, - collator_account: 2, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 1, - },); - - // payouts should exist for past rounds that haven't been paid out yet.. - assert!(>::contains_key(3, 1)); - assert!(>::contains_key(3, 2)); - assert!(>::contains_key(2, 1)); - assert!(>::contains_key(2, 2)); - - assert!( - >::contains_key(1), - "DelayedPayouts should be populated after RewardPaymentDelay" - ); - assert!(>::contains_key(1)); - assert!( - !>::contains_key(1), - "Staked should be cleaned up after round change" - ); - - assert!(!>::contains_key(2)); - assert!( - !>::contains_key(2), - "We never rewarded points for round 2" - ); - assert!(>::contains_key(2)); - - assert!(!>::contains_key(3)); - assert!( - !>::contains_key(3), - "We never awarded points for round 3" - ); - assert!(>::contains_key(3)); - - // collator 1 has been paid in this last block and associated storage cleaned up - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 1)); - - // but collator 2 hasn't been paid - assert!(>::contains_key(1, 2)); - assert!(>::contains_key(1, 2)); - - // second payout occurs in next block - roll_blocks(1); - assert_events_eq!(Event::Rewarded { - account: 2, - rewards: 1, - },); - - roll_to_round_begin(4); - assert_events_eq!( - Event::CollatorChosen { - round: 4, - collator_account: 1, - total_exposed_amount: 20, - }, - Event::CollatorChosen { - round: 4, - collator_account: 2, - total_exposed_amount: 20, - }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - // collators have both been paid and storage fully cleaned up for round 1 - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); // points should be cleaned up - assert!(!>::contains_key(1)); - - roll_to_round_end(4); - - // no more events expected - assert_no_events!(); - }); + use crate::*; + + // this test sets up two collators, gives them points in round one, and focuses on the + // storage over the next several blocks to show that it is properly cleaned up + + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + set_author(1, 1, 1); + set_author(1, 2, 1); + + // reflects genesis? + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + roll_to_round_begin(2); + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + // we should have AtStake snapshots as soon as we start a round... + assert!(>::contains_key(2, 1)); + assert!(>::contains_key(2, 2)); + // ...and it should persist until the round is fully paid out + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + assert!( + !>::contains_key(1), + "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" + ); + assert!( + >::contains_key(1), + "Points should be populated during current round" + ); + assert!( + >::contains_key(1), + "Staked should be populated when round changes" + ); + + assert!( + !>::contains_key(2), + "Points should not be populated until author noted" + ); + assert!( + >::contains_key(2), + "Staked should be populated when round changes" + ); + + // first payout occurs in round 3 + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 },); + + // payouts should exist for past rounds that haven't been paid out yet.. + assert!(>::contains_key(3, 1)); + assert!(>::contains_key(3, 2)); + assert!(>::contains_key(2, 1)); + assert!(>::contains_key(2, 2)); + + assert!( + >::contains_key(1), + "DelayedPayouts should be populated after RewardPaymentDelay" + ); + assert!(>::contains_key(1)); + assert!( + !>::contains_key(1), + "Staked should be cleaned up after round change" + ); + + assert!(!>::contains_key(2)); + assert!(!>::contains_key(2), "We never rewarded points for round 2"); + assert!(>::contains_key(2)); + + assert!(!>::contains_key(3)); + assert!(!>::contains_key(3), "We never awarded points for round 3"); + assert!(>::contains_key(3)); + + // collator 1 has been paid in this last block and associated storage cleaned up + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 1)); + + // but collator 2 hasn't been paid + assert!(>::contains_key(1, 2)); + assert!(>::contains_key(1, 2)); + + // second payout occurs in next block + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 },); + + roll_to_round_begin(4); + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + // collators have both been paid and storage fully cleaned up for round 1 + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); // points should be cleaned up + assert!(!>::contains_key(1)); + + roll_to_round_end(4); + + // no more events expected + assert_no_events!(); + }); } #[test] fn deferred_payment_and_at_stake_storage_items_cleaned_up_for_candidates_not_producing_blocks() { - use crate::*; - - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) - .build() - .execute_with(|| { - // candidate 3 will not produce blocks - set_author(1, 1, 1); - set_author(1, 2, 1); - - // reflects genesis? - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - roll_to_round_begin(2); - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - assert!(>::contains_key(1, 3)); - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(>::contains_key(1)); - assert!(>::contains_key(1)); - roll_to_round_begin(3); - assert!(>::contains_key(1)); - - // all storage items must be cleaned up - roll_to_round_begin(4); - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); - }); + use crate::*; + + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) + .build() + .execute_with(|| { + // candidate 3 will not produce blocks + set_author(1, 1, 1); + set_author(1, 2, 1); + + // reflects genesis? + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + roll_to_round_begin(2); + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + assert!(>::contains_key(1, 3)); + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(>::contains_key(1)); + assert!(>::contains_key(1)); + roll_to_round_begin(3); + assert!(>::contains_key(1)); + + // all storage items must be cleaned up + roll_to_round_begin(4); + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); + }); } #[test] fn deferred_payment_steady_state_event_flow() { - use frame_support::traits::{Currency, ExistenceRequirement, WithdrawReasons}; - - // this test "flows" through a number of rounds, asserting that certain things do/don't happen - // once the staking pallet is in a "steady state" (specifically, once we are past the first few - // rounds to clear RewardPaymentDelay) - - ExtBuilder::default() - .with_balances(vec![ - // collators - (1, 200), - (2, 200), - (3, 200), - (4, 200), - // delegators - (11, 200), - (22, 200), - (33, 200), - (44, 200), - // burn account, see `reset_issuance()` - (111, 1000), - ]) - .with_candidates(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) - .with_delegations(vec![ - // delegator 11 delegates 100 to 1 and 2 - (11, 1, 100), - (11, 2, 100), - // delegator 22 delegates 100 to 2 and 3 - (22, 2, 100), - (22, 3, 100), - // delegator 33 delegates 100 to 3 and 4 - (33, 3, 100), - (33, 4, 100), - // delegator 44 delegates 100 to 4 and 1 - (44, 4, 100), - (44, 1, 100), - ]) - .build() - .execute_with(|| { - // convenience to set the round points consistently - let set_round_points = |round: BlockNumber| { - set_author(round as BlockNumber, 1, 1); - set_author(round as BlockNumber, 2, 1); - set_author(round as BlockNumber, 3, 1); - set_author(round as BlockNumber, 4, 1); - }; - - // grab initial issuance -- we will reset it before round issuance is calculated so that - // it is consistent every round - let initial_issuance = Balances::total_issuance(); - let reset_issuance = || { - let new_issuance = Balances::total_issuance(); - let diff = new_issuance - initial_issuance; - let burned = Balances::burn(diff); - Balances::settle( - &111, - burned, - WithdrawReasons::FEE, - ExistenceRequirement::AllowDeath, - ) - .expect("Account can absorb burn"); - }; - - // fn to roll through the first RewardPaymentDelay rounds. returns new round index - let roll_through_initial_rounds = |mut round: BlockNumber| -> BlockNumber { - while round < crate::mock::RewardPaymentDelay::get() + 1 { - set_round_points(round); - - roll_to_round_end(round); - round += 1; - } - - reset_issuance(); - - round - }; - - // roll through a "steady state" round and make all of our assertions - // returns new round index - let roll_through_steady_state_round = |round: BlockNumber| -> BlockNumber { - let num_rounds_rolled = roll_to_round_begin(round); - assert!( - num_rounds_rolled <= 1, - "expected to be at round begin already" - ); - - assert_events_eq!( - Event::CollatorChosen { - round: round as u32, - collator_account: 1, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 2, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 3, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 4, - total_exposed_amount: 400, - }, - Event::NewRound { - starting_block: (round - 1) * 5, - round: round as u32, - selected_collators_number: 4, - total_balance: 1600, - }, - ); - - set_round_points(round); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 3, - rewards: 19, - }, - Event::Rewarded { - account: 22, - rewards: 6, - }, - Event::Rewarded { - account: 33, - rewards: 6, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 4, - rewards: 19, - }, - Event::Rewarded { - account: 33, - rewards: 6, - }, - Event::Rewarded { - account: 44, - rewards: 6, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 19, - }, - Event::Rewarded { - account: 11, - rewards: 6, - }, - Event::Rewarded { - account: 44, - rewards: 6, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 2, - rewards: 19, - }, - Event::Rewarded { - account: 11, - rewards: 6, - }, - Event::Rewarded { - account: 22, - rewards: 6, - }, - ); - - roll_blocks(1); - // Since we defer first deferred staking payout, this test have the maximum amout of - // supported collators. This eman that the next round is trigerred one block after - // the last reward. - //assert_no_events!(); - - let num_rounds_rolled = roll_to_round_end(round); - assert_eq!(num_rounds_rolled, 0, "expected to be at round end already"); - - reset_issuance(); - - round + 1 - }; - - let mut round = 1; - round = roll_through_initial_rounds(round); // we should be at RewardPaymentDelay - for _ in 1..2 { - round = roll_through_steady_state_round(round); - } - }); + use frame_support::traits::{Currency, ExistenceRequirement, WithdrawReasons}; + + // this test "flows" through a number of rounds, asserting that certain things do/don't happen + // once the staking pallet is in a "steady state" (specifically, once we are past the first few + // rounds to clear RewardPaymentDelay) + + ExtBuilder::default() + .with_balances(vec![ + // collators + (1, 200), + (2, 200), + (3, 200), + (4, 200), + // delegators + (11, 200), + (22, 200), + (33, 200), + (44, 200), + // burn account, see `reset_issuance()` + (111, 1000), + ]) + .with_candidates(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) + .with_delegations(vec![ + // delegator 11 delegates 100 to 1 and 2 + (11, 1, 100), + (11, 2, 100), + // delegator 22 delegates 100 to 2 and 3 + (22, 2, 100), + (22, 3, 100), + // delegator 33 delegates 100 to 3 and 4 + (33, 3, 100), + (33, 4, 100), + // delegator 44 delegates 100 to 4 and 1 + (44, 4, 100), + (44, 1, 100), + ]) + .build() + .execute_with(|| { + // convenience to set the round points consistently + let set_round_points = |round: BlockNumber| { + set_author(round as BlockNumber, 1, 1); + set_author(round as BlockNumber, 2, 1); + set_author(round as BlockNumber, 3, 1); + set_author(round as BlockNumber, 4, 1); + }; + + // grab initial issuance -- we will reset it before round issuance is calculated so that + // it is consistent every round + let initial_issuance = Balances::total_issuance(); + let reset_issuance = || { + let new_issuance = Balances::total_issuance(); + let diff = new_issuance - initial_issuance; + let burned = Balances::burn(diff); + Balances::settle( + &111, + burned, + WithdrawReasons::FEE, + ExistenceRequirement::AllowDeath, + ) + .expect("Account can absorb burn"); + }; + + // fn to roll through the first RewardPaymentDelay rounds. returns new round index + let roll_through_initial_rounds = |mut round: BlockNumber| -> BlockNumber { + while round < crate::mock::RewardPaymentDelay::get() + 1 { + set_round_points(round); + + roll_to_round_end(round); + round += 1; + } + + reset_issuance(); + + round + }; + + // roll through a "steady state" round and make all of our assertions + // returns new round index + let roll_through_steady_state_round = |round: BlockNumber| -> BlockNumber { + let num_rounds_rolled = roll_to_round_begin(round); + assert!(num_rounds_rolled <= 1, "expected to be at round begin already"); + + assert_events_eq!( + Event::CollatorChosen { + round: round as u32, + collator_account: 1, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 2, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 3, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 4, + total_exposed_amount: 400, + }, + Event::NewRound { + starting_block: (round - 1) * 5, + round: round as u32, + selected_collators_number: 4, + total_balance: 1600, + }, + ); + + set_round_points(round); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 3, rewards: 19 }, + Event::Rewarded { account: 22, rewards: 6 }, + Event::Rewarded { account: 33, rewards: 6 }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 4, rewards: 19 }, + Event::Rewarded { account: 33, rewards: 6 }, + Event::Rewarded { account: 44, rewards: 6 }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 19 }, + Event::Rewarded { account: 11, rewards: 6 }, + Event::Rewarded { account: 44, rewards: 6 }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 2, rewards: 19 }, + Event::Rewarded { account: 11, rewards: 6 }, + Event::Rewarded { account: 22, rewards: 6 }, + ); + + roll_blocks(1); + // Since we defer first deferred staking payout, this test have the maximum amout of + // supported collators. This eman that the next round is trigerred one block after + // the last reward. + //assert_no_events!(); + + let num_rounds_rolled = roll_to_round_end(round); + assert_eq!(num_rounds_rolled, 0, "expected to be at round end already"); + + reset_issuance(); + + round + 1 + }; + + let mut round = 1; + round = roll_through_initial_rounds(round); // we should be at RewardPaymentDelay + for _ in 1..2 { + round = roll_through_steady_state_round(round); + } + }); } #[test] fn delegation_kicked_from_bottom_removes_pending_request() { - ExtBuilder::default() - .with_balances(vec![ - (1, 30), - (2, 29), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 30), - ]) - .with_candidates(vec![(1, 30), (11, 30)]) - .with_delegations(vec![ - (2, 1, 19), - (2, 11, 10), // second delegation so not left after first is kicked - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - (7, 1, 20), - (8, 1, 20), - (9, 1, 20), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - // 10 delegates to full 1 => kicks lowest delegation (2, 19) - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(10), - 1, - 20, - 8, - 0 - )); - // check the event - assert_events_emitted!(Event::DelegationKicked { - delegator: 2, - candidate: 1, - unstaked_amount: 19, - }); - // ensure request DNE - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 30), + (2, 29), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 30), + ]) + .with_candidates(vec![(1, 30), (11, 30)]) + .with_delegations(vec![ + (2, 1, 19), + (2, 11, 10), // second delegation so not left after first is kicked + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + (7, 1, 20), + (8, 1, 20), + (9, 1, 20), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + // 10 delegates to full 1 => kicks lowest delegation (2, 19) + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); + // check the event + assert_events_emitted!(Event::DelegationKicked { + delegator: 2, + candidate: 1, + unstaked_amount: 19, + }); + // ensure request DNE + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2) + ); + }); } #[test] fn no_selected_candidates_defaults_to_last_round_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) - .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) - .build() - .execute_with(|| { - roll_to_round_begin(1); - // schedule to leave - for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - 5 - )); - } - let old_round = ParachainStaking::round().current; - let old_selected_candidates = ParachainStaking::selected_candidates(); - let mut old_at_stake_snapshots = Vec::new(); - for account in old_selected_candidates.clone() { - old_at_stake_snapshots.push(>::get(old_round, account)); - } - roll_to_round_begin(3); - // execute leave - for i in 1..6 { - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(i), - i, - 0, - )); - } - // next round - roll_to_round_begin(4); - let new_round = ParachainStaking::round().current; - // check AtStake matches previous - let new_selected_candidates = ParachainStaking::selected_candidates(); - assert_eq!(old_selected_candidates, new_selected_candidates); - let mut index = 0usize; - for account in new_selected_candidates { - assert_eq!( - old_at_stake_snapshots[index], - >::get(new_round, account) - ); - index += 1usize; - } - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) + .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) + .build() + .execute_with(|| { + roll_to_round_begin(1); + // schedule to leave + for i in 1..6 { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + 5 + )); + } + let old_round = ParachainStaking::round().current; + let old_selected_candidates = ParachainStaking::selected_candidates(); + let mut old_at_stake_snapshots = Vec::new(); + for account in old_selected_candidates.clone() { + old_at_stake_snapshots.push(>::get(old_round, account)); + } + roll_to_round_begin(3); + // execute leave + for i in 1..6 { + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(i), + i, + 0, + )); + } + // next round + roll_to_round_begin(4); + let new_round = ParachainStaking::round().current; + // check AtStake matches previous + let new_selected_candidates = ParachainStaking::selected_candidates(); + assert_eq!(old_selected_candidates, new_selected_candidates); + // let mut index = 0usize; + for (index, account) in new_selected_candidates.into_iter().enumerate() { + assert_eq!(old_at_stake_snapshots[index], >::get(new_round, account)); + // index += 1usize; + } + }); } #[test] fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator.total_counted, - "collator's total was reduced unexpectedly" - ); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 4, - }, - Event::Rewarded { - account: 2, - rewards: 1, - }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 5, - },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); } #[test] fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator.total_counted, - "collator's total was reduced unexpectedly" - ); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 5, - },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 4, - }, - Event::Rewarded { - account: 2, - rewards: 1, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + }); } #[test] fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - execute_round: 3, - delegator: 2, - candidate: 1, - amount_to_decrease: 10, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!( - 40, collator.total_counted, - "collator's total was reduced unexpectedly" - ); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 3, - }, - Event::Rewarded { - account: 2, - rewards: 2, - }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 4, - }, - Event::Rewarded { - account: 2, - rewards: 1, - }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + execute_round: 3, + delegator: 2, + candidate: 1, + amount_to_decrease: 10, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 3 }, + Event::Rewarded { account: 2, rewards: 2 }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); } #[test] fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - execute_round: 3, - delegator: 2, - candidate: 1, - amount_to_decrease: 10, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!( - 40, collator.total_counted, - "collator's total was reduced unexpectedly" - ); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_delegation_request( - RuntimeOrigin::signed(2), - 1 - )); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 4, - }, - Event::Rewarded { - account: 2, - rewards: 1, - }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 40, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 3, - }, - Event::Rewarded { - account: 2, - rewards: 2, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + execute_round: 3, + delegator: 2, + candidate: 1, + amount_to_decrease: 10, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 40, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 3 }, + Event::Rewarded { account: 2, rewards: 2 }, + ); + }); } #[test] fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2), - )); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator.total_counted, - "collator's total was reduced unexpectedly" - ); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 4, - }, - Event::Rewarded { - account: 2, - rewards: 1, - }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 5, - },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2),)); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); } #[test] fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator.total_counted, - "collator's total was reduced unexpectedly" - ); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_leave_delegators( - RuntimeOrigin::signed(2) - )); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { - account: 1, - rewards: 5, - },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 4, - }, - Event::Rewarded { - account: 2, - rewards: 1, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + }); } #[test] fn test_delegation_request_exists_returns_false_when_nothing_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_request_exists(&1, &2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_request_exists(&1, &2)); + }); } #[test] fn test_delegation_request_exists_returns_true_when_decrease_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert!(ParachainStaking::delegation_request_exists(&1, &2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert!(ParachainStaking::delegation_request_exists(&1, &2)); + }); } #[test] fn test_delegation_request_exists_returns_true_when_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], - ); - assert!(ParachainStaking::delegation_request_exists(&1, &2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], + ); + assert!(ParachainStaking::delegation_request_exists(&1, &2)); + }); } #[test] fn test_delegation_request_revoke_exists_returns_false_when_nothing_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); } #[test] fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); } #[test] fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], - ); - assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], + ); + assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3, 4] // 4 does not exist, but is OK for idempotency - ) - ); - - assert!(!>::contains_key(2)); - assert!(!>::contains_key(3)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3, 4] // 4 does not exist, but is OK for idempotency + )); + + assert!(!>::contains_key(2)); + assert!(!>::contains_key(3)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2] - ) - ); - - assert!(!>::contains_key(2)); - assert!(>::contains_key(3)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2] + )); + + assert!(!>::contains_key(2)); + assert!(>::contains_key(3)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - vec![ScheduledRequest { - delegator: 10, - when_executable: 1, - action: DelegationAction::Revoke(10), - }], - ); - - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3] - ), - >::CandidateNotLeaving, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + vec![ScheduledRequest { + delegator: 10, + when_executable: 1, + action: DelegationAction::Revoke(10), + }], + ); + + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3] + ), + >::CandidateNotLeaving, + ); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 1, - Vec::>::new(), - ); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![1] - ), - >::CandidateNotLeaving, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 1, + Vec::>::new(), + ); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![1] + ), + >::CandidateNotLeaving, + ); + }); } #[test] fn locking_zero_amount_is_ignored() { - use frame_support::traits::{LockableCurrency, WithdrawReasons}; + use frame_support::traits::{LockableCurrency, WithdrawReasons}; - // this test demonstrates the behavior of pallet Balance's `LockableCurrency` implementation of - // `set_locks()` when an amount of 0 is provided: it is a no-op + // this test demonstrates the behavior of pallet Balance's `LockableCurrency` implementation of + // `set_locks()` when an amount of 0 is provided: it is a no-op - ExtBuilder::default() - .with_balances(vec![(1, 100)]) - .build() - .execute_with(|| { - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), None); + ExtBuilder::default().with_balances(vec![(1, 100)]).build().execute_with(|| { + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), None); - Balances::set_lock(DELEGATOR_LOCK_ID, &1, 1, WithdrawReasons::all()); - assert_eq!( - crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), - Some(1) - ); + Balances::set_lock(DELEGATOR_LOCK_ID, &1, 1, WithdrawReasons::all()); + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); - Balances::set_lock(DELEGATOR_LOCK_ID, &1, 0, WithdrawReasons::all()); - // Note that we tried to call `set_lock(0)` and it ignored it, we still have our lock - assert_eq!( - crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), - Some(1) - ); - }); + Balances::set_lock(DELEGATOR_LOCK_ID, &1, 0, WithdrawReasons::all()); + // Note that we tried to call `set_lock(0)` and it ignored it, we still have our lock + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); + }); } #[test] fn revoke_last_removes_lock() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100)]) - .with_candidates(vec![(1, 25), (2, 25)]) - .with_delegations(vec![(3, 1, 30), (3, 2, 25)]) - .build() - .execute_with(|| { - assert_eq!( - crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), - Some(55) - ); - - // schedule and remove one... - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(3), - 1 - )); - roll_to_round_begin(3); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 1 - )); - assert_eq!( - crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), - Some(25) - ); - - // schedule and remove the other... - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(3), - 2 - )); - roll_to_round_begin(5); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 2 - )); - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); - }); + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100)]) + .with_candidates(vec![(1, 25), (2, 25)]) + .with_delegations(vec![(3, 1, 30), (3, 2, 25)]) + .build() + .execute_with(|| { + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(55)); + + // schedule and remove one... + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 1)); + roll_to_round_begin(3); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 1 + )); + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(25)); + + // schedule and remove the other... + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); + roll_to_round_begin(5); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 2 + )); + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); + }); } #[allow(deprecated)] #[test] fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert!(>::get(1) - .iter() - .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_)))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); - - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert!( + >::get(1) + .iter() + .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_))) + ); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); + + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); + }); } #[allow(deprecated)] #[test] fn test_delegator_with_deprecated_status_leaving_can_cancel_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_ok!(ParachainStaking::cancel_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_events_eq!(Event::DelegatorExitCancelled { delegator: 2 }); - - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_eq!(Event::DelegatorExitCancelled { delegator: 2 }); + + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); + }); } #[allow(deprecated)] #[test] fn test_delegator_with_deprecated_status_leaving_can_execute_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeft { - delegator: 2, - unstaked_amount: 10 - }); - - let state = >::get(2); - assert!(state.is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + + let state = >::get(2); + assert!(state.is_none()); + }); } #[allow(deprecated)] #[test] fn test_delegator_with_deprecated_status_leaving_cannot_execute_leave_delegators_early_no_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorCannotLeaveYet - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorCannotLeaveYet + ); + }); } #[test] fn test_set_auto_compound_fails_if_invalid_delegation_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; // is however, 1 - - assert_noop!( - ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowDelegationCountToAutoCompound, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; // is however, 1 + + assert_noop!( + ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowDelegationCountToAutoCompound, + ); + }); } #[test] fn test_set_auto_compound_fails_if_invalid_candidate_auto_compounding_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new(vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(10), - }]) - .set_storage(&1); - let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 - let delegation_hint = 1; - - assert_noop!( - ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new(vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(10), + }]) + .set_storage(&1); + let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 + let delegation_hint = 1; + + assert_noop!( + ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + ); + }); } #[test] fn test_set_auto_compound_inserts_if_not_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(50), - }], - ParachainStaking::auto_compounding_delegations(&1), - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], + ParachainStaking::auto_compounding_delegations(&1), + ); + }); } #[test] fn test_set_auto_compound_updates_if_existing() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new(vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(10), - }]) - .set_storage(&1); - - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(50), - }], - ParachainStaking::auto_compounding_delegations(&1), - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new(vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(10), + }]) + .set_storage(&1); + + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], + ParachainStaking::auto_compounding_delegations(&1), + ); + }); } #[test] fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new(vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(10), - }]) - .set_storage(&1); - - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::zero(), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::zero(), - }); - assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new(vec![AutoCompoundConfig { + delegator: 2, + value: Percent::from_percent(10), + }]) + .set_storage(&1); + + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::zero(), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::zero(), + }); + assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); + }); } #[test] fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delegation_revoke() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was erroneously removed" - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), + "delegation auto-compound config was erroneously removed" + ); + }); } #[test] fn test_execute_leave_delegators_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 2, - )); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); } #[allow(deprecated)] #[test] fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(2), - 2, - 2, - )); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); } #[test] fn test_execute_leave_candidates_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(1), - 2 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(1), - 1, - 1, - )); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was erroneously removed" - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 2)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1,)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), + "delegation auto-compound config was erroneously removed" + ); + }); } #[test] fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![ - (1, 30), - (2, 29), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 30), - ]) - .with_candidates(vec![(1, 30), (11, 30)]) - .with_delegations(vec![ - (2, 11, 10), // extra delegation to avoid leaving the delegator set - (2, 1, 19), - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - (7, 1, 20), - (8, 1, 20), - (9, 1, 20), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - - // kicks lowest delegation (2, 19) - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(10), - 1, - 20, - 8, - 0 - )); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 30), + (2, 29), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 30), + ]) + .with_candidates(vec![(1, 30), (11, 30)]) + .with_delegations(vec![ + (2, 11, 10), // extra delegation to avoid leaving the delegator set + (2, 1, 19), + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + (7, 1, 20), + (8, 1, 20), + (9, 1, 20), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + + // kicks lowest delegation (2, 19) + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); } #[test] fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 200), (3, 200)]) - .with_candidates(vec![(1, 100)]) - .with_delegations(vec![(2, 1, 200), (3, 1, 200)]) - .build() - .execute_with(|| { - (2..=5).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(3), - 1, - Percent::from_percent(50), - 1, - 1, - )); - roll_to_round_begin(3); - - // schedule revoke for delegator 2; no rewards should be compounded - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - roll_to_round_begin(4); - - assert_events_eq!( - Event::CollatorChosen { - round: 4, - collator_account: 1, - total_exposed_amount: 500, - }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 500, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 9, - }, - // no compound since revoke request exists - Event::Rewarded { - account: 2, - rewards: 8, - }, - // 50% - Event::Rewarded { - account: 3, - rewards: 8, - }, - Event::Compounded { - candidate: 1, - delegator: 3, - amount: 4, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 200), (3, 200)]) + .with_candidates(vec![(1, 100)]) + .with_delegations(vec![(2, 1, 200), (3, 1, 200)]) + .build() + .execute_with(|| { + (2..=5).for_each(|round| set_author(round, 1, 1)); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(3), + 1, + Percent::from_percent(50), + 1, + 1, + )); + roll_to_round_begin(3); + + // schedule revoke for delegator 2; no rewards should be compounded + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to_round_begin(4); + + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 500 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 500, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 9 }, + // no compound since revoke request exists + Event::Rewarded { account: 2, rewards: 8 }, + // 50% + Event::Rewarded { account: 3, rewards: 8 }, + Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, + ); + }); } #[test] fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 200), (3, 200), (4, 200), (5, 200)]) - .with_candidates(vec![(1, 100)]) - .with_delegations(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) - .build() - .execute_with(|| { - (2..=6).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(0), - 0, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(3), - 1, - Percent::from_percent(50), - 1, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(4), - 1, - Percent::from_percent(100), - 2, - 1, - )); - roll_to_round_begin(4); - - assert_events_eq!( - Event::CollatorChosen { - round: 4, - collator_account: 1, - total_exposed_amount: 900, - }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 900, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { - account: 1, - rewards: 13, - }, - // 0% - Event::Rewarded { - account: 2, - rewards: 8, - }, - // 50% - Event::Rewarded { - account: 3, - rewards: 8, - }, - Event::Compounded { - candidate: 1, - delegator: 3, - amount: 4, - }, - // 100% - Event::Rewarded { - account: 4, - rewards: 8, - }, - Event::Compounded { - candidate: 1, - delegator: 4, - amount: 8, - }, - // no-config - Event::Rewarded { - account: 5, - rewards: 8, - }, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 200), (3, 200), (4, 200), (5, 200)]) + .with_candidates(vec![(1, 100)]) + .with_delegations(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) + .build() + .execute_with(|| { + (2..=6).for_each(|round| set_author(round, 1, 1)); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(0), + 0, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(3), + 1, + Percent::from_percent(50), + 1, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(4), + 1, + Percent::from_percent(100), + 2, + 1, + )); + roll_to_round_begin(4); + + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 900 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 900, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 13 }, + // 0% + Event::Rewarded { account: 2, rewards: 8 }, + // 50% + Event::Rewarded { account: 3, rewards: 8 }, + Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, + // 100% + Event::Rewarded { account: 4, rewards: 8 }, + Event::Compounded { candidate: 1, delegator: 4, amount: 8 }, + // no-config + Event::Rewarded { account: 5, rewards: 8 }, + ); + }); } #[test] fn test_delegate_with_auto_compound_fails_if_invalid_delegation_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 3, 10)]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 0; - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; // is however, 1 - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowDelegationCountToDelegate, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 3, 10)]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 0; + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; // is however, 1 + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowDelegationCountToDelegate, + ); + }); } #[test] fn test_delegate_with_auto_compound_fails_if_invalid_candidate_delegation_count_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(3, 1, 10)]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 0; // is however, 1 - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateDelegationCountToDelegate, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(3, 1, 10)]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 0; // is however, 1 + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateDelegationCountToDelegate, + ); + }); } #[test] fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_delegations_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(10))]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 1; - let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 - let delegation_hint = 0; - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(10))]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 1; + let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 + let delegation_hint = 0; + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, + ); + }); } #[test] fn test_delegate_with_auto_compound_sets_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0, - )); - assert_events_emitted!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(50), - }], - ParachainStaking::auto_compounding_delegations(&1), - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0, + )); + assert_events_emitted!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], + ParachainStaking::auto_compounding_delegations(&1), + ); + }); } #[test] fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::zero(), - 0, - 0, - 0, - )); - assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::zero(), + 0, + 0, + 0, + )); + assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }); + }); } #[test] fn test_delegate_with_auto_compound_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::get_delegator_stakable_free_balance(&2), - 10 - ); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0, - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0, + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); } #[test] fn test_delegate_with_auto_compound_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_none()); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - )); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); - assert_eq!(delegator_state.total(), 10); - assert_eq!(delegator_state.delegations.0[0].owner, 1); - assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_none()); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + )); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); + assert_eq!(delegator_state.total(), 10); + assert_eq!(delegator_state.delegations.0[0].owner, 1); + assert_eq!(delegator_state.delegations.0[0].amount, 10); + }); } #[test] fn test_delegate_with_auto_compound_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); - assert!(top_delegations.delegations.is_empty()); - assert!(top_delegations.total.is_zero()); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - )); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); - assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); - assert_eq!(top_delegations.delegations[0].owner, 2); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); + assert!(top_delegations.delegations.is_empty()); + assert!(top_delegations.total.is_zero()); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + )); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); + assert_eq!(candidate_state.total_counted, 40); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); + assert_eq!(top_delegations.delegations[0].owner, 2); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + }); } #[test] fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates( - RuntimeOrigin::signed(1), - 20, - 0 - )); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 20, - Percent::from_percent(50), - 0, - 0, - 0 - )); - }); + ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 20, + Percent::from_percent(50), + 0, + 0, + 0 + )); + }); } #[test] fn test_delegate_with_auto_compound_can_delegate_to_other_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation( - RuntimeOrigin::signed(2), - 1 - )); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 4, - 10, - Percent::from_percent(50), - 0, - 0, - 2 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 4, + 10, + Percent::from_percent(50), + 0, + 0, + 2 + )); + }); } #[test] fn test_delegate_with_auto_compound_cannot_delegate_if_less_than_or_equal_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(11), - 1, - 10, - Percent::from_percent(50), - 8, - 0, - 0 - ), - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(11), + 1, + 10, + Percent::from_percent(50), + 8, + 0, + 0 + ), + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + }); } #[test] fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 11), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(11), - 1, - 11, - Percent::from_percent(50), - 8, - 0, - 0 - )); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); - assert_events_emitted!(Event::DelegatorLeft { - delegator: 10, - unstaked_amount: 10 - }); - }); + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 11), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(11), + 1, + 11, + Percent::from_percent(50), + 8, + 0, + 0 + )); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); + }); } #[test] fn test_delegate_with_auto_compound_can_still_delegate_to_other_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators( - RuntimeOrigin::signed(2) - )); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 3, - 10, - Percent::from_percent(50), - 0, - 0, - 1 - ),); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 3, + 10, + Percent::from_percent(50), + 0, + 0, + 1 + ),); + }); } #[test] fn test_delegate_with_auto_compound_cannot_delegate_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - ), - Error::::CandidateExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + ), + Error::::CandidateExists + ); + }); } #[test] fn test_delegate_with_auto_compound_cannot_delegate_if_already_delegated() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 1, - 1 - ), - Error::::AlreadyDelegatedCandidate - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 1, + 1 + ), + Error::::AlreadyDelegatedCandidate + ); + }); } #[test] fn test_delegate_with_auto_compound_cannot_delegate_more_than_max_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 6, - 10, - Percent::from_percent(50), - 0, - 0, - 4 - ), - Error::::ExceedMaxDelegationsPerDelegator, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 6, + 10, + Percent::from_percent(50), + 0, + 0, + 4 + ), + Error::::ExceedMaxDelegationsPerDelegator, + ); + }); } #[test] fn test_delegate_skips_auto_compound_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(50))]) - .build() - .execute_with(|| { - // We already have an auto-compounding delegation from 3 -> 1, so the hint validation - // would cause a failure if the auto-compounding isn't skipped properly. - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(2), - 1, - 10, - 1, - 0, - )); - assert_eq!(1, ParachainStaking::auto_compounding_delegations(&1).len(),); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(50))]) + .build() + .execute_with(|| { + // We already have an auto-compounding delegation from 3 -> 1, so the hint validation + // would cause a failure if the auto-compounding isn't skipped properly. + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 0,)); + assert_eq!(1, ParachainStaking::auto_compounding_delegations(&1).len(),); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + }); } #[test] fn test_on_initialize_weights() { - use crate::mock::System; - use crate::weights::{SubstrateWeight as PalletWeights, WeightInfo}; - use crate::*; - use frame_support::{pallet_prelude::*, weights::constants::RocksDbWeight}; - - // generate balance, candidate, and delegation vecs to "fill" out delegations - let mut balances = Vec::new(); - let mut candidates = Vec::new(); - let mut delegations = Vec::new(); - - for collator in 1..30 { - balances.push((collator, 100)); - candidates.push((collator, 10)); - let starting_delegator = collator * 1000; - for delegator in starting_delegator..starting_delegator + 300 { - balances.push((delegator, 100)); - delegations.push((delegator, collator, 10)); - } - } - - ExtBuilder::default() - .with_balances(balances) - .with_candidates(candidates) - .with_delegations(delegations) - .build() - .execute_with(|| { - let weight = ParachainStaking::on_initialize(1); - - // TODO: build this with proper db reads/writes - assert_eq!(Weight::from_ref_time(285_890_000), weight); - - // roll to the end of the round, then run on_init again, we should see round change... - roll_to_round_end(3); - set_author(2, 1, 100); // must set some points for prepare_staking_payouts - let block = System::block_number() + 1; - let weight = ParachainStaking::on_initialize(block); - - // the total on_init weight during our round change. this number is taken from running - // the fn with a given weights.rs benchmark, so will need to be updated as benchmarks - // change. - // - // following this assertion, we add individual weights together to show that we can - // derive this number independently. - let expected_on_init = 2_537_230_483; - assert_eq!(Weight::from_ref_time(expected_on_init), weight); - - // assemble weight manually to ensure it is well understood - let mut expected_weight = 0u64; - expected_weight += PalletWeights::::base_on_initialize().ref_time(); - expected_weight += PalletWeights::::prepare_staking_payouts().ref_time(); - - // TODO: this should be the same as >. I believe this relates to - // genesis building - let num_avg_delegations = 8; - expected_weight += PalletWeights::::select_top_candidates( - >::get(), - num_avg_delegations, - ) - .ref_time(); - // Round and Staked writes, done in on-round-change code block inside on_initialize() - expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); - // more reads/writes manually accounted for for on_finalize - expected_weight += RocksDbWeight::get().reads_writes(3, 2).ref_time(); - - assert_eq!(Weight::from_ref_time(expected_weight), weight); - assert_eq!(expected_on_init, expected_weight); // magic number == independent accounting - }); + use crate::{ + mock::System, + weights::{SubstrateWeight as PalletWeights, WeightInfo}, + *, + }; + use frame_support::{pallet_prelude::*, weights::constants::RocksDbWeight}; + + // generate balance, candidate, and delegation vecs to "fill" out delegations + let mut balances = Vec::new(); + let mut candidates = Vec::new(); + let mut delegations = Vec::new(); + + for collator in 1..30 { + balances.push((collator, 100)); + candidates.push((collator, 10)); + let starting_delegator = collator * 1000; + for delegator in starting_delegator..starting_delegator + 300 { + balances.push((delegator, 100)); + delegations.push((delegator, collator, 10)); + } + } + + ExtBuilder::default() + .with_balances(balances) + .with_candidates(candidates) + .with_delegations(delegations) + .build() + .execute_with(|| { + let weight = ParachainStaking::on_initialize(1); + + // TODO: build this with proper db reads/writes + assert_eq!(Weight::from_ref_time(285_890_000), weight); + + // roll to the end of the round, then run on_init again, we should see round change... + roll_to_round_end(3); + set_author(2, 1, 100); // must set some points for prepare_staking_payouts + let block = System::block_number() + 1; + let weight = ParachainStaking::on_initialize(block); + + // the total on_init weight during our round change. this number is taken from running + // the fn with a given weights.rs benchmark, so will need to be updated as benchmarks + // change. + // + // following this assertion, we add individual weights together to show that we can + // derive this number independently. + let expected_on_init = 2_537_230_483; + assert_eq!(Weight::from_ref_time(expected_on_init), weight); + + // assemble weight manually to ensure it is well understood + let mut expected_weight = 0u64; + expected_weight += PalletWeights::::base_on_initialize().ref_time(); + expected_weight += PalletWeights::::prepare_staking_payouts().ref_time(); + + // TODO: this should be the same as >. I believe this relates to + // genesis building + let num_avg_delegations = 8; + expected_weight += PalletWeights::::select_top_candidates( + >::get(), + num_avg_delegations, + ) + .ref_time(); + // Round and Staked writes, done in on-round-change code block inside on_initialize() + expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); + // more reads/writes manually accounted for for on_finalize + expected_weight += RocksDbWeight::get().reads_writes(3, 2).ref_time(); + + assert_eq!(Weight::from_ref_time(expected_weight), weight); + assert_eq!(expected_on_init, expected_weight); // magic number == independent accounting + }); } diff --git a/external/pallets/parachain-staking/src/traits.rs b/external/pallets/parachain-staking/src/traits.rs index 2b30b04cc..b343ef3dc 100644 --- a/external/pallets/parachain-staking/src/traits.rs +++ b/external/pallets/parachain-staking/src/traits.rs @@ -19,48 +19,48 @@ use frame_support::pallet_prelude::Weight; pub trait OnCollatorPayout { - fn on_collator_payout( - for_round: crate::RoundIndex, - collator_id: AccountId, - amount: Balance, - ) -> Weight; + fn on_collator_payout( + for_round: crate::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight; } impl OnCollatorPayout for () { - fn on_collator_payout( - _for_round: crate::RoundIndex, - _collator_id: AccountId, - _amount: Balance, - ) -> Weight { - Weight::zero() - } + fn on_collator_payout( + _for_round: crate::RoundIndex, + _collator_id: AccountId, + _amount: Balance, + ) -> Weight { + Weight::zero() + } } pub trait OnNewRound { - fn on_new_round(round_index: crate::RoundIndex) -> Weight; + fn on_new_round(round_index: crate::RoundIndex) -> Weight; } impl OnNewRound for () { - fn on_new_round(_round_index: crate::RoundIndex) -> Weight { - Weight::zero() - } + fn on_new_round(_round_index: crate::RoundIndex) -> Weight { + Weight::zero() + } } /// Defines the behavior to payout the collator's reward. pub trait PayoutCollatorReward { - fn payout_collator_reward( - round_index: crate::RoundIndex, - collator_id: Runtime::AccountId, - amount: crate::BalanceOf, - ) -> Weight; + fn payout_collator_reward( + round_index: crate::RoundIndex, + collator_id: Runtime::AccountId, + amount: crate::BalanceOf, + ) -> Weight; } /// Defines the default behavior for paying out the collator's reward. The amount is directly /// deposited into the collator's account. impl PayoutCollatorReward for () { - fn payout_collator_reward( - for_round: crate::RoundIndex, - collator_id: Runtime::AccountId, - amount: crate::BalanceOf, - ) -> Weight { - crate::Pallet::::mint_collator_reward(for_round, collator_id, amount) - } + fn payout_collator_reward( + for_round: crate::RoundIndex, + collator_id: Runtime::AccountId, + amount: crate::BalanceOf, + ) -> Weight { + crate::Pallet::::mint_collator_reward(for_round, collator_id, amount) + } } diff --git a/external/pallets/parachain-staking/src/types.rs b/external/pallets/parachain-staking/src/types.rs index dbb673e70..17dfbabb4 100644 --- a/external/pallets/parachain-staking/src/types.rs +++ b/external/pallets/parachain-staking/src/types.rs @@ -17,1741 +17,1614 @@ //! Types for parachain-staking use crate::{ - auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, - CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, - Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, + auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, + CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, + Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, }; use frame_support::{ - pallet_prelude::*, - traits::{tokens::WithdrawReasons, LockableCurrency}, + pallet_prelude::*, + traits::{tokens::WithdrawReasons, LockableCurrency}, }; use parity_scale_codec::{Decode, Encode}; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Saturating, Zero}, - Perbill, Percent, RuntimeDebug, + traits::{AtLeast32BitUnsigned, Saturating, Zero}, + Perbill, Percent, RuntimeDebug, }; use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; pub struct CountedDelegations { - pub uncounted_stake: BalanceOf, - pub rewardable_delegations: Vec>>, + pub uncounted_stake: BalanceOf, + pub rewardable_delegations: Vec>>, } #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct Bond { - pub owner: AccountId, - pub amount: Balance, + pub owner: AccountId, + pub amount: Balance, } impl Default for Bond { - fn default() -> Bond { - Bond { - owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - amount: B::default(), - } - } + fn default() -> Bond { + Bond { + owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + amount: B::default(), + } + } } impl Bond { - pub fn from_owner(owner: A) -> Self { - Bond { - owner, - amount: B::default(), - } - } + pub fn from_owner(owner: A) -> Self { + Bond { owner, amount: B::default() } + } } impl Eq for Bond {} impl Ord for Bond { - fn cmp(&self, other: &Self) -> Ordering { - self.owner.cmp(&other.owner) - } + fn cmp(&self, other: &Self) -> Ordering { + self.owner.cmp(&other.owner) + } } impl PartialOrd for Bond { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } impl PartialEq for Bond { - fn eq(&self, other: &Self) -> bool { - self.owner == other.owner - } + fn eq(&self, other: &Self) -> bool { + self.owner == other.owner + } } #[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] /// The activity status of the collator pub enum CollatorStatus { - /// Committed to be online and producing valid blocks (not equivocating) - Active, - /// Temporarily inactive and excused for inactivity - Idle, - /// Bonded until the inner round - Leaving(RoundIndex), + /// Committed to be online and producing valid blocks (not equivocating) + Active, + /// Temporarily inactive and excused for inactivity + Idle, + /// Bonded until the inner round + Leaving(RoundIndex), } impl Default for CollatorStatus { - fn default() -> CollatorStatus { - CollatorStatus::Active - } + fn default() -> CollatorStatus { + CollatorStatus::Active + } } #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct BondWithAutoCompound { - pub owner: AccountId, - pub amount: Balance, - pub auto_compound: Percent, + pub owner: AccountId, + pub amount: Balance, + pub auto_compound: Percent, } impl Default for BondWithAutoCompound { - fn default() -> BondWithAutoCompound { - BondWithAutoCompound { - owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - amount: B::default(), - auto_compound: Percent::zero(), - } - } + fn default() -> BondWithAutoCompound { + BondWithAutoCompound { + owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + amount: B::default(), + auto_compound: Percent::zero(), + } + } } #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] /// Snapshot of collator state at the start of the round for which they are selected pub struct CollatorSnapshot { - /// The total value locked by the collator. - pub bond: Balance, + /// The total value locked by the collator. + pub bond: Balance, - /// The rewardable delegations. This list is a subset of total delegators, where certain - /// delegators are adjusted based on their scheduled - /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. - pub delegations: Vec>, + /// The rewardable delegations. This list is a subset of total delegators, where certain + /// delegators are adjusted based on their scheduled + /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. + pub delegations: Vec>, - /// The total counted value locked for the collator, including the self bond + total staked by - /// top delegators. - pub total: Balance, + /// The total counted value locked for the collator, including the self bond + total staked by + /// top delegators. + pub total: Balance, } impl PartialEq for CollatorSnapshot { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.bond == other.bond && self.total == other.total; - if !must_be_true { - return false; - } - for ( - BondWithAutoCompound { - owner: o1, - amount: a1, - auto_compound: c1, - }, - BondWithAutoCompound { - owner: o2, - amount: a2, - auto_compound: c2, - }, - ) in self.delegations.iter().zip(other.delegations.iter()) - { - if o1 != o2 || a1 != a2 || c1 != c2 { - return false; - } - } - true - } + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.bond == other.bond && self.total == other.total; + if !must_be_true { + return false; + } + for ( + BondWithAutoCompound { owner: o1, amount: a1, auto_compound: c1 }, + BondWithAutoCompound { owner: o2, amount: a2, auto_compound: c2 }, + ) in self.delegations.iter().zip(other.delegations.iter()) + { + if o1 != o2 || a1 != a2 || c1 != c2 { + return false; + } + } + true + } } impl Default for CollatorSnapshot { - fn default() -> CollatorSnapshot { - CollatorSnapshot { - bond: B::default(), - delegations: Vec::new(), - total: B::default(), - } - } + fn default() -> CollatorSnapshot { + CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } + } } #[derive(Default, Encode, Decode, RuntimeDebug, TypeInfo)] /// Info needed to make delayed payments to stakers after round end pub struct DelayedPayout { - /// Total round reward (result of compute_issuance() at round end) - pub round_issuance: Balance, - /// The total inflation paid this round to stakers (e.g. less parachain bond fund) - pub total_staking_reward: Balance, - /// Snapshot of collator commission rate at the end of the round - pub collator_commission: Perbill, + /// Total round reward (result of compute_issuance() at round end) + pub round_issuance: Balance, + /// The total inflation paid this round to stakers (e.g. less parachain bond fund) + pub total_staking_reward: Balance, + /// Snapshot of collator commission rate at the end of the round + pub collator_commission: Perbill, } #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] /// DEPRECATED /// Collator state with commission fee, bonded stake, and delegations pub struct Collator2 { - /// The account of this collator - pub id: AccountId, - /// This collator's self stake. - pub bond: Balance, - /// Set of all nominator AccountIds (to prevent >1 nomination per AccountId) - pub nominators: OrderedSet, - /// Top T::MaxDelegatorsPerCollator::get() nominators, ordered greatest to least - pub top_nominators: Vec>, - /// Bottom nominators (unbounded), ordered least to greatest - pub bottom_nominators: Vec>, - /// Sum of top delegations + self.bond - pub total_counted: Balance, - /// Sum of all delegations + self.bond = (total_counted + uncounted) - pub total_backing: Balance, - /// Current status of the collator - pub state: CollatorStatus, + /// The account of this collator + pub id: AccountId, + /// This collator's self stake. + pub bond: Balance, + /// Set of all nominator AccountIds (to prevent >1 nomination per AccountId) + pub nominators: OrderedSet, + /// Top T::MaxDelegatorsPerCollator::get() nominators, ordered greatest to least + pub top_nominators: Vec>, + /// Bottom nominators (unbounded), ordered least to greatest + pub bottom_nominators: Vec>, + /// Sum of top delegations + self.bond + pub total_counted: Balance, + /// Sum of all delegations + self.bond = (total_counted + uncounted) + pub total_backing: Balance, + /// Current status of the collator + pub state: CollatorStatus, } impl From> for CollatorCandidate { - fn from(other: Collator2) -> CollatorCandidate { - CollatorCandidate { - id: other.id, - bond: other.bond, - delegators: other.nominators, - top_delegations: other.top_nominators, - bottom_delegations: other.bottom_nominators, - total_counted: other.total_counted, - total_backing: other.total_backing, - request: None, - state: other.state, - } - } + fn from(other: Collator2) -> CollatorCandidate { + CollatorCandidate { + id: other.id, + bond: other.bond, + delegators: other.nominators, + top_delegations: other.top_nominators, + bottom_delegations: other.bottom_nominators, + total_counted: other.total_counted, + total_backing: other.total_backing, + request: None, + state: other.state, + } + } } -#[derive(PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] /// Request scheduled to change the collator candidate self-bond pub struct CandidateBondLessRequest { - pub amount: Balance, - pub when_executable: RoundIndex, + pub amount: Balance, + pub when_executable: RoundIndex, } #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] /// DEPRECATED, replaced by `CandidateMetadata` and two storage instances of `Delegations` /// Collator candidate state with self bond + delegations pub struct CollatorCandidate { - /// The account of this collator - pub id: AccountId, - /// This collator's self stake. - pub bond: Balance, - /// Set of all delegator AccountIds (to prevent >1 delegation per AccountId) - pub delegators: OrderedSet, - /// Top T::MaxDelegatorsPerCollator::get() delegations, ordered greatest to least - pub top_delegations: Vec>, - /// Bottom delegations (unbounded), ordered least to greatest - pub bottom_delegations: Vec>, - /// Sum of top delegations + self.bond - pub total_counted: Balance, - /// Sum of all delegations + self.bond = (total_counted + uncounted) - pub total_backing: Balance, - /// Maximum 1 pending request to decrease candidate self bond at any given time - pub request: Option>, - /// Current status of the collator - pub state: CollatorStatus, + /// The account of this collator + pub id: AccountId, + /// This collator's self stake. + pub bond: Balance, + /// Set of all delegator AccountIds (to prevent >1 delegation per AccountId) + pub delegators: OrderedSet, + /// Top T::MaxDelegatorsPerCollator::get() delegations, ordered greatest to least + pub top_delegations: Vec>, + /// Bottom delegations (unbounded), ordered least to greatest + pub bottom_delegations: Vec>, + /// Sum of top delegations + self.bond + pub total_counted: Balance, + /// Sum of all delegations + self.bond = (total_counted + uncounted) + pub total_backing: Balance, + /// Maximum 1 pending request to decrease candidate self bond at any given time + pub request: Option>, + /// Current status of the collator + pub state: CollatorStatus, } #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] /// Type for top and bottom delegation storage item pub struct Delegations { - pub delegations: Vec>, - pub total: Balance, + pub delegations: Vec>, + pub total: Balance, } impl Default for Delegations { - fn default() -> Delegations { - Delegations { - delegations: Vec::new(), - total: B::default(), - } - } + fn default() -> Delegations { + Delegations { delegations: Vec::new(), total: B::default() } + } } impl - Delegations + Delegations { - pub fn sort_greatest_to_least(&mut self) { - self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); - } - /// Insert sorted greatest to least and increase .total accordingly - /// Insertion respects first come first serve so new delegations are pushed after existing - /// delegations if the amount is the same - pub fn insert_sorted_greatest_to_least(&mut self, delegation: Bond) { - self.total = self.total.saturating_add(delegation.amount); - // if delegations nonempty && last_element == delegation.amount => push input and return - if !self.delegations.is_empty() { - // if last_element == delegation.amount => push the delegation and return early - if self.delegations[self.delegations.len() - 1].amount == delegation.amount { - self.delegations.push(delegation); - // early return - return; - } - } - // else binary search insertion - match self - .delegations - .binary_search_by(|x| delegation.amount.cmp(&x.amount)) - { - // sorted insertion on sorted vec - // enforces first come first serve for equal bond amounts - Ok(i) => { - let mut new_index = i + 1; - while new_index <= (self.delegations.len() - 1) { - if self.delegations[new_index].amount == delegation.amount { - new_index = new_index.saturating_add(1); - } else { - self.delegations.insert(new_index, delegation); - return; - } - } - self.delegations.push(delegation) - } - Err(i) => self.delegations.insert(i, delegation), - } - } - /// Return the capacity status for top delegations - pub fn top_capacity(&self) -> CapacityStatus { - match &self.delegations { - x if x.len() as u32 >= T::MaxTopDelegationsPerCandidate::get() => CapacityStatus::Full, - x if x.is_empty() => CapacityStatus::Empty, - _ => CapacityStatus::Partial, - } - } - /// Return the capacity status for bottom delegations - pub fn bottom_capacity(&self) -> CapacityStatus { - match &self.delegations { - x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => { - CapacityStatus::Full - } - x if x.is_empty() => CapacityStatus::Empty, - _ => CapacityStatus::Partial, - } - } - /// Return last delegation amount without popping the delegation - pub fn lowest_delegation_amount(&self) -> Balance { - self.delegations - .last() - .map(|x| x.amount) - .unwrap_or(Balance::zero()) - } - /// Return highest delegation amount - pub fn highest_delegation_amount(&self) -> Balance { - self.delegations - .first() - .map(|x| x.amount) - .unwrap_or(Balance::zero()) - } + pub fn sort_greatest_to_least(&mut self) { + self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); + } + /// Insert sorted greatest to least and increase .total accordingly + /// Insertion respects first come first serve so new delegations are pushed after existing + /// delegations if the amount is the same + pub fn insert_sorted_greatest_to_least(&mut self, delegation: Bond) { + self.total = self.total.saturating_add(delegation.amount); + // if delegations nonempty && last_element == delegation.amount => push input and return + if !self.delegations.is_empty() { + // if last_element == delegation.amount => push the delegation and return early + if self.delegations[self.delegations.len() - 1].amount == delegation.amount { + self.delegations.push(delegation); + // early return + return; + } + } + // else binary search insertion + match self.delegations.binary_search_by(|x| delegation.amount.cmp(&x.amount)) { + // sorted insertion on sorted vec + // enforces first come first serve for equal bond amounts + Ok(i) => { + let mut new_index = i + 1; + while new_index <= (self.delegations.len() - 1) { + if self.delegations[new_index].amount == delegation.amount { + new_index = new_index.saturating_add(1); + } else { + self.delegations.insert(new_index, delegation); + return; + } + } + self.delegations.push(delegation) + } + Err(i) => self.delegations.insert(i, delegation), + } + } + /// Return the capacity status for top delegations + pub fn top_capacity(&self) -> CapacityStatus { + match &self.delegations { + x if x.len() as u32 >= T::MaxTopDelegationsPerCandidate::get() => CapacityStatus::Full, + x if x.is_empty() => CapacityStatus::Empty, + _ => CapacityStatus::Partial, + } + } + /// Return the capacity status for bottom delegations + pub fn bottom_capacity(&self) -> CapacityStatus { + match &self.delegations { + x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => { + CapacityStatus::Full + } + x if x.is_empty() => CapacityStatus::Empty, + _ => CapacityStatus::Partial, + } + } + /// Return last delegation amount without popping the delegation + pub fn lowest_delegation_amount(&self) -> Balance { + self.delegations.last().map(|x| x.amount).unwrap_or_else(Balance::zero) + } + /// Return highest delegation amount + pub fn highest_delegation_amount(&self) -> Balance { + self.delegations.first().map(|x| x.amount).unwrap_or_else(Balance::zero) + } } -#[derive(PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] /// Capacity status for top or bottom delegations pub enum CapacityStatus { - /// Reached capacity - Full, - /// Empty aka contains no delegations - Empty, - /// Partially full (nonempty and not full) - Partial, + /// Reached capacity + Full, + /// Empty aka contains no delegations + Empty, + /// Partially full (nonempty and not full) + Partial, } #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] /// All candidate info except the top and bottom delegations pub struct CandidateMetadata { - /// This candidate's self bond amount - pub bond: Balance, - /// Total number of delegations to this candidate - pub delegation_count: u32, - /// Self bond + sum of top delegations - pub total_counted: Balance, - /// The smallest top delegation amount - pub lowest_top_delegation_amount: Balance, - /// The highest bottom delegation amount - pub highest_bottom_delegation_amount: Balance, - /// The smallest bottom delegation amount - pub lowest_bottom_delegation_amount: Balance, - /// Capacity status for top delegations - pub top_capacity: CapacityStatus, - /// Capacity status for bottom delegations - pub bottom_capacity: CapacityStatus, - /// Maximum 1 pending request to decrease candidate self bond at any given time - pub request: Option>, - /// Current status of the collator - pub status: CollatorStatus, + /// This candidate's self bond amount + pub bond: Balance, + /// Total number of delegations to this candidate + pub delegation_count: u32, + /// Self bond + sum of top delegations + pub total_counted: Balance, + /// The smallest top delegation amount + pub lowest_top_delegation_amount: Balance, + /// The highest bottom delegation amount + pub highest_bottom_delegation_amount: Balance, + /// The smallest bottom delegation amount + pub lowest_bottom_delegation_amount: Balance, + /// Capacity status for top delegations + pub top_capacity: CapacityStatus, + /// Capacity status for bottom delegations + pub bottom_capacity: CapacityStatus, + /// Maximum 1 pending request to decrease candidate self bond at any given time + pub request: Option>, + /// Current status of the collator + pub status: CollatorStatus, } impl< - Balance: Copy - + Zero - + PartialOrd - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + sp_std::fmt::Debug - + Saturating, - > CandidateMetadata + Balance: Copy + + Zero + + PartialOrd + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + sp_std::fmt::Debug + + Saturating, +> CandidateMetadata { - pub fn new(bond: Balance) -> Self { - CandidateMetadata { - bond, - delegation_count: 0u32, - total_counted: bond, - lowest_top_delegation_amount: Zero::zero(), - highest_bottom_delegation_amount: Zero::zero(), - lowest_bottom_delegation_amount: Zero::zero(), - top_capacity: CapacityStatus::Empty, - bottom_capacity: CapacityStatus::Empty, - request: None, - status: CollatorStatus::Active, - } - } - pub fn is_active(&self) -> bool { - matches!(self.status, CollatorStatus::Active) - } - pub fn is_leaving(&self) -> bool { - matches!(self.status, CollatorStatus::Leaving(_)) - } - pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { - ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); - let now = >::get().current; - let when = now + T::LeaveCandidatesDelay::get(); - self.status = CollatorStatus::Leaving(when); - Ok((now, when)) - } - pub fn can_leave(&self) -> DispatchResult { - if let CollatorStatus::Leaving(when) = self.status { - ensure!( - >::get().current >= when, - Error::::CandidateCannotLeaveYet - ); - Ok(()) - } else { - Err(Error::::CandidateNotLeaving.into()) - } - } - pub fn go_offline(&mut self) { - self.status = CollatorStatus::Idle; - } - pub fn go_online(&mut self) { - self.status = CollatorStatus::Active; - } - pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult - where - BalanceOf: From, - { - ensure!( - >::get_collator_stakable_free_balance(&who) >= more.into(), - Error::::InsufficientBalance - ); - let new_total = >::get().saturating_add(more.into()); - >::put(new_total); - self.bond = self.bond.saturating_add(more); - T::Currency::set_lock( - COLLATOR_LOCK_ID, - &who.clone(), - self.bond.into(), - WithdrawReasons::all(), - ); - self.total_counted = self.total_counted.saturating_add(more); - >::deposit_event(Event::CandidateBondedMore { - candidate: who.clone(), - amount: more.into(), - new_total_bond: self.bond.into(), - }); - Ok(()) - } - /// Schedule executable decrease of collator candidate self bond - /// Returns the round at which the collator can execute the pending request - pub fn schedule_bond_less( - &mut self, - less: Balance, - ) -> Result - where - BalanceOf: Into, - { - // ensure no pending request - ensure!( - self.request.is_none(), - Error::::PendingCandidateRequestAlreadyExists - ); - // ensure bond above min after decrease - ensure!(self.bond > less, Error::::CandidateBondBelowMin); - ensure!( - self.bond - less >= T::MinCandidateStk::get().into(), - Error::::CandidateBondBelowMin - ); - let when_executable = >::get().current + T::CandidateBondLessDelay::get(); - self.request = Some(CandidateBondLessRequest { - amount: less, - when_executable, - }); - Ok(when_executable) - } - /// Execute pending request to decrease the collator self bond - /// Returns the event to be emitted - pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult - where - BalanceOf: From, - { - let request = self - .request - .ok_or(Error::::PendingCandidateRequestsDNE)?; - ensure!( - request.when_executable <= >::get().current, - Error::::PendingCandidateRequestNotDueYet - ); - let new_total_staked = >::get().saturating_sub(request.amount.into()); - >::put(new_total_staked); - // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond - // (assumptions enforced by `schedule_bond_less`; if storage corrupts, must re-verify) - self.bond = self.bond.saturating_sub(request.amount); - T::Currency::set_lock( - COLLATOR_LOCK_ID, - &who.clone(), - self.bond.into(), - WithdrawReasons::all(), - ); - self.total_counted = self.total_counted.saturating_sub(request.amount); - let event = Event::CandidateBondedLess { - candidate: who.clone().into(), - amount: request.amount.into(), - new_bond: self.bond.into(), - }; - // reset s.t. no pending request - self.request = None; - // update candidate pool value because it must change if self bond changes - if self.is_active() { - Pallet::::update_active(who.into(), self.total_counted.into()); - } - Pallet::::deposit_event(event); - Ok(()) - } - /// Cancel candidate bond less request - pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult - where - BalanceOf: From, - { - let request = self - .request - .ok_or(Error::::PendingCandidateRequestsDNE)?; - let event = Event::CancelledCandidateBondLess { - candidate: who.clone().into(), - amount: request.amount.into(), - execute_round: request.when_executable, - }; - self.request = None; - Pallet::::deposit_event(event); - Ok(()) - } - /// Reset top delegations metadata - pub fn reset_top_data( - &mut self, - candidate: T::AccountId, - top_delegations: &Delegations>, - ) where - BalanceOf: Into + From, - { - self.lowest_top_delegation_amount = top_delegations.lowest_delegation_amount().into(); - self.top_capacity = top_delegations.top_capacity::(); - let old_total_counted = self.total_counted; - self.total_counted = self.bond.saturating_add(top_delegations.total.into()); - // CandidatePool value for candidate always changes if top delegations total changes - // so we moved the update into this function to deduplicate code and patch a bug that - // forgot to apply the update when increasing top delegation - if old_total_counted != self.total_counted && self.is_active() { - Pallet::::update_active(candidate, self.total_counted.into()); - } - } - /// Reset bottom delegations metadata - pub fn reset_bottom_data( - &mut self, - bottom_delegations: &Delegations>, - ) where - BalanceOf: Into, - { - self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); - self.highest_bottom_delegation_amount = - bottom_delegations.highest_delegation_amount().into(); - self.bottom_capacity = bottom_delegations.bottom_capacity::(); - } - /// Add delegation - /// Returns whether delegator was added and an optional negative total counted remainder - /// for if a bottom delegation was kicked - /// MUST ensure no delegation exists for this candidate in the `DelegatorState` before call - pub fn add_delegation( - &mut self, - candidate: &T::AccountId, - delegation: Bond>, - ) -> Result<(DelegatorAdded, Option), DispatchError> - where - BalanceOf: Into + From, - { - let mut less_total_staked = None; - let delegator_added = match self.top_capacity { - CapacityStatus::Full => { - // top is full, insert into top iff the lowest_top < amount - if self.lowest_top_delegation_amount < delegation.amount.into() { - // bumps lowest top to the bottom inside this function call - less_total_staked = self.add_top_delegation::(candidate, delegation); - DelegatorAdded::AddedToTop { - new_total: self.total_counted, - } - } else { - // if bottom is full, only insert if greater than lowest bottom (which will - // be bumped out) - if matches!(self.bottom_capacity, CapacityStatus::Full) { - ensure!( - delegation.amount.into() > self.lowest_bottom_delegation_amount, - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - // need to subtract from total staked - less_total_staked = Some(self.lowest_bottom_delegation_amount); - } - // insert into bottom - self.add_bottom_delegation::(false, candidate, delegation); - DelegatorAdded::AddedToBottom - } - } - // top is either empty or partially full - _ => { - self.add_top_delegation::(candidate, delegation); - DelegatorAdded::AddedToTop { - new_total: self.total_counted, - } - } - }; - Ok((delegator_added, less_total_staked)) - } - /// Add delegation to top delegation - /// Returns Option - /// Only call if lowest top delegation is less than delegation.amount || !top_full - pub fn add_top_delegation( - &mut self, - candidate: &T::AccountId, - delegation: Bond>, - ) -> Option - where - BalanceOf: Into + From, - { - let mut less_total_staked = None; - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); - let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); - if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { - // pop lowest top delegation - let new_bottom_delegation = top_delegations.delegations.pop().expect(""); - top_delegations.total = top_delegations - .total - .saturating_sub(new_bottom_delegation.amount); - if matches!(self.bottom_capacity, CapacityStatus::Full) { - less_total_staked = Some(self.lowest_bottom_delegation_amount); - } - self.add_bottom_delegation::(true, candidate, new_bottom_delegation); - } - // insert into top - top_delegations.insert_sorted_greatest_to_least(delegation); - // update candidate info - self.reset_top_data::(candidate.clone(), &top_delegations); - if less_total_staked.is_none() { - // only increment delegation count if we are not kicking a bottom delegation - self.delegation_count = self.delegation_count.saturating_add(1u32); - } - >::insert(&candidate, top_delegations); - less_total_staked - } - /// Add delegation to bottom delegations - /// Check before call that if capacity is full, inserted delegation is higher than lowest - /// bottom delegation (and if so, need to adjust the total storage item) - /// CALLER MUST ensure(lowest_bottom_to_be_kicked.amount < delegation.amount) - pub fn add_bottom_delegation( - &mut self, - bumped_from_top: bool, - candidate: &T::AccountId, - delegation: Bond>, - ) where - BalanceOf: Into + From, - { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); - // if bottom is full, kick the lowest bottom (which is expected to be lower than input - // as per check) - let increase_delegation_count = if bottom_delegations.delegations.len() as u32 - == T::MaxBottomDelegationsPerCandidate::get() - { - let lowest_bottom_to_be_kicked = bottom_delegations - .delegations - .pop() - .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); - // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller - // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick - // the lowest bottom to enforce first come first served - bottom_delegations.total = bottom_delegations - .total - .saturating_sub(lowest_bottom_to_be_kicked.amount); - // update delegator state - // total staked is updated via propagation of lowest bottom delegation amount prior - // to call - let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) - .expect("Delegation existence => DelegatorState existence"); - let leaving = delegator_state.delegations.0.len() == 1usize; - delegator_state.rm_delegation::(candidate); - >::delegation_remove_request_with_state( - &candidate, - &lowest_bottom_to_be_kicked.owner, - &mut delegator_state, - ); - >::remove_auto_compound( - &candidate, - &lowest_bottom_to_be_kicked.owner, - ); - - Pallet::::deposit_event(Event::DelegationKicked { - delegator: lowest_bottom_to_be_kicked.owner.clone(), - candidate: candidate.clone(), - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - if leaving { - >::remove(&lowest_bottom_to_be_kicked.owner); - Pallet::::deposit_event(Event::DelegatorLeft { - delegator: lowest_bottom_to_be_kicked.owner, - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - } else { - >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); - } - false - } else { - !bumped_from_top - }; - // only increase delegation count if new bottom delegation (1) doesn't come from top && - // (2) doesn't pop the lowest delegation from the bottom - if increase_delegation_count { - self.delegation_count = self.delegation_count.saturating_add(1u32); - } - bottom_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - } - /// Remove delegation - /// Removes from top if amount is above lowest top or top is not full - /// Return Ok(if_total_counted_changed) - pub fn rm_delegation_if_exists( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - amount: Balance, - ) -> Result - where - BalanceOf: Into + From, - { - let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; - let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { - self.rm_top_delegation::(candidate, delegator) - } else if amount_geq_lowest_top && lowest_top_eq_highest_bottom { - let result = self.rm_top_delegation::(candidate, delegator.clone()); - if result == Err(delegation_dne_err) { - // worst case removal - self.rm_bottom_delegation::(candidate, delegator) - } else { - result - } - } else { - self.rm_bottom_delegation::(candidate, delegator) - } - } - /// Remove top delegation, bumps top bottom delegation if exists - pub fn rm_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - ) -> Result - where - BalanceOf: Into + From, - { - let old_total_counted = self.total_counted; - // remove top delegation - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); - let mut actual_amount_option: Option> = None; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - actual_amount_option = Some(d.amount); - false - } - }) - .collect(); - let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; - top_delegations.total = top_delegations.total.saturating_sub(actual_amount); - // if bottom nonempty => bump top bottom to top - if !matches!(self.bottom_capacity, CapacityStatus::Empty) { - let mut bottom_delegations = - >::get(candidate).expect("bottom is nonempty as just checked"); - // expect already stored greatest to least by bond amount - let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = bottom_delegations - .total - .saturating_sub(highest_bottom_delegation.amount); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - // insert highest bottom into top delegations - top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); - } - // update candidate info - self.reset_top_data::(candidate.clone(), &top_delegations); - self.delegation_count = self.delegation_count.saturating_sub(1u32); - >::insert(candidate, top_delegations); - // return whether total counted changed - Ok(old_total_counted == self.total_counted) - } - /// Remove bottom delegation - /// Returns if_total_counted_changed: bool - pub fn rm_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - ) -> Result - where - BalanceOf: Into, - { - // remove bottom delegation - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); - let mut actual_amount_option: Option> = None; - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - actual_amount_option = Some(d.amount); - false - } - }) - .collect(); - let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; - bottom_delegations.total = bottom_delegations.total.saturating_sub(actual_amount); - // update candidate info - self.reset_bottom_data::(&bottom_delegations); - self.delegation_count = self.delegation_count.saturating_sub(1u32); - >::insert(candidate, bottom_delegations); - Ok(false) - } - /// Increase delegation amount - pub fn increase_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { - // definitely in top - self.increase_top_delegation::(candidate, delegator.clone(), more) - } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { - // update top but if error then update bottom (because could be in bottom because - // lowest_top_eq_highest_bottom) - let result = self.increase_top_delegation::(candidate, delegator.clone(), more); - if result == Err(delegation_dne_err) { - self.increase_bottom_delegation::(candidate, delegator, bond, more) - } else { - result - } - } else { - self.increase_bottom_delegation::(candidate, delegator, bond, more) - } - } - /// Increase top delegation - pub fn increase_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); - let mut in_top = false; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_top = true; - let new_amount = d.amount.saturating_add(more); - Bond { - owner: d.owner, - amount: new_amount, - } - } - }) - .collect(); - ensure!(in_top, Error::::DelegationDNE); - top_delegations.total = top_delegations.total.saturating_add(more); - top_delegations.sort_greatest_to_least(); - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - Ok(true) - } - /// Increase bottom delegation - pub fn increase_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let mut bottom_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; - let mut delegation_option: Option>> = None; - let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount - { - // bump it from bottom - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_add(more), - }); - false - } - }) - .collect(); - let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; - bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); - // add it to top - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); - // if top is full, pop lowest top - if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { - // pop lowest top delegation - let new_bottom_delegation = top_delegations - .delegations - .pop() - .expect("Top capacity full => Exists at least 1 top delegation"); - top_delegations.total = top_delegations - .total - .saturating_sub(new_bottom_delegation.amount); - bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); - } - // insert into top - top_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - true - } else { - let mut in_bottom = false; - // just increase the delegation - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_bottom = true; - Bond { - owner: d.owner, - amount: d.amount.saturating_add(more), - } - } - }) - .collect(); - ensure!(in_bottom, Error::::DelegationDNE); - bottom_delegations.total = bottom_delegations.total.saturating_add(more); - bottom_delegations.sort_greatest_to_least(); - false - }; - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - Ok(in_top_after) - } - /// Decrease delegation - pub fn decrease_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: Balance, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { - // definitely in top - self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less) - } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { - // update top but if error then update bottom (because could be in bottom because - // lowest_top_eq_highest_bottom) - let result = - self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); - if result == Err(delegation_dne_err) { - self.decrease_bottom_delegation::(candidate, delegator, less) - } else { - result - } - } else { - self.decrease_bottom_delegation::(candidate, delegator, less) - } - } - /// Decrease top delegation - pub fn decrease_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - // The delegation after the `decrease-delegation` will be strictly less than the - // highest bottom delegation - let bond_after_less_than_highest_bottom = - bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; - // The top delegations is full and the bottom delegations has at least one delegation - let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) - && !matches!(self.bottom_capacity, CapacityStatus::Empty); - let mut top_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; - let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { - let mut delegation_option: Option>> = None; - // take delegation from top - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - top_delegations.total = top_delegations.total.saturating_sub(d.amount); - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_sub(less), - }); - false - } - }) - .collect(); - let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; - // pop highest bottom by reverse and popping - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); - let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = bottom_delegations - .total - .saturating_sub(highest_bottom_delegation.amount); - // insert highest bottom into top - top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); - // insert previous top into bottom - bottom_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - false - } else { - // keep it in the top - let mut is_in_top = false; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - is_in_top = true; - Bond { - owner: d.owner, - amount: d.amount.saturating_sub(less), - } - } - }) - .collect(); - ensure!(is_in_top, Error::::DelegationDNE); - top_delegations.total = top_delegations.total.saturating_sub(less); - top_delegations.sort_greatest_to_least(); - true - }; - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - Ok(in_top_after) - } - /// Decrease bottom delegation - pub fn decrease_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into, - { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); - let mut in_bottom = false; - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_bottom = true; - Bond { - owner: d.owner, - amount: d.amount.saturating_sub(less), - } - } - }) - .collect(); - ensure!(in_bottom, Error::::DelegationDNE); - bottom_delegations.sort_greatest_to_least(); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - Ok(false) - } + pub fn new(bond: Balance) -> Self { + CandidateMetadata { + bond, + delegation_count: 0u32, + total_counted: bond, + lowest_top_delegation_amount: Zero::zero(), + highest_bottom_delegation_amount: Zero::zero(), + lowest_bottom_delegation_amount: Zero::zero(), + top_capacity: CapacityStatus::Empty, + bottom_capacity: CapacityStatus::Empty, + request: None, + status: CollatorStatus::Active, + } + } + pub fn is_active(&self) -> bool { + matches!(self.status, CollatorStatus::Active) + } + pub fn is_leaving(&self) -> bool { + matches!(self.status, CollatorStatus::Leaving(_)) + } + pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { + ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); + let now = >::get().current; + let when = now + T::LeaveCandidatesDelay::get(); + self.status = CollatorStatus::Leaving(when); + Ok((now, when)) + } + pub fn can_leave(&self) -> DispatchResult { + if let CollatorStatus::Leaving(when) = self.status { + ensure!(>::get().current >= when, Error::::CandidateCannotLeaveYet); + Ok(()) + } else { + Err(Error::::CandidateNotLeaving.into()) + } + } + pub fn go_offline(&mut self) { + self.status = CollatorStatus::Idle; + } + pub fn go_online(&mut self) { + self.status = CollatorStatus::Active; + } + pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult + where + BalanceOf: From, + { + ensure!( + >::get_collator_stakable_free_balance(&who) >= more.into(), + Error::::InsufficientBalance + ); + let new_total = >::get().saturating_add(more.into()); + >::put(new_total); + self.bond = self.bond.saturating_add(more); + T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); + self.total_counted = self.total_counted.saturating_add(more); + >::deposit_event(Event::CandidateBondedMore { + candidate: who, + amount: more.into(), + new_total_bond: self.bond.into(), + }); + Ok(()) + } + /// Schedule executable decrease of collator candidate self bond + /// Returns the round at which the collator can execute the pending request + pub fn schedule_bond_less( + &mut self, + less: Balance, + ) -> Result + where + BalanceOf: Into, + { + // ensure no pending request + ensure!(self.request.is_none(), Error::::PendingCandidateRequestAlreadyExists); + // ensure bond above min after decrease + ensure!(self.bond > less, Error::::CandidateBondBelowMin); + ensure!( + self.bond - less >= T::MinCandidateStk::get().into(), + Error::::CandidateBondBelowMin + ); + let when_executable = >::get().current + T::CandidateBondLessDelay::get(); + self.request = Some(CandidateBondLessRequest { amount: less, when_executable }); + Ok(when_executable) + } + /// Execute pending request to decrease the collator self bond + /// Returns the event to be emitted + pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult + where + BalanceOf: From, + { + let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; + ensure!( + request.when_executable <= >::get().current, + Error::::PendingCandidateRequestNotDueYet + ); + let new_total_staked = >::get().saturating_sub(request.amount.into()); + >::put(new_total_staked); + // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond + // (assumptions enforced by `schedule_bond_less`; if storage corrupts, must re-verify) + self.bond = self.bond.saturating_sub(request.amount); + T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); + self.total_counted = self.total_counted.saturating_sub(request.amount); + let event = Event::CandidateBondedLess { + candidate: who.clone(), + amount: request.amount.into(), + new_bond: self.bond.into(), + }; + // reset s.t. no pending request + self.request = None; + // update candidate pool value because it must change if self bond changes + if self.is_active() { + Pallet::::update_active(who, self.total_counted.into()); + } + Pallet::::deposit_event(event); + Ok(()) + } + /// Cancel candidate bond less request + pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult + where + BalanceOf: From, + { + let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; + let event = Event::CancelledCandidateBondLess { + candidate: who, + amount: request.amount.into(), + execute_round: request.when_executable, + }; + self.request = None; + Pallet::::deposit_event(event); + Ok(()) + } + /// Reset top delegations metadata + pub fn reset_top_data( + &mut self, + candidate: T::AccountId, + top_delegations: &Delegations>, + ) where + BalanceOf: Into + From, + { + self.lowest_top_delegation_amount = top_delegations.lowest_delegation_amount().into(); + self.top_capacity = top_delegations.top_capacity::(); + let old_total_counted = self.total_counted; + self.total_counted = self.bond.saturating_add(top_delegations.total.into()); + // CandidatePool value for candidate always changes if top delegations total changes + // so we moved the update into this function to deduplicate code and patch a bug that + // forgot to apply the update when increasing top delegation + if old_total_counted != self.total_counted && self.is_active() { + Pallet::::update_active(candidate, self.total_counted.into()); + } + } + /// Reset bottom delegations metadata + pub fn reset_bottom_data( + &mut self, + bottom_delegations: &Delegations>, + ) where + BalanceOf: Into, + { + self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); + self.highest_bottom_delegation_amount = + bottom_delegations.highest_delegation_amount().into(); + self.bottom_capacity = bottom_delegations.bottom_capacity::(); + } + /// Add delegation + /// Returns whether delegator was added and an optional negative total counted remainder + /// for if a bottom delegation was kicked + /// MUST ensure no delegation exists for this candidate in the `DelegatorState` before call + pub fn add_delegation( + &mut self, + candidate: &T::AccountId, + delegation: Bond>, + ) -> Result<(DelegatorAdded, Option), DispatchError> + where + BalanceOf: Into + From, + { + let mut less_total_staked = None; + let delegator_added = match self.top_capacity { + CapacityStatus::Full => { + // top is full, insert into top iff the lowest_top < amount + if self.lowest_top_delegation_amount < delegation.amount.into() { + // bumps lowest top to the bottom inside this function call + less_total_staked = self.add_top_delegation::(candidate, delegation); + DelegatorAdded::AddedToTop { new_total: self.total_counted } + } else { + // if bottom is full, only insert if greater than lowest bottom (which will + // be bumped out) + if matches!(self.bottom_capacity, CapacityStatus::Full) { + ensure!( + delegation.amount.into() > self.lowest_bottom_delegation_amount, + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + // need to subtract from total staked + less_total_staked = Some(self.lowest_bottom_delegation_amount); + } + // insert into bottom + self.add_bottom_delegation::(false, candidate, delegation); + DelegatorAdded::AddedToBottom + } + } + // top is either empty or partially full + _ => { + self.add_top_delegation::(candidate, delegation); + DelegatorAdded::AddedToTop { new_total: self.total_counted } + } + }; + Ok((delegator_added, less_total_staked)) + } + /// Add delegation to top delegation + /// Returns Option + /// Only call if lowest top delegation is less than delegation.amount || !top_full + pub fn add_top_delegation( + &mut self, + candidate: &T::AccountId, + delegation: Bond>, + ) -> Option + where + BalanceOf: Into + From, + { + let mut less_total_staked = None; + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); + let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); + if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { + // pop lowest top delegation + let new_bottom_delegation = top_delegations.delegations.pop().expect(""); + top_delegations.total = + top_delegations.total.saturating_sub(new_bottom_delegation.amount); + if matches!(self.bottom_capacity, CapacityStatus::Full) { + less_total_staked = Some(self.lowest_bottom_delegation_amount); + } + self.add_bottom_delegation::(true, candidate, new_bottom_delegation); + } + // insert into top + top_delegations.insert_sorted_greatest_to_least(delegation); + // update candidate info + self.reset_top_data::(candidate.clone(), &top_delegations); + if less_total_staked.is_none() { + // only increment delegation count if we are not kicking a bottom delegation + self.delegation_count = self.delegation_count.saturating_add(1u32); + } + >::insert(candidate, top_delegations); + less_total_staked + } + /// Add delegation to bottom delegations + /// Check before call that if capacity is full, inserted delegation is higher than lowest + /// bottom delegation (and if so, need to adjust the total storage item) + /// CALLER MUST ensure(lowest_bottom_to_be_kicked.amount < delegation.amount) + pub fn add_bottom_delegation( + &mut self, + bumped_from_top: bool, + candidate: &T::AccountId, + delegation: Bond>, + ) where + BalanceOf: Into + From, + { + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); + // if bottom is full, kick the lowest bottom (which is expected to be lower than input + // as per check) + let increase_delegation_count = if bottom_delegations.delegations.len() as u32 + == T::MaxBottomDelegationsPerCandidate::get() + { + let lowest_bottom_to_be_kicked = bottom_delegations + .delegations + .pop() + .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); + // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller + // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick + // the lowest bottom to enforce first come first served + bottom_delegations.total = + bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); + // update delegator state + // total staked is updated via propagation of lowest bottom delegation amount prior + // to call + let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) + .expect("Delegation existence => DelegatorState existence"); + let leaving = delegator_state.delegations.0.len() == 1usize; + delegator_state.rm_delegation::(candidate); + >::delegation_remove_request_with_state( + candidate, + &lowest_bottom_to_be_kicked.owner, + &mut delegator_state, + ); + >::remove_auto_compound( + candidate, + &lowest_bottom_to_be_kicked.owner, + ); + + Pallet::::deposit_event(Event::DelegationKicked { + delegator: lowest_bottom_to_be_kicked.owner.clone(), + candidate: candidate.clone(), + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + if leaving { + >::remove(&lowest_bottom_to_be_kicked.owner); + Pallet::::deposit_event(Event::DelegatorLeft { + delegator: lowest_bottom_to_be_kicked.owner, + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + } else { + >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); + } + false + } else { + !bumped_from_top + }; + // only increase delegation count if new bottom delegation (1) doesn't come from top && + // (2) doesn't pop the lowest delegation from the bottom + if increase_delegation_count { + self.delegation_count = self.delegation_count.saturating_add(1u32); + } + bottom_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + } + /// Remove delegation + /// Removes from top if amount is above lowest top or top is not full + /// Return Ok(if_total_counted_changed) + pub fn rm_delegation_if_exists( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + amount: Balance, + ) -> Result + where + BalanceOf: Into + From, + { + let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; + let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { + self.rm_top_delegation::(candidate, delegator) + } else if amount_geq_lowest_top && lowest_top_eq_highest_bottom { + let result = self.rm_top_delegation::(candidate, delegator.clone()); + if result == Err(delegation_dne_err) { + // worst case removal + self.rm_bottom_delegation::(candidate, delegator) + } else { + result + } + } else { + self.rm_bottom_delegation::(candidate, delegator) + } + } + /// Remove top delegation, bumps top bottom delegation if exists + pub fn rm_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + ) -> Result + where + BalanceOf: Into + From, + { + let old_total_counted = self.total_counted; + // remove top delegation + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); + let mut actual_amount_option: Option> = None; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + actual_amount_option = Some(d.amount); + false + } + }) + .collect(); + let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; + top_delegations.total = top_delegations.total.saturating_sub(actual_amount); + // if bottom nonempty => bump top bottom to top + if !matches!(self.bottom_capacity, CapacityStatus::Empty) { + let mut bottom_delegations = + >::get(candidate).expect("bottom is nonempty as just checked"); + // expect already stored greatest to least by bond amount + let highest_bottom_delegation = bottom_delegations.delegations.remove(0); + bottom_delegations.total = + bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + // insert highest bottom into top delegations + top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); + } + // update candidate info + self.reset_top_data::(candidate.clone(), &top_delegations); + self.delegation_count = self.delegation_count.saturating_sub(1u32); + >::insert(candidate, top_delegations); + // return whether total counted changed + Ok(old_total_counted == self.total_counted) + } + /// Remove bottom delegation + /// Returns if_total_counted_changed: bool + pub fn rm_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + ) -> Result + where + BalanceOf: Into, + { + // remove bottom delegation + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); + let mut actual_amount_option: Option> = None; + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + actual_amount_option = Some(d.amount); + false + } + }) + .collect(); + let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; + bottom_delegations.total = bottom_delegations.total.saturating_sub(actual_amount); + // update candidate info + self.reset_bottom_data::(&bottom_delegations); + self.delegation_count = self.delegation_count.saturating_sub(1u32); + >::insert(candidate, bottom_delegations); + Ok(false) + } + /// Increase delegation amount + pub fn increase_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { + // definitely in top + self.increase_top_delegation::(candidate, delegator, more) + } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { + // update top but if error then update bottom (because could be in bottom because + // lowest_top_eq_highest_bottom) + let result = self.increase_top_delegation::(candidate, delegator.clone(), more); + if result == Err(delegation_dne_err) { + self.increase_bottom_delegation::(candidate, delegator, bond, more) + } else { + result + } + } else { + self.increase_bottom_delegation::(candidate, delegator, bond, more) + } + } + /// Increase top delegation + pub fn increase_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); + let mut in_top = false; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_top = true; + let new_amount = d.amount.saturating_add(more); + Bond { owner: d.owner, amount: new_amount } + } + }) + .collect(); + ensure!(in_top, Error::::DelegationDNE); + top_delegations.total = top_delegations.total.saturating_add(more); + top_delegations.sort_greatest_to_least(); + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + Ok(true) + } + /// Increase bottom delegation + pub fn increase_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let mut bottom_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; + let mut delegation_option: Option>> = None; + let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount + { + // bump it from bottom + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_add(more), + }); + false + } + }) + .collect(); + let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; + bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); + // add it to top + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); + // if top is full, pop lowest top + if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { + // pop lowest top delegation + let new_bottom_delegation = top_delegations + .delegations + .pop() + .expect("Top capacity full => Exists at least 1 top delegation"); + top_delegations.total = + top_delegations.total.saturating_sub(new_bottom_delegation.amount); + bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); + } + // insert into top + top_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + true + } else { + let mut in_bottom = false; + // just increase the delegation + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_bottom = true; + Bond { owner: d.owner, amount: d.amount.saturating_add(more) } + } + }) + .collect(); + ensure!(in_bottom, Error::::DelegationDNE); + bottom_delegations.total = bottom_delegations.total.saturating_add(more); + bottom_delegations.sort_greatest_to_least(); + false + }; + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + Ok(in_top_after) + } + /// Decrease delegation + pub fn decrease_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: Balance, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { + // definitely in top + self.decrease_top_delegation::(candidate, delegator, bond.into(), less) + } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { + // update top but if error then update bottom (because could be in bottom because + // lowest_top_eq_highest_bottom) + let result = + self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); + if result == Err(delegation_dne_err) { + self.decrease_bottom_delegation::(candidate, delegator, less) + } else { + result + } + } else { + self.decrease_bottom_delegation::(candidate, delegator, less) + } + } + /// Decrease top delegation + pub fn decrease_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + // The delegation after the `decrease-delegation` will be strictly less than the + // highest bottom delegation + let bond_after_less_than_highest_bottom = + bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; + // The top delegations is full and the bottom delegations has at least one delegation + let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) + && !matches!(self.bottom_capacity, CapacityStatus::Empty); + let mut top_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; + let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { + let mut delegation_option: Option>> = None; + // take delegation from top + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + top_delegations.total = top_delegations.total.saturating_sub(d.amount); + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_sub(less), + }); + false + } + }) + .collect(); + let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; + // pop highest bottom by reverse and popping + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); + let highest_bottom_delegation = bottom_delegations.delegations.remove(0); + bottom_delegations.total = + bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + // insert highest bottom into top + top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); + // insert previous top into bottom + bottom_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + false + } else { + // keep it in the top + let mut is_in_top = false; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + is_in_top = true; + Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } + } + }) + .collect(); + ensure!(is_in_top, Error::::DelegationDNE); + top_delegations.total = top_delegations.total.saturating_sub(less); + top_delegations.sort_greatest_to_least(); + true + }; + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + Ok(in_top_after) + } + /// Decrease bottom delegation + pub fn decrease_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into, + { + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); + let mut in_bottom = false; + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_bottom = true; + Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } + } + }) + .collect(); + ensure!(in_bottom, Error::::DelegationDNE); + bottom_delegations.sort_greatest_to_least(); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + Ok(false) + } } // Temporary manual implementation for migration testing purposes impl PartialEq for CollatorCandidate { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.id == other.id - && self.bond == other.bond - && self.total_counted == other.total_counted - && self.total_backing == other.total_backing - && self.request == other.request - && self.state == other.state; - if !must_be_true { - return false; - } - for (x, y) in self.delegators.0.iter().zip(other.delegators.0.iter()) { - if x != y { - return false; - } - } - for ( - Bond { - owner: o1, - amount: a1, - }, - Bond { - owner: o2, - amount: a2, - }, - ) in self - .top_delegations - .iter() - .zip(other.top_delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - for ( - Bond { - owner: o1, - amount: a1, - }, - Bond { - owner: o2, - amount: a2, - }, - ) in self - .bottom_delegations - .iter() - .zip(other.bottom_delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - true - } + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.id == other.id + && self.bond == other.bond + && self.total_counted == other.total_counted + && self.total_backing == other.total_backing + && self.request == other.request + && self.state == other.state; + if !must_be_true { + return false; + } + for (x, y) in self.delegators.0.iter().zip(other.delegators.0.iter()) { + if x != y { + return false; + } + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.top_delegations.iter().zip(other.top_delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.bottom_delegations.iter().zip(other.bottom_delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + true + } } /// Convey relevant information describing if a delegator was added to the top or bottom /// Delegations added to the top yield a new total -#[derive(Clone, Copy, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum DelegatorAdded { - AddedToTop { new_total: B }, - AddedToBottom, + AddedToTop { new_total: B }, + AddedToBottom, } impl< - A: Ord + Clone + sp_std::fmt::Debug, - B: AtLeast32BitUnsigned - + Ord - + Copy - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::fmt::Debug, - > CollatorCandidate + A: Ord + Clone + sp_std::fmt::Debug, + B: AtLeast32BitUnsigned + + Ord + + Copy + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::fmt::Debug, +> CollatorCandidate { - pub fn is_active(&self) -> bool { - self.state == CollatorStatus::Active - } + pub fn is_active(&self) -> bool { + self.state == CollatorStatus::Active + } } impl From> for CollatorSnapshot { - fn from(other: CollatorCandidate) -> CollatorSnapshot { - CollatorSnapshot { - bond: other.bond, - delegations: other - .top_delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner, - amount: d.amount, - auto_compound: Percent::zero(), - }) - .collect(), - total: other.total_counted, - } - } + fn from(other: CollatorCandidate) -> CollatorSnapshot { + CollatorSnapshot { + bond: other.bond, + delegations: other + .top_delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner, + amount: d.amount, + auto_compound: Percent::zero(), + }) + .collect(), + total: other.total_counted, + } + } } #[allow(deprecated)] -#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum DelegatorStatus { - /// Active with no scheduled exit - Active, - /// Schedule exit to revoke all ongoing delegations - #[deprecated(note = "must only be used for backwards compatibility reasons")] - Leaving(RoundIndex), + /// Active with no scheduled exit + Active, + /// Schedule exit to revoke all ongoing delegations + #[deprecated(note = "must only be used for backwards compatibility reasons")] + Leaving(RoundIndex), } #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] /// Delegator state pub struct Delegator { - /// Delegator account - pub id: AccountId, - /// All current delegations - pub delegations: OrderedSet>, - /// Total balance locked for this delegator - pub total: Balance, - /// Sum of pending revocation amounts + bond less amounts - pub less_total: Balance, - /// Status for this delegator - pub status: DelegatorStatus, + /// Delegator account + pub id: AccountId, + /// All current delegations + pub delegations: OrderedSet>, + /// Total balance locked for this delegator + pub total: Balance, + /// Sum of pending revocation amounts + bond less amounts + pub less_total: Balance, + /// Status for this delegator + pub status: DelegatorStatus, } // Temporary manual implementation for migration testing purposes impl PartialEq for Delegator { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.id == other.id - && self.total == other.total - && self.less_total == other.less_total - && self.status == other.status; - if !must_be_true { - return false; - } - for ( - Bond { - owner: o1, - amount: a1, - }, - Bond { - owner: o2, - amount: a2, - }, - ) in self.delegations.0.iter().zip(other.delegations.0.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - true - } + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.id == other.id + && self.total == other.total + && self.less_total == other.less_total + && self.status == other.status; + if !must_be_true { + return false; + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.delegations.0.iter().zip(other.delegations.0.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + true + } } impl< - AccountId: Ord + Clone, - Balance: Copy - + sp_std::ops::AddAssign - + sp_std::ops::Add - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + Ord - + Zero - + Default - + Saturating, - > Delegator + AccountId: Ord + Clone, + Balance: Copy + + sp_std::ops::AddAssign + + sp_std::ops::Add + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + Ord + + Zero + + Default + + Saturating, +> Delegator { - pub fn new(id: AccountId, collator: AccountId, amount: Balance) -> Self { - Delegator { - id, - delegations: OrderedSet::from(vec![Bond { - owner: collator, - amount, - }]), - total: amount, - less_total: Balance::zero(), - status: DelegatorStatus::Active, - } - } - - pub fn default_with_total(id: AccountId, amount: Balance) -> Self { - Delegator { - id, - total: amount, - delegations: OrderedSet::from(vec![]), - less_total: Balance::zero(), - status: DelegatorStatus::Active, - } - } - - pub fn total(&self) -> Balance { - self.total - } - - pub fn total_sub_if(&mut self, amount: Balance, check: F) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - F: Fn(Balance) -> DispatchResult, - { - let total = self.total.saturating_sub(amount); - check(total)?; - self.total = total; - self.adjust_bond_lock::(BondAdjust::Decrease)?; - Ok(()) - } - - pub fn total_add(&mut self, amount: Balance) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - { - self.total = self.total.saturating_add(amount); - self.adjust_bond_lock::(BondAdjust::Increase(amount))?; - Ok(()) - } - - pub fn total_sub(&mut self, amount: Balance) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - { - self.total = self.total.saturating_sub(amount); - self.adjust_bond_lock::(BondAdjust::Decrease)?; - Ok(()) - } - - pub fn is_active(&self) -> bool { - matches!(self.status, DelegatorStatus::Active) - } - - pub fn add_delegation(&mut self, bond: Bond) -> bool { - let amt = bond.amount; - if self.delegations.insert(bond) { - self.total = self.total.saturating_add(amt); - true - } else { - false - } - } - // Return Some(remaining balance), must be more than MinDelegatorStk - // Return None if delegation not found - pub fn rm_delegation(&mut self, collator: &AccountId) -> Option - where - BalanceOf: From, - T::AccountId: From, - { - let mut amt: Option = None; - let delegations = self - .delegations - .0 - .iter() - .filter_map(|x| { - if &x.owner == collator { - amt = Some(x.amount); - None - } else { - Some(x.clone()) - } - }) - .collect(); - if let Some(balance) = amt { - self.delegations = OrderedSet::from(delegations); - self.total_sub::(balance) - .expect("Decreasing lock cannot fail, qed"); - Some(self.total) - } else { - None - } - } - - /// Increases the delegation amount and returns `true` if the delegation is part of the - /// TopDelegations set, `false` otherwise. - pub fn increase_delegation( - &mut self, - candidate: AccountId, - amount: Balance, - ) -> Result - where - BalanceOf: From, - T::AccountId: From, - Delegator>: From>, - { - let delegator_id: T::AccountId = self.id.clone().into(); - let candidate_id: T::AccountId = candidate.clone().into(); - let balance_amt: BalanceOf = amount.into(); - // increase delegation - for x in &mut self.delegations.0 { - if x.owner == candidate { - let before_amount: BalanceOf = x.amount.into(); - x.amount = x.amount.saturating_add(amount); - self.total = self.total.saturating_add(amount); - self.adjust_bond_lock::(BondAdjust::Increase(amount))?; - - // update collator state delegation - let mut collator_state = - >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; - let before = collator_state.total_counted; - let in_top = collator_state.increase_delegation::( - &candidate_id, - delegator_id.clone(), - before_amount, - balance_amt, - )?; - let after = collator_state.total_counted; - if collator_state.is_active() && (before != after) { - Pallet::::update_active(candidate_id.clone(), after); - } - >::insert(&candidate_id, collator_state); - let new_total_staked = >::get().saturating_add(balance_amt); - >::put(new_total_staked); - let nom_st: Delegator> = self.clone().into(); - >::insert(&delegator_id, nom_st); - return Ok(in_top); - } - } - Err(Error::::DelegationDNE.into()) - } - - /// Updates the bond locks for this delegator. - /// - /// This will take the current self.total and ensure that a lock of the same amount is applied - /// and when increasing the bond lock will also ensure that the account has enough free balance. - /// - /// `additional_required_balance` should reflect the change to the amount that should be locked if - /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is - /// not possible to query the amount that is locked for a given lock id. - pub fn adjust_bond_lock( - &mut self, - additional_required_balance: BondAdjust, - ) -> DispatchResult - where - BalanceOf: From, - T::AccountId: From, - { - match additional_required_balance { - BondAdjust::Increase(amount) => { - ensure!( - >::get_delegator_stakable_free_balance(&self.id.clone().into()) - >= amount.into(), - Error::::InsufficientBalance, - ); - - // additional sanity check: shouldn't ever want to lock more than total - if amount > self.total { - log::warn!("LOGIC ERROR: request to reserve more than bond total"); - return Err(DispatchError::Other("Invalid additional_required_balance")); - } - } - BondAdjust::Decrease => (), // do nothing on decrease - }; - - if self.total.is_zero() { - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &self.id.clone().into()); - } else { - T::Currency::set_lock( - DELEGATOR_LOCK_ID, - &self.id.clone().into(), - self.total.into(), - WithdrawReasons::all(), - ); - } - Ok(()) - } - - /// Retrieves the bond amount that a delegator has provided towards a collator. - /// Returns `None` if missing. - pub fn get_bond_amount(&self, collator: &AccountId) -> Option { - self.delegations - .0 - .iter() - .find(|b| &b.owner == collator) - .map(|b| b.amount) - } + pub fn new(id: AccountId, collator: AccountId, amount: Balance) -> Self { + Delegator { + id, + delegations: OrderedSet::from(vec![Bond { owner: collator, amount }]), + total: amount, + less_total: Balance::zero(), + status: DelegatorStatus::Active, + } + } + + pub fn default_with_total(id: AccountId, amount: Balance) -> Self { + Delegator { + id, + total: amount, + delegations: OrderedSet::from(vec![]), + less_total: Balance::zero(), + status: DelegatorStatus::Active, + } + } + + pub fn total(&self) -> Balance { + self.total + } + + pub fn total_sub_if(&mut self, amount: Balance, check: F) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + F: Fn(Balance) -> DispatchResult, + { + let total = self.total.saturating_sub(amount); + check(total)?; + self.total = total; + self.adjust_bond_lock::(BondAdjust::Decrease)?; + Ok(()) + } + + pub fn total_add(&mut self, amount: Balance) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + { + self.total = self.total.saturating_add(amount); + self.adjust_bond_lock::(BondAdjust::Increase(amount))?; + Ok(()) + } + + pub fn total_sub(&mut self, amount: Balance) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + { + self.total = self.total.saturating_sub(amount); + self.adjust_bond_lock::(BondAdjust::Decrease)?; + Ok(()) + } + + pub fn is_active(&self) -> bool { + matches!(self.status, DelegatorStatus::Active) + } + + pub fn add_delegation(&mut self, bond: Bond) -> bool { + let amt = bond.amount; + if self.delegations.insert(bond) { + self.total = self.total.saturating_add(amt); + true + } else { + false + } + } + // Return Some(remaining balance), must be more than MinDelegatorStk + // Return None if delegation not found + pub fn rm_delegation(&mut self, collator: &AccountId) -> Option + where + BalanceOf: From, + T::AccountId: From, + { + let mut amt: Option = None; + let delegations = self + .delegations + .0 + .iter() + .filter_map(|x| { + if &x.owner == collator { + amt = Some(x.amount); + None + } else { + Some(x.clone()) + } + }) + .collect(); + if let Some(balance) = amt { + self.delegations = OrderedSet::from(delegations); + self.total_sub::(balance).expect("Decreasing lock cannot fail, qed"); + Some(self.total) + } else { + None + } + } + + /// Increases the delegation amount and returns `true` if the delegation is part of the + /// TopDelegations set, `false` otherwise. + pub fn increase_delegation( + &mut self, + candidate: AccountId, + amount: Balance, + ) -> Result + where + BalanceOf: From, + T::AccountId: From, + Delegator>: From>, + { + let delegator_id: T::AccountId = self.id.clone().into(); + let candidate_id: T::AccountId = candidate.clone().into(); + let balance_amt: BalanceOf = amount.into(); + // increase delegation + for x in &mut self.delegations.0 { + if x.owner == candidate { + let before_amount: BalanceOf = x.amount.into(); + x.amount = x.amount.saturating_add(amount); + self.total = self.total.saturating_add(amount); + self.adjust_bond_lock::(BondAdjust::Increase(amount))?; + + // update collator state delegation + let mut collator_state = + >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; + let before = collator_state.total_counted; + let in_top = collator_state.increase_delegation::( + &candidate_id, + delegator_id.clone(), + before_amount, + balance_amt, + )?; + let after = collator_state.total_counted; + if collator_state.is_active() && (before != after) { + Pallet::::update_active(candidate_id.clone(), after); + } + >::insert(&candidate_id, collator_state); + let new_total_staked = >::get().saturating_add(balance_amt); + >::put(new_total_staked); + let nom_st: Delegator> = self.clone().into(); + >::insert(&delegator_id, nom_st); + return Ok(in_top); + } + } + Err(Error::::DelegationDNE.into()) + } + + /// Updates the bond locks for this delegator. + /// + /// This will take the current self.total and ensure that a lock of the same amount is applied + /// and when increasing the bond lock will also ensure that the account has enough free balance. + /// + /// `additional_required_balance` should reflect the change to the amount that should be locked if + /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is + /// not possible to query the amount that is locked for a given lock id. + pub fn adjust_bond_lock( + &mut self, + additional_required_balance: BondAdjust, + ) -> DispatchResult + where + BalanceOf: From, + T::AccountId: From, + { + match additional_required_balance { + BondAdjust::Increase(amount) => { + ensure!( + >::get_delegator_stakable_free_balance(&self.id.clone().into()) + >= amount.into(), + Error::::InsufficientBalance, + ); + + // additional sanity check: shouldn't ever want to lock more than total + if amount > self.total { + log::warn!("LOGIC ERROR: request to reserve more than bond total"); + return Err(DispatchError::Other("Invalid additional_required_balance")); + } + } + BondAdjust::Decrease => (), // do nothing on decrease + }; + + if self.total.is_zero() { + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &self.id.clone().into()); + } else { + T::Currency::set_lock( + DELEGATOR_LOCK_ID, + &self.id.clone().into(), + self.total.into(), + WithdrawReasons::all(), + ); + } + Ok(()) + } + + /// Retrieves the bond amount that a delegator has provided towards a collator. + /// Returns `None` if missing. + pub fn get_bond_amount(&self, collator: &AccountId) -> Option { + self.delegations.0.iter().find(|b| &b.owner == collator).map(|b| b.amount) + } } pub mod deprecated { - #![allow(deprecated)] - - use super::*; - - #[deprecated(note = "use DelegationAction")] - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - /// Changes requested by the delegator - /// - limit of 1 ongoing change per delegation - pub enum DelegationChange { - Revoke, - Decrease, - } - - #[deprecated(note = "use ScheduledRequest")] - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - pub struct DelegationRequest { - pub collator: AccountId, - pub amount: Balance, - pub when_executable: RoundIndex, - pub action: DelegationChange, - } - - #[deprecated(note = "use DelegationScheduledRequests storage item")] - #[derive(Clone, Encode, PartialEq, Decode, RuntimeDebug, TypeInfo)] - /// Pending requests to mutate delegations for each delegator - pub struct PendingDelegationRequests { - /// Number of pending revocations (necessary for determining whether revoke is exit) - pub revocations_count: u32, - /// Map from collator -> Request (enforces at most 1 pending request per delegation) - pub requests: BTreeMap>, - /// Sum of pending revocation amounts + bond less amounts - pub less_total: Balance, - } - - impl Default for PendingDelegationRequests { - fn default() -> PendingDelegationRequests { - PendingDelegationRequests { - revocations_count: 0u32, - requests: BTreeMap::new(), - less_total: B::zero(), - } - } - } - - impl< - A: Ord + Clone, - B: Zero - + Ord - + Copy - + Clone - + sp_std::ops::AddAssign - + sp_std::ops::Add - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + Saturating, - > PendingDelegationRequests - { - /// New default (empty) pending requests - pub fn new() -> Self { - Self::default() - } - } - - #[deprecated(note = "use new crate::types::Delegator struct")] - #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] - /// Delegator state - pub struct Delegator { - /// Delegator account - pub id: AccountId, - /// All current delegations - pub delegations: OrderedSet>, - /// Total balance locked for this delegator - pub total: Balance, - /// Requests to change delegations, relevant iff active - pub requests: PendingDelegationRequests, - /// Status for this delegator - pub status: DelegatorStatus, - } - - // CollatorSnapshot - - #[deprecated(note = "use CollatorSnapshot with BondWithAutoCompound delegations")] - #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] - /// Snapshot of collator state at the start of the round for which they are selected - pub struct CollatorSnapshot { - /// The total value locked by the collator. - pub bond: Balance, - - /// The rewardable delegations. This list is a subset of total delegators, where certain - /// delegators are adjusted based on their scheduled - /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. - pub delegations: Vec>, - - /// The total counted value locked for the collator, including the self bond + total staked by - /// top delegators. - pub total: Balance, - } - - impl PartialEq for CollatorSnapshot { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.bond == other.bond && self.total == other.total; - if !must_be_true { - return false; - } - for ( - Bond { - owner: o1, - amount: a1, - }, - Bond { - owner: o2, - amount: a2, - }, - ) in self.delegations.iter().zip(other.delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - true - } - } - - impl Default for CollatorSnapshot { - fn default() -> CollatorSnapshot { - CollatorSnapshot { - bond: B::default(), - delegations: Vec::new(), - total: B::default(), - } - } - } + #![allow(deprecated)] + + use super::*; + + #[deprecated(note = "use DelegationAction")] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] + /// Changes requested by the delegator + /// - limit of 1 ongoing change per delegation + pub enum DelegationChange { + Revoke, + Decrease, + } + + #[deprecated(note = "use ScheduledRequest")] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] + pub struct DelegationRequest { + pub collator: AccountId, + pub amount: Balance, + pub when_executable: RoundIndex, + pub action: DelegationChange, + } + + #[deprecated(note = "use DelegationScheduledRequests storage item")] + #[derive(Clone, Encode, PartialEq, Eq, Decode, RuntimeDebug, TypeInfo)] + /// Pending requests to mutate delegations for each delegator + pub struct PendingDelegationRequests { + /// Number of pending revocations (necessary for determining whether revoke is exit) + pub revocations_count: u32, + /// Map from collator -> Request (enforces at most 1 pending request per delegation) + pub requests: BTreeMap>, + /// Sum of pending revocation amounts + bond less amounts + pub less_total: Balance, + } + + impl Default for PendingDelegationRequests { + fn default() -> PendingDelegationRequests { + PendingDelegationRequests { + revocations_count: 0u32, + requests: BTreeMap::new(), + less_total: B::zero(), + } + } + } + + impl< + A: Ord + Clone, + B: Zero + + Ord + + Copy + + Clone + + sp_std::ops::AddAssign + + sp_std::ops::Add + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + Saturating, + > PendingDelegationRequests + { + /// New default (empty) pending requests + pub fn new() -> Self { + Self::default() + } + } + + #[deprecated(note = "use new crate::types::Delegator struct")] + #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] + /// Delegator state + pub struct Delegator { + /// Delegator account + pub id: AccountId, + /// All current delegations + pub delegations: OrderedSet>, + /// Total balance locked for this delegator + pub total: Balance, + /// Requests to change delegations, relevant iff active + pub requests: PendingDelegationRequests, + /// Status for this delegator + pub status: DelegatorStatus, + } + + // CollatorSnapshot + + #[deprecated(note = "use CollatorSnapshot with BondWithAutoCompound delegations")] + #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] + /// Snapshot of collator state at the start of the round for which they are selected + pub struct CollatorSnapshot { + /// The total value locked by the collator. + pub bond: Balance, + + /// The rewardable delegations. This list is a subset of total delegators, where certain + /// delegators are adjusted based on their scheduled + /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. + pub delegations: Vec>, + + /// The total counted value locked for the collator, including the self bond + total staked by + /// top delegators. + pub total: Balance, + } + + impl PartialEq for CollatorSnapshot { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.bond == other.bond && self.total == other.total; + if !must_be_true { + return false; + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.delegations.iter().zip(other.delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false; + } + } + true + } + } + + impl Default for CollatorSnapshot { + fn default() -> CollatorSnapshot { + CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } + } + } } #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] /// DEPRECATED in favor of Delegator /// Nominator state pub struct Nominator2 { - /// All current delegations - pub delegations: OrderedSet>, - /// Delegations scheduled to be revoked - pub revocations: OrderedSet, - /// Total balance locked for this nominator - pub total: Balance, - /// Total number of revocations scheduled to be executed - pub scheduled_revocations_count: u32, - /// Total amount to be unbonded once revocations are executed - pub scheduled_revocations_total: Balance, - /// Status for this nominator - pub status: DelegatorStatus, + /// All current delegations + pub delegations: OrderedSet>, + /// Delegations scheduled to be revoked + pub revocations: OrderedSet, + /// Total balance locked for this nominator + pub total: Balance, + /// Total number of revocations scheduled to be executed + pub scheduled_revocations_count: u32, + /// Total amount to be unbonded once revocations are executed + pub scheduled_revocations_total: Balance, + /// Status for this nominator + pub status: DelegatorStatus, } // /// Temporary function to migrate state // pub(crate) fn migrate_nominator_to_delegator_state( -// id: T::AccountId, -// nominator: Nominator2>, +// id: T::AccountId, +// nominator: Nominator2>, // ) -> Delegator> { -// Delegator { -// id, -// delegations: nominator.delegations, -// total: nominator.total, -// requests: PendingDelegationRequests::new(), -// status: nominator.status, -// } +// Delegator { +// id, +// delegations: nominator.delegations, +// total: nominator.total, +// requests: PendingDelegationRequests::new(), +// status: nominator.status, +// } // } #[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] /// The current round index and transition information pub struct RoundInfo { - /// Current round index - pub current: RoundIndex, - /// The first block of the current round - pub first: BlockNumber, - /// The length of the current round in number of blocks - pub length: u32, + /// Current round index + pub current: RoundIndex, + /// The first block of the current round + pub first: BlockNumber, + /// The length of the current round in number of blocks + pub length: u32, } -impl< - B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, - > RoundInfo +impl + sp_std::ops::Sub + From + PartialOrd> + RoundInfo { - pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { - RoundInfo { - current, - first, - length, - } - } - /// Check if the round should be updated - pub fn should_update(&self, now: B) -> bool { - now - self.first >= self.length.into() - } - /// New round - pub fn update(&mut self, now: B) { - self.current = self.current.saturating_add(1u32); - self.first = now; - } + pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { + RoundInfo { current, first, length } + } + /// Check if the round should be updated + pub fn should_update(&self, now: B) -> bool { + now - self.first >= self.length.into() + } + /// New round + pub fn update(&mut self, now: B) { + self.current = self.current.saturating_add(1u32); + self.first = now; + } } -impl< - B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, - > Default for RoundInfo +impl + sp_std::ops::Sub + From + PartialOrd> + Default for RoundInfo { - fn default() -> RoundInfo { - RoundInfo::new(1u32, 1u32.into(), 20u32) - } + fn default() -> RoundInfo { + RoundInfo::new(1u32, 1u32.into(), 20u32) + } } #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] /// Reserve information { account, percent_of_inflation } pub struct ParachainBondConfig { - /// Account which receives funds intended for parachain bond - pub account: AccountId, - /// Percent of inflation set aside for parachain bond account - pub percent: Percent, + /// Account which receives funds intended for parachain bond + pub account: AccountId, + /// Percent of inflation set aside for parachain bond account + pub percent: Percent, } impl Default for ParachainBondConfig { - fn default() -> ParachainBondConfig { - ParachainBondConfig { - account: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - percent: Percent::zero(), - } - } + fn default() -> ParachainBondConfig { + ParachainBondConfig { + account: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + percent: Percent::zero(), + } + } } pub enum BondAdjust { - Increase(Balance), - Decrease, + Increase(Balance), + Decrease, } diff --git a/external/pallets/parachain-staking/src/weights.rs b/external/pallets/parachain-staking/src/weights.rs index 01c070a18..60ac48da0 100644 --- a/external/pallets/parachain-staking/src/weights.rs +++ b/external/pallets/parachain-staking/src/weights.rs @@ -44,860 +44,860 @@ #![allow(unused_imports)] use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, + traits::Get, + weights::{constants::RocksDbWeight, Weight}, }; use sp_std::marker::PhantomData; /// Weight functions needed for parachain_staking. pub trait WeightInfo { - #[rustfmt::skip] - fn set_staking_expectations() -> Weight; - #[rustfmt::skip] - fn set_inflation() -> Weight; - #[rustfmt::skip] - fn set_parachain_bond_account() -> Weight; - #[rustfmt::skip] - fn set_parachain_bond_reserve_percent() -> Weight; - #[rustfmt::skip] - fn set_total_selected() -> Weight; - #[rustfmt::skip] - fn set_collator_commission() -> Weight; - #[rustfmt::skip] - fn set_blocks_per_round() -> Weight; - #[rustfmt::skip] - fn join_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn schedule_leave_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn execute_leave_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn cancel_leave_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn go_offline() -> Weight; - #[rustfmt::skip] - fn go_online() -> Weight; - #[rustfmt::skip] - fn candidate_bond_more() -> Weight; - #[rustfmt::skip] - fn schedule_candidate_bond_less() -> Weight; - #[rustfmt::skip] - fn execute_candidate_bond_less() -> Weight; - #[rustfmt::skip] - fn cancel_candidate_bond_less() -> Weight; - #[rustfmt::skip] - fn delegate(x: u32, y: u32, ) -> Weight; - #[rustfmt::skip] - fn schedule_leave_delegators() -> Weight; - #[rustfmt::skip] - fn execute_leave_delegators(x: u32, ) -> Weight; - #[rustfmt::skip] - fn cancel_leave_delegators() -> Weight; - #[rustfmt::skip] - fn schedule_revoke_delegation() -> Weight; - #[rustfmt::skip] - fn delegator_bond_more() -> Weight; - #[rustfmt::skip] - fn schedule_delegator_bond_less() -> Weight; - #[rustfmt::skip] - fn execute_revoke_delegation() -> Weight; - #[rustfmt::skip] - fn execute_delegator_bond_less() -> Weight; - #[rustfmt::skip] - fn cancel_revoke_delegation() -> Weight; - #[rustfmt::skip] - fn cancel_delegator_bond_less() -> Weight; - #[rustfmt::skip] - fn prepare_staking_payouts() -> Weight; - #[rustfmt::skip] - fn get_rewardable_delegators(y: u32, ) -> Weight; - #[rustfmt::skip] - fn select_top_candidates(x: u32, y: u32, ) -> Weight; - #[rustfmt::skip] - fn pay_one_collator_reward(y: u32, ) -> Weight; - #[rustfmt::skip] - fn base_on_initialize() -> Weight; - #[rustfmt::skip] - fn set_auto_compound(x: u32, y: u32, ) -> Weight; - #[rustfmt::skip] - fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight; - #[rustfmt::skip] - fn mint_collator_reward() -> Weight; + #[rustfmt::skip] + fn set_staking_expectations() -> Weight; + #[rustfmt::skip] + fn set_inflation() -> Weight; + #[rustfmt::skip] + fn set_parachain_bond_account() -> Weight; + #[rustfmt::skip] + fn set_parachain_bond_reserve_percent() -> Weight; + #[rustfmt::skip] + fn set_total_selected() -> Weight; + #[rustfmt::skip] + fn set_collator_commission() -> Weight; + #[rustfmt::skip] + fn set_blocks_per_round() -> Weight; + #[rustfmt::skip] + fn join_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn schedule_leave_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn execute_leave_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn cancel_leave_candidates(x: u32, ) -> Weight; + #[rustfmt::skip] + fn go_offline() -> Weight; + #[rustfmt::skip] + fn go_online() -> Weight; + #[rustfmt::skip] + fn candidate_bond_more() -> Weight; + #[rustfmt::skip] + fn schedule_candidate_bond_less() -> Weight; + #[rustfmt::skip] + fn execute_candidate_bond_less() -> Weight; + #[rustfmt::skip] + fn cancel_candidate_bond_less() -> Weight; + #[rustfmt::skip] + fn delegate(x: u32, y: u32, ) -> Weight; + #[rustfmt::skip] + fn schedule_leave_delegators() -> Weight; + #[rustfmt::skip] + fn execute_leave_delegators(x: u32, ) -> Weight; + #[rustfmt::skip] + fn cancel_leave_delegators() -> Weight; + #[rustfmt::skip] + fn schedule_revoke_delegation() -> Weight; + #[rustfmt::skip] + fn delegator_bond_more() -> Weight; + #[rustfmt::skip] + fn schedule_delegator_bond_less() -> Weight; + #[rustfmt::skip] + fn execute_revoke_delegation() -> Weight; + #[rustfmt::skip] + fn execute_delegator_bond_less() -> Weight; + #[rustfmt::skip] + fn cancel_revoke_delegation() -> Weight; + #[rustfmt::skip] + fn cancel_delegator_bond_less() -> Weight; + #[rustfmt::skip] + fn prepare_staking_payouts() -> Weight; + #[rustfmt::skip] + fn get_rewardable_delegators(y: u32, ) -> Weight; + #[rustfmt::skip] + fn select_top_candidates(x: u32, y: u32, ) -> Weight; + #[rustfmt::skip] + fn pay_one_collator_reward(y: u32, ) -> Weight; + #[rustfmt::skip] + fn base_on_initialize() -> Weight; + #[rustfmt::skip] + fn set_auto_compound(x: u32, y: u32, ) -> Weight; + #[rustfmt::skip] + fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight; + #[rustfmt::skip] + fn mint_collator_reward() -> Weight; } /// Weights for parachain_staking using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_staking_expectations() -> Weight { - Weight::from_ref_time(48_225_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_inflation() -> Weight { - Weight::from_ref_time(61_063_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_account() -> Weight { - Weight::from_ref_time(27_645_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_reserve_percent() -> Weight { - Weight::from_ref_time(26_922_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:1) - #[rustfmt::skip] - fn set_total_selected() -> Weight { - Weight::from_ref_time(29_263_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CollatorCommission (r:1 w:1) - #[rustfmt::skip] - fn set_collator_commission() -> Weight { - Weight::from_ref_time(25_867_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(66_047_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:0 w:1) - // Storage: ParachainStaking BottomDelegations (r:0 w:1) - #[rustfmt::skip] - fn join_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(93_609_702 as u64) - // Standard Error: 1_049 - .saturating_add(Weight::from_ref_time(156_227 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(74_938_974 as u64) - // Standard Error: 1_813 - .saturating_add(Weight::from_ref_time(136_560 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: Balances Locks (r:2 w:2) - // Storage: System Account (r:2 w:2) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(120_885_000 as u64) - // Standard Error: 73_687 - .saturating_add(Weight::from_ref_time(31_457_020 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(5 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(70_048_572 as u64) - // Standard Error: 1_524 - .saturating_add(Weight::from_ref_time(145_661 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_offline() -> Weight { - Weight::from_ref_time(42_412_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_online() -> Weight { - Weight::from_ref_time(41_744_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn candidate_bond_more() -> Weight { - Weight::from_ref_time(68_900_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn schedule_candidate_bond_less() -> Weight { - Weight::from_ref_time(38_239_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn execute_candidate_bond_less() -> Weight { - Weight::from_ref_time(76_166_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn cancel_candidate_bond_less() -> Weight { - Weight::from_ref_time(35_581_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegate(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(131_245_351 as u64) - // Standard Error: 19_323 - .saturating_add(Weight::from_ref_time(239_400 as u64).saturating_mul(x as u64)) - // Standard Error: 6_339 - .saturating_add(Weight::from_ref_time(261_836 as u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_delegators() -> Weight { - Weight::from_ref_time(44_609_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_delegators(x: u32, ) -> Weight { - Weight::from_ref_time(14_022_061 as u64) - // Standard Error: 30_972 - .saturating_add(Weight::from_ref_time(29_549_278 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_delegators() -> Weight { - Weight::from_ref_time(44_825_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_revoke_delegation() -> Weight { - Weight::from_ref_time(43_131_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegator_bond_more() -> Weight { - Weight::from_ref_time(90_452_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_delegator_bond_less() -> Weight { - Weight::from_ref_time(43_388_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_revoke_delegation() -> Weight { - Weight::from_ref_time(112_401_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_delegator_bond_less() -> Weight { - Weight::from_ref_time(97_377_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_revoke_delegation() -> Weight { - Weight::from_ref_time(43_406_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_delegator_bond_less() -> Weight { - Weight::from_ref_time(49_020_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking Staked (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CollatorCommission (r:1 w:0) - // Storage: ParachainStaking DelayedPayouts (r:0 w:1) - #[rustfmt::skip] - fn prepare_staking_payouts() -> Weight { - Weight::from_ref_time(59_628_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - #[rustfmt::skip] - fn get_rewardable_delegators(y: u32, ) -> Weight { - Weight::from_ref_time(16_322_694 as u64) - // Standard Error: 1_133 - .saturating_add(Weight::from_ref_time(233_812 as u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:0) - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:0) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:0 w:1) - // Storage: ParachainStaking AtStake (r:0 w:1) - #[rustfmt::skip] - fn select_top_candidates(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(44_110_000 as u64) - // Standard Error: 237_049 - .saturating_add(Weight::from_ref_time(24_788_127 as u64).saturating_mul(x as u64)) - // Standard Error: 118_210 - .saturating_add(Weight::from_ref_time(2_957_731 as u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelayedPayouts (r:1 w:0) - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking AtStake (r:2 w:1) - // Storage: ParachainStaking AwardedPts (r:1 w:1) - // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn pay_one_collator_reward(y: u32, ) -> Weight { - Weight::from_ref_time(65_307_432 as u64) - // Standard Error: 9_596 - .saturating_add(Weight::from_ref_time(17_073_916 as u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(y as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(y as u64))) - } - #[rustfmt::skip] - fn base_on_initialize() -> Weight { - Weight::from_ref_time(10_890_000 as u64) - } - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - #[rustfmt::skip] - fn set_auto_compound(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(64_797_700 as u64) - // Standard Error: 5_810 - .saturating_add(Weight::from_ref_time(292_809 as u64).saturating_mul(x as u64)) - // Standard Error: 17_394 - .saturating_add(Weight::from_ref_time(258_382 as u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - #[rustfmt::skip] - fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { - Weight::from_ref_time(181_911_542 as u64) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(120_473 as u64).saturating_mul(x as u64)) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(80_638 as u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) - } - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn mint_collator_reward() -> Weight { - Weight::from_ref_time(40_146_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_staking_expectations() -> Weight { + Weight::from_ref_time(48_225_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_inflation() -> Weight { + Weight::from_ref_time(61_063_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_account() -> Weight { + Weight::from_ref_time(27_645_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_reserve_percent() -> Weight { + Weight::from_ref_time(26_922_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:1) + #[rustfmt::skip] + fn set_total_selected() -> Weight { + Weight::from_ref_time(29_263_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking CollatorCommission (r:1 w:1) + #[rustfmt::skip] + fn set_collator_commission() -> Weight { + Weight::from_ref_time(25_867_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_blocks_per_round() -> Weight { + Weight::from_ref_time(66_047_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:0 w:1) + // Storage: ParachainStaking BottomDelegations (r:0 w:1) + #[rustfmt::skip] + fn join_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(93_609_702_u64) + // Standard Error: 1_049 + .saturating_add(Weight::from_ref_time(156_227_u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(74_938_974_u64) + // Standard Error: 1_813 + .saturating_add(Weight::from_ref_time(136_560_u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: Balances Locks (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(120_885_000_u64) + // Standard Error: 73_687 + .saturating_add(Weight::from_ref_time(31_457_020_u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x as u64))) + .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(70_048_572_u64) + // Standard Error: 1_524 + .saturating_add(Weight::from_ref_time(145_661_u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_offline() -> Weight { + Weight::from_ref_time(42_412_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_online() -> Weight { + Weight::from_ref_time(41_744_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn candidate_bond_more() -> Weight { + Weight::from_ref_time(68_900_000_u64) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn schedule_candidate_bond_less() -> Weight { + Weight::from_ref_time(38_239_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn execute_candidate_bond_less() -> Weight { + Weight::from_ref_time(76_166_000_u64) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn cancel_candidate_bond_less() -> Weight { + Weight::from_ref_time(35_581_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegate(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(131_245_351_u64) + // Standard Error: 19_323 + .saturating_add(Weight::from_ref_time(239_400_u64).saturating_mul(x as u64)) + // Standard Error: 6_339 + .saturating_add(Weight::from_ref_time(261_836_u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_delegators() -> Weight { + Weight::from_ref_time(44_609_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_delegators(x: u32, ) -> Weight { + Weight::from_ref_time(14_022_061_u64) + // Standard Error: 30_972 + .saturating_add(Weight::from_ref_time(29_549_278_u64).saturating_mul(x as u64)) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x as u64))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_delegators() -> Weight { + Weight::from_ref_time(44_825_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_revoke_delegation() -> Weight { + Weight::from_ref_time(43_131_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegator_bond_more() -> Weight { + Weight::from_ref_time(90_452_000_u64) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_delegator_bond_less() -> Weight { + Weight::from_ref_time(43_388_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_revoke_delegation() -> Weight { + Weight::from_ref_time(112_401_000_u64) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_delegator_bond_less() -> Weight { + Weight::from_ref_time(97_377_000_u64) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_revoke_delegation() -> Weight { + Weight::from_ref_time(43_406_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_delegator_bond_less() -> Weight { + Weight::from_ref_time(49_020_000_u64) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking Staked (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CollatorCommission (r:1 w:0) + // Storage: ParachainStaking DelayedPayouts (r:0 w:1) + #[rustfmt::skip] + fn prepare_staking_payouts() -> Weight { + Weight::from_ref_time(59_628_000_u64) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + #[rustfmt::skip] + fn get_rewardable_delegators(y: u32, ) -> Weight { + Weight::from_ref_time(16_322_694_u64) + // Standard Error: 1_133 + .saturating_add(Weight::from_ref_time(233_812_u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:0) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:0 w:1) + // Storage: ParachainStaking AtStake (r:0 w:1) + #[rustfmt::skip] + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(44_110_000_u64) + // Standard Error: 237_049 + .saturating_add(Weight::from_ref_time(24_788_127_u64).saturating_mul(x as u64)) + // Standard Error: 118_210 + .saturating_add(Weight::from_ref_time(2_957_731_u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x as u64))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelayedPayouts (r:1 w:0) + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking AtStake (r:2 w:1) + // Storage: ParachainStaking AwardedPts (r:1 w:1) + // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn pay_one_collator_reward(y: u32, ) -> Weight { + Weight::from_ref_time(65_307_432_u64) + // Standard Error: 9_596 + .saturating_add(Weight::from_ref_time(17_073_916_u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y as u64))) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y as u64))) + } + #[rustfmt::skip] + fn base_on_initialize() -> Weight { + Weight::from_ref_time(10_890_000_u64) + } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + #[rustfmt::skip] + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(64_797_700_u64) + // Standard Error: 5_810 + .saturating_add(Weight::from_ref_time(292_809_u64).saturating_mul(x as u64)) + // Standard Error: 17_394 + .saturating_add(Weight::from_ref_time(258_382_u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + #[rustfmt::skip] + fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { + Weight::from_ref_time(181_911_542_u64) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(120_473_u64).saturating_mul(x as u64)) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(80_638_u64).saturating_mul(y as u64)) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn mint_collator_reward() -> Weight { + Weight::from_ref_time(40_146_000_u64) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests impl WeightInfo for () { - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_staking_expectations() -> Weight { - Weight::from_ref_time(48_225_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_inflation() -> Weight { - Weight::from_ref_time(61_063_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_account() -> Weight { - Weight::from_ref_time(27_645_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_reserve_percent() -> Weight { - Weight::from_ref_time(26_922_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:1) - #[rustfmt::skip] - fn set_total_selected() -> Weight { - Weight::from_ref_time(29_263_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CollatorCommission (r:1 w:1) - #[rustfmt::skip] - fn set_collator_commission() -> Weight { - Weight::from_ref_time(25_867_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(66_047_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:0 w:1) - // Storage: ParachainStaking BottomDelegations (r:0 w:1) - #[rustfmt::skip] - fn join_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(93_609_702 as u64) - // Standard Error: 1_049 - .saturating_add(Weight::from_ref_time(156_227 as u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(74_938_974 as u64) - // Standard Error: 1_813 - .saturating_add(Weight::from_ref_time(136_560 as u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: Balances Locks (r:2 w:2) - // Storage: System Account (r:2 w:2) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(120_885_000 as u64) - // Standard Error: 73_687 - .saturating_add(Weight::from_ref_time(31_457_020 as u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().reads((3 as u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(5 as u64)) - .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(70_048_572 as u64) - // Standard Error: 1_524 - .saturating_add(Weight::from_ref_time(145_661 as u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_offline() -> Weight { - Weight::from_ref_time(42_412_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_online() -> Weight { - Weight::from_ref_time(41_744_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn candidate_bond_more() -> Weight { - Weight::from_ref_time(68_900_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(5 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn schedule_candidate_bond_less() -> Weight { - Weight::from_ref_time(38_239_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn execute_candidate_bond_less() -> Weight { - Weight::from_ref_time(76_166_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(5 as u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn cancel_candidate_bond_less() -> Weight { - Weight::from_ref_time(35_581_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegate(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(131_245_351 as u64) - // Standard Error: 19_323 - .saturating_add(Weight::from_ref_time(239_400 as u64).saturating_mul(x as u64)) - // Standard Error: 6_339 - .saturating_add(Weight::from_ref_time(261_836 as u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(7 as u64)) - .saturating_add(RocksDbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_delegators() -> Weight { - Weight::from_ref_time(44_609_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_delegators(x: u32, ) -> Weight { - Weight::from_ref_time(14_022_061 as u64) - // Standard Error: 30_972 - .saturating_add(Weight::from_ref_time(29_549_278 as u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_delegators() -> Weight { - Weight::from_ref_time(44_825_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_revoke_delegation() -> Weight { - Weight::from_ref_time(43_131_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegator_bond_more() -> Weight { - Weight::from_ref_time(90_452_000 as u64) - .saturating_add(RocksDbWeight::get().reads(8 as u64)) - .saturating_add(RocksDbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_delegator_bond_less() -> Weight { - Weight::from_ref_time(43_388_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_revoke_delegation() -> Weight { - Weight::from_ref_time(112_401_000 as u64) - .saturating_add(RocksDbWeight::get().reads(9 as u64)) - .saturating_add(RocksDbWeight::get().writes(8 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_delegator_bond_less() -> Weight { - Weight::from_ref_time(97_377_000 as u64) - .saturating_add(RocksDbWeight::get().reads(8 as u64)) - .saturating_add(RocksDbWeight::get().writes(8 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_revoke_delegation() -> Weight { - Weight::from_ref_time(43_406_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_delegator_bond_less() -> Weight { - Weight::from_ref_time(49_020_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking Staked (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CollatorCommission (r:1 w:0) - // Storage: ParachainStaking DelayedPayouts (r:0 w:1) - #[rustfmt::skip] - fn prepare_staking_payouts() -> Weight { - Weight::from_ref_time(59_628_000 as u64) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - #[rustfmt::skip] - fn get_rewardable_delegators(y: u32, ) -> Weight { - Weight::from_ref_time(16_322_694 as u64) - // Standard Error: 1_133 - .saturating_add(Weight::from_ref_time(233_812 as u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:0) - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:0) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:0 w:1) - // Storage: ParachainStaking AtStake (r:0 w:1) - #[rustfmt::skip] - fn select_top_candidates(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(44_110_000 as u64) - // Standard Error: 237_049 - .saturating_add(Weight::from_ref_time(24_788_127 as u64).saturating_mul(x as u64)) - // Standard Error: 118_210 - .saturating_add(Weight::from_ref_time(2_957_731 as u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelayedPayouts (r:1 w:0) - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking AtStake (r:2 w:1) - // Storage: ParachainStaking AwardedPts (r:1 w:1) - // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn pay_one_collator_reward(y: u32, ) -> Weight { - Weight::from_ref_time(65_307_432 as u64) - // Standard Error: 9_596 - .saturating_add(Weight::from_ref_time(17_073_916 as u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(7 as u64)) - .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(y as u64))) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) - .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(y as u64))) - } - #[rustfmt::skip] - fn base_on_initialize() -> Weight { - Weight::from_ref_time(10_890_000 as u64) - } - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - #[rustfmt::skip] - fn set_auto_compound(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(64_797_700 as u64) - // Standard Error: 5_810 - .saturating_add(Weight::from_ref_time(292_809 as u64).saturating_mul(x as u64)) - // Standard Error: 17_394 - .saturating_add(Weight::from_ref_time(258_382 as u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - #[rustfmt::skip] - fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { - Weight::from_ref_time(181_911_542 as u64) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(120_473 as u64).saturating_mul(x as u64)) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(80_638 as u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(8 as u64)) - .saturating_add(RocksDbWeight::get().writes(8 as u64)) - } - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn mint_collator_reward() -> Weight { - Weight::from_ref_time(40_146_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_staking_expectations() -> Weight { + Weight::from_ref_time(48_225_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_inflation() -> Weight { + Weight::from_ref_time(61_063_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_account() -> Weight { + Weight::from_ref_time(27_645_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + #[rustfmt::skip] + fn set_parachain_bond_reserve_percent() -> Weight { + Weight::from_ref_time(26_922_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:1) + #[rustfmt::skip] + fn set_total_selected() -> Weight { + Weight::from_ref_time(29_263_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking CollatorCommission (r:1 w:1) + #[rustfmt::skip] + fn set_collator_commission() -> Weight { + Weight::from_ref_time(25_867_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + #[rustfmt::skip] + fn set_blocks_per_round() -> Weight { + Weight::from_ref_time(66_047_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:0 w:1) + // Storage: ParachainStaking BottomDelegations (r:0 w:1) + #[rustfmt::skip] + fn join_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(93_609_702_u64) + // Standard Error: 1_049 + .saturating_add(Weight::from_ref_time(156_227_u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(74_938_974_u64) + // Standard Error: 1_813 + .saturating_add(Weight::from_ref_time(136_560_u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: Balances Locks (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(120_885_000_u64) + // Standard Error: 73_687 + .saturating_add(Weight::from_ref_time(31_457_020_u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(x as u64))) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(70_048_572_u64) + // Standard Error: 1_524 + .saturating_add(Weight::from_ref_time(145_661_u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_offline() -> Weight { + Weight::from_ref_time(42_412_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn go_online() -> Weight { + Weight::from_ref_time(41_744_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn candidate_bond_more() -> Weight { + Weight::from_ref_time(68_900_000_u64) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn schedule_candidate_bond_less() -> Weight { + Weight::from_ref_time(38_239_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + #[rustfmt::skip] + fn execute_candidate_bond_less() -> Weight { + Weight::from_ref_time(76_166_000_u64) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + #[rustfmt::skip] + fn cancel_candidate_bond_less() -> Weight { + Weight::from_ref_time(35_581_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegate(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(131_245_351_u64) + // Standard Error: 19_323 + .saturating_add(Weight::from_ref_time(239_400_u64).saturating_mul(x as u64)) + // Standard Error: 6_339 + .saturating_add(Weight::from_ref_time(261_836_u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_leave_delegators() -> Weight { + Weight::from_ref_time(44_609_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn execute_leave_delegators(x: u32, ) -> Weight { + Weight::from_ref_time(14_022_061_u64) + // Standard Error: 30_972 + .saturating_add(Weight::from_ref_time(29_549_278_u64).saturating_mul(x as u64)) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x as u64))) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_leave_delegators() -> Weight { + Weight::from_ref_time(44_825_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_revoke_delegation() -> Weight { + Weight::from_ref_time(43_131_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn delegator_bond_more() -> Weight { + Weight::from_ref_time(90_452_000_u64) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn schedule_delegator_bond_less() -> Weight { + Weight::from_ref_time(43_388_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_revoke_delegation() -> Weight { + Weight::from_ref_time(112_401_000_u64) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + #[rustfmt::skip] + fn execute_delegator_bond_less() -> Weight { + Weight::from_ref_time(97_377_000_u64) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_revoke_delegation() -> Weight { + Weight::from_ref_time(43_406_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + #[rustfmt::skip] + fn cancel_delegator_bond_less() -> Weight { + Weight::from_ref_time(49_020_000_u64) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking Staked (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking CollatorCommission (r:1 w:0) + // Storage: ParachainStaking DelayedPayouts (r:0 w:1) + #[rustfmt::skip] + fn prepare_staking_payouts() -> Weight { + Weight::from_ref_time(59_628_000_u64) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + #[rustfmt::skip] + fn get_rewardable_delegators(y: u32, ) -> Weight { + Weight::from_ref_time(16_322_694_u64) + // Standard Error: 1_133 + .saturating_add(Weight::from_ref_time(233_812_u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking TotalSelected (r:1 w:0) + // Storage: ParachainStaking CandidateInfo (r:1 w:0) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + // Storage: ParachainStaking SelectedCandidates (r:0 w:1) + // Storage: ParachainStaking AtStake (r:0 w:1) + #[rustfmt::skip] + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(44_110_000_u64) + // Standard Error: 237_049 + .saturating_add(Weight::from_ref_time(24_788_127_u64).saturating_mul(x as u64)) + // Standard Error: 118_210 + .saturating_add(Weight::from_ref_time(2_957_731_u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x as u64))) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(x as u64))) + } + // Storage: ParachainStaking DelayedPayouts (r:1 w:0) + // Storage: ParachainStaking Points (r:1 w:0) + // Storage: ParachainStaking AtStake (r:2 w:1) + // Storage: ParachainStaking AwardedPts (r:1 w:1) + // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn pay_one_collator_reward(y: u32, ) -> Weight { + Weight::from_ref_time(65_307_432_u64) + // Standard Error: 9_596 + .saturating_add(Weight::from_ref_time(17_073_916_u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y as u64))) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(y as u64))) + } + #[rustfmt::skip] + fn base_on_initialize() -> Weight { + Weight::from_ref_time(10_890_000_u64) + } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + #[rustfmt::skip] + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(64_797_700_u64) + // Standard Error: 5_810 + .saturating_add(Weight::from_ref_time(292_809_u64).saturating_mul(x as u64)) + // Standard Error: 17_394 + .saturating_add(Weight::from_ref_time(258_382_u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidateInfo (r:1 w:1) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + // Storage: ParachainStaking TopDelegations (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking Total (r:1 w:1) + // Storage: ParachainStaking BottomDelegations (r:1 w:1) + #[rustfmt::skip] + fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { + Weight::from_ref_time(181_911_542_u64) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(120_473_u64).saturating_mul(x as u64)) + // Standard Error: 5_811 + .saturating_add(Weight::from_ref_time(80_638_u64).saturating_mul(y as u64)) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + // Storage: System Account (r:1 w:1) + #[rustfmt::skip] + fn mint_collator_reward() -> Weight { + Weight::from_ref_time(40_146_000_u64) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/external/session-keys/Cargo.toml b/external/session-keys/Cargo.toml index e4822d04e..debbd84bd 100644 --- a/external/session-keys/Cargo.toml +++ b/external/session-keys/Cargo.toml @@ -1,16 +1,16 @@ [package] -name = "session-keys-primitives" -authors = [ "PureStake" ] +authors = ["PureStake"] description = "Primitives for session keys" edition = "2021" +name = "session-keys-primitives" version = "0.1.0" [dependencies] async-trait = { version = "0.1", optional = true } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } nimbus-primitives = { path = "../nimbus-primitives", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive" ] } -scale-info = { version = "2.0", default-features = false, features = [ "derive" ] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0", default-features = false, features = ["derive"] } sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } @@ -22,21 +22,21 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkad sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } [features] -default = [ "std" ] +default = ["std"] +runtime-benchmarks = [] std = [ - "async-trait", - "frame-support/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-api/std", - "sp-application-crypto/std", - "sp-consensus-babe/std", - "sp-consensus-vrf/std", - "sp-core/std", - "sp-inherents/std", - "sp-keystore", - "sp-runtime/std", - "sp-std/std", + "async-trait", + "frame-support/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-api/std", + "sp-application-crypto/std", + "sp-consensus-babe/std", + "sp-consensus-vrf/std", + "sp-core/std", + "sp-inherents/std", + "sp-keystore", + "sp-runtime/std", + "sp-std/std", ] -runtime-benchmarks = [] diff --git a/external/session-keys/src/digest.rs b/external/session-keys/src/digest.rs index c82cf7f92..2c92c2999 100644 --- a/external/session-keys/src/digest.rs +++ b/external/session-keys/src/digest.rs @@ -23,41 +23,41 @@ use sp_runtime::{generic::DigestItem, RuntimeDebug}; /// Raw VRF pre-digest. #[derive(Clone, RuntimeDebug, Encode, Decode)] pub struct PreDigest { - /// VRF output - pub vrf_output: VRFOutput, - /// VRF proof - pub vrf_proof: VRFProof, + /// VRF output + pub vrf_output: VRFOutput, + /// VRF proof + pub vrf_proof: VRFProof, } /// A digest item which is usable with moonbeam VRF. pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which contains a VRF pre-digest. - fn vrf_pre_digest(seal: PreDigest) -> Self; + /// Construct a digest item which contains a VRF pre-digest. + fn vrf_pre_digest(seal: PreDigest) -> Self; - /// If this item is an VRF pre-digest, return it. - fn as_vrf_pre_digest(&self) -> Option; + /// If this item is an VRF pre-digest, return it. + fn as_vrf_pre_digest(&self) -> Option; - /// Construct a digest item which contains a VRF seal. - fn vrf_seal(signature: VrfSignature) -> Self; + /// Construct a digest item which contains a VRF seal. + fn vrf_seal(signature: VrfSignature) -> Self; - /// If this item is a VRF signature, return the signature. - fn as_vrf_seal(&self) -> Option; + /// If this item is a VRF signature, return the signature. + fn as_vrf_seal(&self) -> Option; } impl CompatibleDigestItem for DigestItem { - fn vrf_pre_digest(digest: PreDigest) -> Self { - DigestItem::PreRuntime(VRF_ENGINE_ID, digest.encode()) - } + fn vrf_pre_digest(digest: PreDigest) -> Self { + DigestItem::PreRuntime(VRF_ENGINE_ID, digest.encode()) + } - fn as_vrf_pre_digest(&self) -> Option { - self.pre_runtime_try_to(&VRF_ENGINE_ID) - } + fn as_vrf_pre_digest(&self) -> Option { + self.pre_runtime_try_to(&VRF_ENGINE_ID) + } - fn vrf_seal(signature: VrfSignature) -> Self { - DigestItem::Seal(VRF_ENGINE_ID, signature.encode()) - } + fn vrf_seal(signature: VrfSignature) -> Self { + DigestItem::Seal(VRF_ENGINE_ID, signature.encode()) + } - fn as_vrf_seal(&self) -> Option { - self.seal_try_to(&VRF_ENGINE_ID) - } + fn as_vrf_seal(&self) -> Option { + self.seal_try_to(&VRF_ENGINE_ID) + } } diff --git a/external/session-keys/src/inherent.rs b/external/session-keys/src/inherent.rs index f2948739d..b0f21f87d 100644 --- a/external/session-keys/src/inherent.rs +++ b/external/session-keys/src/inherent.rs @@ -20,27 +20,27 @@ use sp_runtime::RuntimeString; #[derive(Encode)] #[cfg_attr(feature = "std", derive(Debug, Decode))] pub enum InherentError { - Other(RuntimeString), + Other(RuntimeString), } impl IsFatalError for InherentError { - fn is_fatal_error(&self) -> bool { - match *self { - InherentError::Other(_) => true, - } - } + fn is_fatal_error(&self) -> bool { + match *self { + InherentError::Other(_) => true, + } + } } impl InherentError { - /// Try to create an instance ouf of the given identifier and data. - #[cfg(feature = "std")] - pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { - if id == &INHERENT_IDENTIFIER { - ::decode(&mut &*data).ok() - } else { - None - } - } + /// Try to create an instance ouf of the given identifier and data. + #[cfg(feature = "std")] + pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { + if id == &INHERENT_IDENTIFIER { + ::decode(&mut &*data).ok() + } else { + None + } + } } /// The InherentIdentifier to set the babe randomness results @@ -54,23 +54,23 @@ pub struct InherentDataProvider; #[cfg(feature = "std")] #[async_trait::async_trait] impl sp_inherents::InherentDataProvider for InherentDataProvider { - fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> { - inherent_data.put_data(INHERENT_IDENTIFIER, &()) - } + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> { + inherent_data.put_data(INHERENT_IDENTIFIER, &()) + } - async fn try_handle_error( - &self, - identifier: &InherentIdentifier, - _error: &[u8], - ) -> Option> { - // Don't process modules from other inherents - if *identifier != INHERENT_IDENTIFIER { - return None; - } + async fn try_handle_error( + &self, + identifier: &InherentIdentifier, + _error: &[u8], + ) -> Option> { + // Don't process modules from other inherents + if *identifier != INHERENT_IDENTIFIER { + return None; + } - // All errors with the randomness inherent are fatal - Some(Err(Error::Application(Box::from(String::from( - "Error processing dummy randomness inherent", - ))))) - } + // All errors with the randomness inherent are fatal + Some(Err(Error::Application(Box::from(String::from( + "Error processing dummy randomness inherent", + ))))) + } } diff --git a/external/session-keys/src/lib.rs b/external/session-keys/src/lib.rs index 4fb8eeb56..bae1a16af 100644 --- a/external/session-keys/src/lib.rs +++ b/external/session-keys/src/lib.rs @@ -26,20 +26,20 @@ pub use vrf::*; /// A Trait to lookup keys from AuthorIds pub trait KeysLookup { - #[cfg(feature = "runtime-benchmarks")] - type Account; - fn lookup_keys(author: &AuthorId) -> Option; - #[cfg(feature = "runtime-benchmarks")] - fn set_keys(id: AuthorId, account: Self::Account, keys: Keys); + #[cfg(feature = "runtime-benchmarks")] + type Account; + fn lookup_keys(author: &AuthorId) -> Option; + #[cfg(feature = "runtime-benchmarks")] + fn set_keys(id: AuthorId, account: Self::Account, keys: Keys); } // A dummy impl used in simple tests impl KeysLookup for () { - #[cfg(feature = "runtime-benchmarks")] - type Account = (); - fn lookup_keys(_: &AuthorId) -> Option { - None - } - #[cfg(feature = "runtime-benchmarks")] - fn set_keys(_id: AuthorId, _account: Self::Account, _keys: Keys) {} + #[cfg(feature = "runtime-benchmarks")] + type Account = (); + fn lookup_keys(_: &AuthorId) -> Option { + None + } + #[cfg(feature = "runtime-benchmarks")] + fn set_keys(_id: AuthorId, _account: Self::Account, _keys: Keys) {} } diff --git a/external/session-keys/src/vrf.rs b/external/session-keys/src/vrf.rs index b8a1a8ddb..caf1c3b13 100644 --- a/external/session-keys/src/vrf.rs +++ b/external/session-keys/src/vrf.rs @@ -24,36 +24,36 @@ use sp_runtime::{BoundToRuntimeAppPublic, ConsensusEngineId}; /// Make VRF transcript from the VrfInput pub fn make_transcript>(last_vrf_output: Hash) -> Transcript { - let mut transcript = Transcript::new(&VRF_ENGINE_ID); - transcript.append_message(b"last vrf output", last_vrf_output.as_ref()); - transcript + let mut transcript = Transcript::new(&VRF_ENGINE_ID); + transcript.append_message(b"last vrf output", last_vrf_output.as_ref()); + transcript } /// Make a VRF transcript data container #[cfg(feature = "std")] pub fn make_transcript_data>(last_vrf_output: Hash) -> VRFTranscriptData { - VRFTranscriptData { - label: &VRF_ENGINE_ID, - items: vec![( - "last vrf output", - VRFTranscriptValue::Bytes(last_vrf_output.as_ref().to_vec()), - )], - } + VRFTranscriptData { + label: &VRF_ENGINE_ID, + items: vec![( + "last vrf output", + VRFTranscriptValue::Bytes(last_vrf_output.as_ref().to_vec()), + )], + } } /// Struct to implement `BoundToRuntimeAppPublic` by assigning Public = VrfId pub struct VrfSessionKey; impl BoundToRuntimeAppPublic for VrfSessionKey { - type Public = VrfId; + type Public = VrfId; } impl From for VrfId { - fn from(nimbus_id: NimbusId) -> VrfId { - let nimbus_as_sr25519: sr25519::Public = nimbus_id.into(); - let sr25519_as_bytes: [u8; 32] = nimbus_as_sr25519.into(); - sr25519::Public::unchecked_from(sr25519_as_bytes).into() - } + fn from(nimbus_id: NimbusId) -> VrfId { + let nimbus_as_sr25519: sr25519::Public = nimbus_id.into(); + let sr25519_as_bytes: [u8; 32] = nimbus_as_sr25519.into(); + sr25519::Public::unchecked_from(sr25519_as_bytes).into() + } } /// The ConsensusEngineId for VRF keys @@ -67,8 +67,8 @@ pub static VRF_INOUT_CONTEXT: &[u8] = b"VRFInOutContext"; // The strongly-typed crypto wrappers to be used by VRF in the keystore mod vrf_crypto { - use sp_application_crypto::{app_crypto, sr25519}; - app_crypto!(sr25519, crate::VRF_KEY_ID); + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, crate::VRF_KEY_ID); } /// A vrf public key. @@ -78,23 +78,23 @@ pub type VrfId = vrf_crypto::Public; pub type VrfSignature = vrf_crypto::Signature; sp_application_crypto::with_pair! { - /// A vrf key pair - pub type VrfPair = vrf_crypto::Pair; + /// A vrf key pair + pub type VrfPair = vrf_crypto::Pair; } sp_api::decl_runtime_apis! { - pub trait VrfApi { - fn get_last_vrf_output() -> Option; - fn vrf_key_lookup(nimbus_id: nimbus_primitives::NimbusId) -> Option; - } + pub trait VrfApi { + fn get_last_vrf_output() -> Option; + fn vrf_key_lookup(nimbus_id: nimbus_primitives::NimbusId) -> Option; + } } #[test] fn nimbus_to_vrf_id() { - for x in 0u8..10u8 { - let nimbus_id: NimbusId = sr25519::Public::unchecked_from([x; 32]).into(); - let expected_vrf_id: VrfId = sr25519::Public::unchecked_from([x; 32]).into(); - let nimbus_to_vrf_id: VrfId = nimbus_id.into(); - assert_eq!(expected_vrf_id, nimbus_to_vrf_id); - } + for x in 0u8..10u8 { + let nimbus_id: NimbusId = sr25519::Public::unchecked_from([x; 32]).into(); + let expected_vrf_id: VrfId = sr25519::Public::unchecked_from([x; 32]).into(); + let nimbus_to_vrf_id: VrfId = nimbus_id.into(); + assert_eq!(expected_vrf_id, nimbus_to_vrf_id); + } } diff --git a/external/vrf/Cargo.toml b/external/vrf/Cargo.toml index f0c736803..76915e432 100644 --- a/external/vrf/Cargo.toml +++ b/external/vrf/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "moonbeam-vrf" -authors = [ "PureStake" ] +authors = ["PureStake"] edition = "2018" homepage = "https://moonbeam.network" license = "GPL-3.0-only" +name = "moonbeam-vrf" repository = "https://github.com/PureStake/moonbeam/" version = "0.1.0" [dependencies] # Substrate -codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } diff --git a/external/vrf/src/lib.rs b/external/vrf/src/lib.rs index 169e13660..6fac4740d 100644 --- a/external/vrf/src/lib.rs +++ b/external/vrf/src/lib.rs @@ -26,50 +26,46 @@ use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; /// Uses the runtime API to get the VRF inputs and sign them with the VRF key that /// corresponds to the authoring NimbusId. pub fn vrf_pre_digest( - client: &C, - keystore: &SyncCryptoStorePtr, - nimbus_id: NimbusId, - parent: H256, + client: &C, + keystore: &SyncCryptoStorePtr, + nimbus_id: NimbusId, + parent: H256, ) -> Option where - B: sp_runtime::traits::Block, - C: sp_api::ProvideRuntimeApi, - C::Api: VrfApi, + B: sp_runtime::traits::Block, + C: sp_api::ProvideRuntimeApi, + C::Api: VrfApi, { - let at = sp_api::BlockId::Hash(parent); - let runtime_api = client.runtime_api(); + let at = sp_api::BlockId::Hash(parent); + let runtime_api = client.runtime_api(); - // first ? for runtime API, second ? for if last vrf output is not available - let last_vrf_output = runtime_api.get_last_vrf_output(&at).ok()??; - // first ? for runtime API, second ? for not VRF key associated with NimbusId - let key: VrfId = runtime_api.vrf_key_lookup(&at, nimbus_id).ok()??; - let vrf_pre_digest = sign_vrf(last_vrf_output, key, &keystore)?; - Some(session_keys_primitives::digest::CompatibleDigestItem::vrf_pre_digest(vrf_pre_digest)) + // first ? for runtime API, second ? for if last vrf output is not available + let last_vrf_output = runtime_api.get_last_vrf_output(&at).ok()??; + // first ? for runtime API, second ? for not VRF key associated with NimbusId + let key: VrfId = runtime_api.vrf_key_lookup(&at, nimbus_id).ok()??; + let vrf_pre_digest = sign_vrf(last_vrf_output, key, keystore)?; + Some(session_keys_primitives::digest::CompatibleDigestItem::vrf_pre_digest(vrf_pre_digest)) } /// Signs the VrfInput using the private key corresponding to the input `key` public key /// to be found in the input keystore fn sign_vrf(last_vrf_output: H256, key: VrfId, keystore: &SyncCryptoStorePtr) -> Option { - let transcript = make_transcript(last_vrf_output.clone()); - let transcript_data = make_transcript_data(last_vrf_output); - let try_sign = - SyncCryptoStore::sr25519_vrf_sign(&**keystore, VrfId::ID, key.as_ref(), transcript_data); - if let Ok(Some(signature)) = try_sign { - let public = PublicKey::from_bytes(&key.to_raw_vec()).ok()?; - if signature - .output - .attach_input_hash(&public, transcript) - .is_err() - { - // VRF signature cannot be validated using key and transcript - return None; - } - Some(PreDigest { - vrf_output: VRFOutput(signature.output), - vrf_proof: VRFProof(signature.proof), - }) - } else { - // VRF key not found in keystore or VRF signing failed - None - } + let transcript = make_transcript(last_vrf_output); + let transcript_data = make_transcript_data(last_vrf_output); + let try_sign = + SyncCryptoStore::sr25519_vrf_sign(&**keystore, VrfId::ID, key.as_ref(), transcript_data); + if let Ok(Some(signature)) = try_sign { + let public = PublicKey::from_bytes(&key.to_raw_vec()).ok()?; + if signature.output.attach_input_hash(&public, transcript).is_err() { + // VRF signature cannot be validated using key and transcript + return None; + } + Some(PreDigest { + vrf_output: VRFOutput(signature.output), + vrf_proof: VRFProof(signature.proof), + }) + } else { + // VRF key not found in keystore or VRF signing failed + None + } } diff --git a/node/Cargo.toml b/node/Cargo.toml index b507c56db..352653004 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -64,8 +64,8 @@ cumulus-relay-chain-rpc-interface = { branch = "polkadot-v0.9.32", git = "https: # Parachain moonbeam-vrf = { path = "../external/vrf", optional = true } -nimbus-primitives = { default-features = false, path = "../external/nimbus-primitives", optional = true } nimbus-consensus = { default-features = false, path = "../external/nimbus-consensus", optional = true } +nimbus-primitives = { default-features = false, path = "../external/nimbus-primitives", optional = true } pallet-author-inherent = { default-features = false, path = "../external/pallets/author-inherent", optional = true } pallet-parachain-staking = { default-features = false, path = "../external/pallets/parachain-staking", optional = true } parity-scale-codec = { optional = true, version = "3.0.0" } diff --git a/node/src/command.rs b/node/src/command.rs index 86ab40238..1ffe3508d 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -115,10 +115,9 @@ pub fn run() -> sc_cli::Result<()> { runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())) } #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err( - "Storage benchmarking can be enabled with `--features runtime-benchmarks`." - .into(), - ), + BenchmarkCmd::Storage(_) => Err("Storage benchmarking can be enabled with \ + `--features runtime-benchmarks`." + .into()), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => match chain_spec { #[cfg(feature = "with-zeitgeist-runtime")] diff --git a/node/src/service/service_parachain.rs b/node/src/service/service_parachain.rs index 348af4d7e..6f4e3f7ea 100644 --- a/node/src/service/service_parachain.rs +++ b/node/src/service/service_parachain.rs @@ -19,7 +19,7 @@ use crate::{ service::{AdditionalRuntimeApiCollection, RuntimeApiCollection}, KUSAMA_BLOCK_DURATION, SOFT_DEADLINE_PERCENT, }; -use cumulus_client_cli::CollatorOptions; +// use cumulus_client_cli::CollatorOptions; use cumulus_client_consensus_common::ParachainConsensus; use cumulus_client_network::BlockAnnounceValidator; use cumulus_client_service::{ @@ -322,7 +322,7 @@ where keystore: params.keystore_container.sync_keystore(), network: network.clone(), rpc_builder, - tx_handler_controller: tx_handler_controller, + tx_handler_controller, system_rpc_tx, task_manager: &mut task_manager, telemetry: telemetry.as_mut(), diff --git a/runtime/battery-station/src/integration_tests/xcm/setup.rs b/runtime/battery-station/src/integration_tests/xcm/setup.rs index d1c071295..bc44aab7a 100644 --- a/runtime/battery-station/src/integration_tests/xcm/setup.rs +++ b/runtime/battery-station/src/integration_tests/xcm/setup.rs @@ -18,7 +18,8 @@ use crate::{ xcm_config::config::{battery_station, general_key}, - AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, RuntimeOrigin, Runtime, System, + AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, Runtime, RuntimeOrigin, + System, }; use frame_support::{assert_ok, traits::GenesisBuild}; use orml_traits::asset_registry::AssetMetadata; @@ -147,7 +148,11 @@ pub(super) fn register_foreign_sibling(additional_meta: Option) additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_SIBLING_ID))); + assert_ok!(AssetRegistry::register_asset( + RuntimeOrigin::root(), + meta, + Some(FOREIGN_SIBLING_ID) + )); } pub(super) fn register_foreign_parent(additional_meta: Option) { diff --git a/runtime/battery-station/src/integration_tests/xcm/test_net.rs b/runtime/battery-station/src/integration_tests/xcm/test_net.rs index 4f91fd7a3..c66231145 100644 --- a/runtime/battery-station/src/integration_tests/xcm/test_net.rs +++ b/runtime/battery-station/src/integration_tests/xcm/test_net.rs @@ -17,7 +17,7 @@ use crate::{ parameters::ZeitgeistTreasuryAccount, xcm_config::config::battery_station, AccountId, - CurrencyId, DmpQueue, RuntimeOrigin, Runtime, XcmpQueue, + CurrencyId, DmpQueue, Runtime, RuntimeOrigin, XcmpQueue, }; use frame_support::{traits::GenesisBuild, weights::Weight}; use polkadot_primitives::v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; diff --git a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs index 91af6cfe0..eadbf19ab 100644 --- a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs @@ -71,7 +71,7 @@ fn transfer_ztg_to_sibling() { ) .into() ), - 4_000_000_000, + xcm_emulator::Limited(4_000_000_000), )); // Confirm that Alice's balance is initial_balance - amount_transferred @@ -141,7 +141,7 @@ fn transfer_ztg_sibling_to_zeitgeist() { ) .into() ), - 4_000_000_000, + xcm_emulator::Limited(4_000_000_000), )); // Confirm that Bobs's balance is initial balance - amount transferred @@ -187,7 +187,7 @@ fn transfer_ksm_from_relay_chain() { assert!(initial_balance >= transfer_amount); assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), + kusama_runtime::RuntimeOrigin::signed(ALICE.into()), Box::new(Parachain(battery_station::ID).into().into()), Box::new(Junction::AccountId32 { network: NetworkId::Any, id: BOB }.into().into()), Box::new((Here, transfer_amount).into()), @@ -225,7 +225,7 @@ fn transfer_ksm_to_relay_chain() { ) .into() ), - 4_000_000_000 + xcm_emulator::Limited(4_000_000_000) )); assert_eq!( @@ -287,7 +287,7 @@ fn transfer_ztg_to_sibling_with_custom_fee() { ) .into() ), - 4_000_000_000, + xcm_emulator::Limited(4_000_000_000), )); // Confirm that Alice's balance is initial_balance - amount_transferred diff --git a/runtime/battery-station/src/parachain_params.rs b/runtime/battery-station/src/parachain_params.rs index daaf82ddb..43a354673 100644 --- a/runtime/battery-station/src/parachain_params.rs +++ b/runtime/battery-station/src/parachain_params.rs @@ -22,7 +22,7 @@ )] #![cfg(feature = "parachain")] -use super::{parameters::MAXIMUM_BLOCK_WEIGHT, RuntimeOrigin, ParachainInfo}; +use super::{parameters::MAXIMUM_BLOCK_WEIGHT, ParachainInfo, RuntimeOrigin}; use frame_support::{parameter_types, weights::Weight}; use orml_traits::parameter_type_with_key; use sp_runtime::{Perbill, Percent}; diff --git a/runtime/battery-station/src/parameters.rs b/runtime/battery-station/src/parameters.rs index f19c00fa0..92e1191d1 100644 --- a/runtime/battery-station/src/parameters.rs +++ b/runtime/battery-station/src/parameters.rs @@ -23,12 +23,13 @@ use super::VERSION; use frame_support::{ + dispatch::DispatchClass, parameter_types, + traits::WithdrawReasons, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, - DispatchClass, Weight, + Weight, }, - traits::WithdrawReasons, PalletId, }; use frame_system::limits::{BlockLength, BlockWeights}; @@ -353,7 +354,7 @@ parameter_types! { // Vesting pub const MinVestedTransfer: Balance = ExistentialDeposit::get(); pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); } #[cfg(feature = "with-global-disputes")] diff --git a/runtime/battery-station/src/xcm_config/config.rs b/runtime/battery-station/src/xcm_config/config.rs index 6ccb40723..c09995566 100644 --- a/runtime/battery-station/src/xcm_config/config.rs +++ b/runtime/battery-station/src/xcm_config/config.rs @@ -17,9 +17,9 @@ use super::fees::{native_per_second, FixedConversionRateProvider}; use crate::{ - AccountId, Ancestry, AssetManager, AssetRegistry, Balance, RuntimeCall, CurrencyId, MaxInstructions, - RuntimeOrigin, ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, - UnitWeightCost, UnknownTokens, XcmpQueue, ZeitgeistTreasuryAccount, + AccountId, Ancestry, AssetManager, AssetRegistry, Balance, CurrencyId, MaxInstructions, + ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, RuntimeCall, + RuntimeOrigin, UnitWeightCost, UnknownTokens, XcmpQueue, ZeitgeistTreasuryAccount, }; use frame_support::{parameter_types, traits::Everything, WeakBoundedVec}; diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 5a4f6c7ca..2d6769dc7 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1812,7 +1812,7 @@ macro_rules! create_common_tests { mod common_tests { mod fees { use crate::*; - use frame_support::weights::{DispatchClass, Weight}; + use frame_support::{dispatch::DispatchClass, weights::Weight}; use sp_core::H256; use sp_runtime::traits::Convert; diff --git a/runtime/zeitgeist/src/integration_tests/xcm/setup.rs b/runtime/zeitgeist/src/integration_tests/xcm/setup.rs index 6a7a8bacd..055a5413d 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/setup.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/setup.rs @@ -18,7 +18,8 @@ use crate::{ xcm_config::config::{general_key, zeitgeist}, - AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, RuntimeOrigin, Runtime, System, + AccountId, AssetRegistry, Balance, CurrencyId, ExistentialDeposit, Runtime, RuntimeOrigin, + System, }; use frame_support::{assert_ok, traits::GenesisBuild}; use orml_traits::asset_registry::AssetMetadata; @@ -147,7 +148,11 @@ pub(super) fn register_foreign_sibling(additional_meta: Option) additional: additional_meta.unwrap_or_default(), }; - assert_ok!(AssetRegistry::register_asset(RuntimeOrigin::root(), meta, Some(FOREIGN_SIBLING_ID))); + assert_ok!(AssetRegistry::register_asset( + RuntimeOrigin::root(), + meta, + Some(FOREIGN_SIBLING_ID) + )); } pub(super) fn register_foreign_parent(additional_meta: Option) { diff --git a/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs b/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs index 71748407a..aac0db713 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/test_net.rs @@ -17,7 +17,7 @@ use crate::{ parameters::ZeitgeistTreasuryAccount, xcm_config::config::zeitgeist, AccountId, CurrencyId, - DmpQueue, RuntimeOrigin, Runtime, XcmpQueue, + DmpQueue, Runtime, RuntimeOrigin, XcmpQueue, }; use frame_support::{traits::GenesisBuild, weights::Weight}; use polkadot_primitives::v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; diff --git a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs index acb2c5da7..a731dc53f 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs @@ -71,7 +71,7 @@ fn transfer_ztg_to_sibling() { ) .into() ), - 4_000_000_000, + xcm_emulator::Limited(4_000_000_000), )); // Confirm that Alice's balance is initial_balance - amount_transferred @@ -141,7 +141,7 @@ fn transfer_ztg_sibling_to_zeitgeist() { ) .into() ), - 4_000_000_000, + xcm_emulator::Limited(4_000_000_000), )); // Confirm that Bobs's balance is initial balance - amount transferred @@ -187,7 +187,7 @@ fn transfer_ksm_from_relay_chain() { assert!(initial_balance >= transfer_amount); assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), + kusama_runtime::RuntimeOrigin::signed(ALICE.into()), Box::new(Parachain(zeitgeist::ID).into().into()), Box::new(Junction::AccountId32 { network: NetworkId::Any, id: BOB }.into().into()), Box::new((Here, transfer_amount).into()), @@ -225,7 +225,7 @@ fn transfer_ksm_to_relay_chain() { ) .into() ), - 4_000_000_000 + xcm_emulator::Limited(4_000_000_000) )); assert_eq!( @@ -287,7 +287,7 @@ fn transfer_ztg_to_sibling_with_custom_fee() { ) .into() ), - 4_000_000_000, + xcm_emulator::Limited(4_000_000_000), )); // Confirm that Alice's balance is initial_balance - amount_transferred diff --git a/runtime/zeitgeist/src/parachain_params.rs b/runtime/zeitgeist/src/parachain_params.rs index b7193a3e2..85ddf053c 100644 --- a/runtime/zeitgeist/src/parachain_params.rs +++ b/runtime/zeitgeist/src/parachain_params.rs @@ -22,7 +22,7 @@ )] #![cfg(feature = "parachain")] -use super::{parameters::MAXIMUM_BLOCK_WEIGHT, RuntimeOrigin, ParachainInfo}; +use super::{parameters::MAXIMUM_BLOCK_WEIGHT, ParachainInfo, RuntimeOrigin}; use frame_support::{parameter_types, weights::Weight}; use orml_traits::parameter_type_with_key; use sp_runtime::{Perbill, Percent}; diff --git a/runtime/zeitgeist/src/parameters.rs b/runtime/zeitgeist/src/parameters.rs index 577bdb56c..8ca41d088 100644 --- a/runtime/zeitgeist/src/parameters.rs +++ b/runtime/zeitgeist/src/parameters.rs @@ -23,12 +23,13 @@ use super::VERSION; use frame_support::{ + dispatch::DispatchClass, parameter_types, + traits::WithdrawReasons, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, - DispatchClass, Weight, + Weight, }, - traits::WithdrawReasons, PalletId, }; use frame_system::limits::{BlockLength, BlockWeights}; @@ -353,7 +354,7 @@ parameter_types! { // Vesting pub const MinVestedTransfer: Balance = ExistentialDeposit::get(); pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); } #[cfg(feature = "with-global-disputes")] diff --git a/runtime/zeitgeist/src/xcm_config/config.rs b/runtime/zeitgeist/src/xcm_config/config.rs index b2fd46231..620bff6b8 100644 --- a/runtime/zeitgeist/src/xcm_config/config.rs +++ b/runtime/zeitgeist/src/xcm_config/config.rs @@ -17,9 +17,9 @@ use super::fees::{native_per_second, FixedConversionRateProvider}; use crate::{ - AccountId, Ancestry, AssetManager, AssetRegistry, Balance, RuntimeCall, CurrencyId, MaxInstructions, - RuntimeOrigin, ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, - UnitWeightCost, UnknownTokens, XcmpQueue, ZeitgeistTreasuryAccount, + AccountId, Ancestry, AssetManager, AssetRegistry, Balance, CurrencyId, MaxInstructions, + ParachainInfo, ParachainSystem, PolkadotXcm, RelayChainOrigin, RelayNetwork, RuntimeCall, + RuntimeOrigin, UnitWeightCost, UnknownTokens, XcmpQueue, ZeitgeistTreasuryAccount, }; use frame_support::{parameter_types, traits::Everything, WeakBoundedVec}; diff --git a/zrml/authorized/src/tests.rs b/zrml/authorized/src/tests.rs index aa2844c47..f22157e21 100644 --- a/zrml/authorized/src/tests.rs +++ b/zrml/authorized/src/tests.rs @@ -19,7 +19,7 @@ use crate::{ market_mock, - mock::{Authorized, AuthorizedDisputeResolutionUser, ExtBuilder, RuntimeOrigin, Runtime, BOB}, + mock::{Authorized, AuthorizedDisputeResolutionUser, ExtBuilder, Runtime, RuntimeOrigin, BOB}, mock_storage::pallet as mock_storage, AuthorizedOutcomeReports, Error, }; @@ -150,7 +150,11 @@ fn authorize_market_outcome_fails_on_unauthorized_account() { ExtBuilder::default().build().execute_with(|| { Markets::::insert(0, market_mock::()); assert_noop!( - Authorized::authorize_market_outcome(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(1)), + Authorized::authorize_market_outcome( + RuntimeOrigin::signed(BOB), + 0, + OutcomeReport::Scalar(1) + ), DispatchError::BadOrigin, ); }); diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index a4203c509..322cbaf93 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -19,8 +19,8 @@ use crate::{ mock::{ - Balances, Court, ExtBuilder, RuntimeOrigin, RandomnessCollectiveFlip, Runtime, System, ALICE, BOB, - CHARLIE, INITIAL_BALANCE, + Balances, Court, ExtBuilder, RandomnessCollectiveFlip, Runtime, RuntimeOrigin, System, + ALICE, BOB, CHARLIE, INITIAL_BALANCE, }, Error, Juror, JurorStatus, Jurors, MarketOf, RequestedJurors, Votes, }; diff --git a/zrml/liquidity-mining/src/tests.rs b/zrml/liquidity-mining/src/tests.rs index 5023a06c5..a264c1347 100644 --- a/zrml/liquidity-mining/src/tests.rs +++ b/zrml/liquidity-mining/src/tests.rs @@ -18,7 +18,7 @@ #![cfg(test)] use crate::{ - mock::{Balances, ExtBuilder, LiquidityMining, RuntimeOrigin, Runtime, System, ALICE, BOB}, + mock::{Balances, ExtBuilder, LiquidityMining, Runtime, RuntimeOrigin, System, ALICE, BOB}, track_incentives_based_on_bought_shares::TrackIncentivesBasedOnBoughtShares, track_incentives_based_on_sold_shares::TrackIncentivesBasedOnSoldShares, BlockBoughtShares, BlockSoldShares, LiquidityMiningPalletApi as _, OwnedValues, diff --git a/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs b/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs index 02adff777..718c2837e 100644 --- a/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs +++ b/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs @@ -47,7 +47,8 @@ fuzz_target!(|data: Data| { data.make_fill_order_price, ); - let _ = Orderbook::fill_order(RuntimeOrigin::signed(data.fill_order_origin.into()), order_hash); + let _ = + Orderbook::fill_order(RuntimeOrigin::signed(data.fill_order_origin.into()), order_hash); // Make arbitrary order and attempt to cancel let order_asset = asset(data.make_cancel_order_asset); diff --git a/zrml/orderbook-v1/src/tests.rs b/zrml/orderbook-v1/src/tests.rs index 26c8be49e..4bbbd31af 100644 --- a/zrml/orderbook-v1/src/tests.rs +++ b/zrml/orderbook-v1/src/tests.rs @@ -94,7 +94,13 @@ fn it_cancels_orders() { ExtBuilder::default().build().execute_with(|| { // Make an order from Alice to buy shares. let share_id = Asset::CategoricalOutcome(0, 2); - assert_ok!(Orderbook::make_order(RuntimeOrigin::signed(ALICE), share_id, OrderSide::Bid, 25, 10)); + assert_ok!(Orderbook::make_order( + RuntimeOrigin::signed(ALICE), + share_id, + OrderSide::Bid, + 25, + 10 + )); let order_hash = Orderbook::order_hash(&ALICE, share_id, 0); diff --git a/zrml/prediction-markets/fuzz/pm_full_workflow.rs b/zrml/prediction-markets/fuzz/pm_full_workflow.rs index c97116f4a..915493f6d 100644 --- a/zrml/prediction-markets/fuzz/pm_full_workflow.rs +++ b/zrml/prediction-markets/fuzz/pm_full_workflow.rs @@ -25,7 +25,7 @@ use zeitgeist_primitives::types::{ Asset, Deadlines, MarketCreation, MarketDisputeMechanism, MarketPeriod, MarketType, MultiHash, OutcomeReport, ScoringRule, }; -use zrml_prediction_markets::mock::{ExtBuilder, RuntimeOrigin, PredictionMarkets, System}; +use zrml_prediction_markets::mock::{ExtBuilder, PredictionMarkets, RuntimeOrigin, System}; fuzz_target!(|data: Data| { let mut ext = ExtBuilder::default().build(); diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 7264cae74..dcafa6f40 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -44,8 +44,7 @@ mod pallet { tokens::BalanceStatus, Currency, EnsureOrigin, Get, Hooks, Imbalance, IsType, NamedReservableCurrency, OnUnbalanced, StorageVersion, }, - transactional, - Blake2_128Concat, BoundedVec, PalletId, Twox64Concat, + transactional, Blake2_128Concat, BoundedVec, PalletId, Twox64Concat, }; use frame_system::{ensure_signed, pallet_prelude::OriginFor}; diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 6073e7bdf..e9daaf10b 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -179,7 +179,8 @@ impl OnRuntimeUpgrade for AddOutsiderBo // let old_markets: BTreeMap, OldMarketOf> = // Self::get_temp_storage("old_markets").unwrap(); let old_markets: BTreeMap, OldMarketOf> = - Decode::decode(&mut old_markets.as_slice()).expect("old_markets not generated properly by pre_upgrade"); + Decode::decode(&mut old_markets.as_slice()) + .expect("old_markets not generated properly by pre_upgrade"); let new_market_count = >::market_iter().count(); assert_eq!(old_markets.len(), new_market_count); for (market_id, new_market) in >::market_iter() { diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 1bc046ebd..a2d1566c0 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -141,7 +141,10 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_blocknumb ); run_blocks(3); let market_id = 0; - assert_ok!(PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::admin_move_market_to_closed( + RuntimeOrigin::signed(SUDO), + market_id + )); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Closed); let new_end = now + 3; @@ -182,7 +185,10 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_timestamp set_timestamp_for_on_initialize(start + shift + MILLISECS_PER_BLOCK as u64); run_blocks(shift_blocks); - assert_ok!(PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::admin_move_market_to_closed( + RuntimeOrigin::signed(SUDO), + market_id + )); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Closed); let new_end = start + shift; @@ -1196,7 +1202,10 @@ fn admin_move_market_to_resovled_fails_if_market_is_not_reported_or_disputed( Ok(()) })); assert_noop!( - PredictionMarkets::admin_move_market_to_resolved(RuntimeOrigin::signed(SUDO), market_id,), + PredictionMarkets::admin_move_market_to_resolved( + RuntimeOrigin::signed(SUDO), + market_id, + ), Error::::InvalidMarketStatus, ); }); @@ -1383,7 +1392,11 @@ fn it_allows_request_edit_origin_to_request_edits_for_markets() { ); // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason.clone())); + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(SUDO), + 0, + edit_reason.clone() + )); System::assert_last_event( Event::MarketRequestedEdit( 0, @@ -1733,7 +1746,11 @@ fn on_market_close_auto_rejects_expired_advised_market_with_edit_request() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), market_id, edit_reason)); + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(SUDO), + market_id, + edit_reason + )); assert!(MarketIdsForEdit::::contains_key(0)); run_blocks(end); @@ -2490,7 +2507,11 @@ fn it_allows_only_oracle_to_report_the_outcome_of_a_market_during_oracle_duratio assert!(market.report.is_none()); assert_noop!( - PredictionMarkets::report(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report( + RuntimeOrigin::signed(CHARLIE), + 0, + OutcomeReport::Categorical(1) + ), Error::::ReporterNotOracle ); @@ -2702,7 +2723,11 @@ fn dispute_fails_authority_reported_already() { )); assert_noop!( - PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::dispute( + RuntimeOrigin::signed(CHARLIE), + 0, + OutcomeReport::Categorical(1) + ), AuthorizedError::::OnlyOneDisputeAllowed ); }); @@ -2959,7 +2984,11 @@ fn dispute_fails_unless_reported_or_disputed_market(status: MarketStatus) { })); assert_noop!( - PredictionMarkets::dispute(RuntimeOrigin::signed(EVE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::dispute( + RuntimeOrigin::signed(EVE), + 0, + OutcomeReport::Categorical(1) + ), Error::::InvalidMarketStatus ); }); @@ -2997,13 +3026,19 @@ fn start_global_dispute_works() { if i == 1 { #[cfg(feature = "with-global-disputes")] assert_noop!( - PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id), + PredictionMarkets::start_global_dispute( + RuntimeOrigin::signed(CHARLIE), + market_id + ), Error::::InvalidMarketStatus ); } else { #[cfg(feature = "with-global-disputes")] assert_noop!( - PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id), + PredictionMarkets::start_global_dispute( + RuntimeOrigin::signed(CHARLIE), + market_id + ), Error::::MaxDisputesNeeded ); } @@ -3030,7 +3065,10 @@ fn start_global_dispute_works() { use zrml_global_disputes::GlobalDisputesPalletApi; let now = >::block_number(); - assert_ok!(PredictionMarkets::start_global_dispute(RuntimeOrigin::signed(CHARLIE), market_id)); + assert_ok!(PredictionMarkets::start_global_dispute( + RuntimeOrigin::signed(CHARLIE), + market_id + )); // report check assert_eq!( @@ -3608,7 +3646,11 @@ fn full_scalar_market_lifecycle() { ScoringRule::CPMM )); - assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, 100 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set( + RuntimeOrigin::signed(CHARLIE), + 0, + 100 * BASE + )); // check balances let assets = PredictionMarkets::outcome_assets(0, &MarketCommons::market(&0).unwrap()); @@ -3626,7 +3668,11 @@ fn full_scalar_market_lifecycle() { Timestamp::set_timestamp(100_000_000 + grace_period); // report - assert_ok!(PredictionMarkets::report(RuntimeOrigin::signed(BOB), 0, OutcomeReport::Scalar(100))); + assert_ok!(PredictionMarkets::report( + RuntimeOrigin::signed(BOB), + 0, + OutcomeReport::Scalar(100) + )); let market_after_report = MarketCommons::market(&0).unwrap(); assert!(market_after_report.report.is_some()); @@ -3636,7 +3682,11 @@ fn full_scalar_market_lifecycle() { assert_eq!(report.outcome, OutcomeReport::Scalar(100)); // dispute - assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(DAVE), 0, OutcomeReport::Scalar(25))); + assert_ok!(PredictionMarkets::dispute( + RuntimeOrigin::signed(DAVE), + 0, + OutcomeReport::Scalar(25) + )); let disputes = crate::Disputes::::get(0); assert_eq!(disputes.len(), 1); @@ -3805,7 +3855,11 @@ fn market_resolve_does_not_hold_liquidity_withdraw() { deploy_swap_pool(MarketCommons::market(&0).unwrap(), 0).unwrap(); assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(ALICE), 0, BASE)); assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(BOB), 0, 2 * BASE)); - assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, 3 * BASE)); + assert_ok!(PredictionMarkets::buy_complete_set( + RuntimeOrigin::signed(CHARLIE), + 0, + 3 * BASE + )); let market = MarketCommons::market(&0).unwrap(); let grace_period = end + market.deadlines.grace_period; @@ -4926,7 +4980,11 @@ fn report_fails_if_reporter_is_not_the_oracle() { let grace_period: u64 = market.deadlines.grace_period * MILLISECS_PER_BLOCK as u64; set_timestamp_for_on_initialize(100_000_000 + grace_period + MILLISECS_PER_BLOCK as u64); assert_noop!( - PredictionMarkets::report(RuntimeOrigin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::report( + RuntimeOrigin::signed(CHARLIE), + 0, + OutcomeReport::Categorical(1) + ), Error::::ReporterNotOracle, ); }); diff --git a/zrml/styx/src/tests.rs b/zrml/styx/src/tests.rs index 44323b632..20988d223 100644 --- a/zrml/styx/src/tests.rs +++ b/zrml/styx/src/tests.rs @@ -39,7 +39,10 @@ fn account_should_only_be_able_to_cross_once() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); assert_ok!(Styx::cross(RuntimeOrigin::signed(ALICE))); - assert_noop!(Styx::cross(RuntimeOrigin::signed(ALICE)), Error::::HasAlreadyCrossed); + assert_noop!( + Styx::cross(RuntimeOrigin::signed(ALICE)), + Error::::HasAlreadyCrossed + ); }); } diff --git a/zrml/swaps/src/tests.rs b/zrml/swaps/src/tests.rs index a5d8a2967..dfc16a2fc 100644 --- a/zrml/swaps/src/tests.rs +++ b/zrml/swaps/src/tests.rs @@ -1108,7 +1108,11 @@ fn pool_exit_decreases_correct_pool_parameters_on_cleaned_up_pool() { assert_ok!(Swaps::pool_join(alice_signed(), 0, _1, vec!(_1, _1, _1, _1),)); assert_ok!(Swaps::close_pool(0)); - assert_ok!(Swaps::admin_clean_up_pool(RuntimeOrigin::root(), 0, OutcomeReport::Categorical(65),)); + assert_ok!(Swaps::admin_clean_up_pool( + RuntimeOrigin::root(), + 0, + OutcomeReport::Categorical(65), + )); assert_ok!(Swaps::pool_exit(alice_signed(), 0, _1, vec!(_1, _1),)); System::assert_last_event( @@ -2920,7 +2924,13 @@ fn pool_exit_with_exact_pool_amount_fails_if_balances_drop_too_low() { )); assert_noop!( - Swaps::pool_exit_with_exact_pool_amount(RuntimeOrigin::signed(BOB), pool_id, ASSET_A, _1, 0), + Swaps::pool_exit_with_exact_pool_amount( + RuntimeOrigin::signed(BOB), + pool_id, + ASSET_A, + _1, + 0 + ), crate::Error::::PoolDrain, ); }); From 6223fb6bf3991069cb94c38c2cc2d97d988744cc Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Wed, 8 Feb 2023 15:18:59 +0530 Subject: [PATCH 04/22] Add migrations for parity pallets --- runtime/common/src/lib.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 2d6769dc7..471bd642d 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -58,7 +58,13 @@ macro_rules! decl_common_types { frame_system::ChainContext, Runtime, AllPalletsWithSystem, - zrml_prediction_markets::migrations::AddOutsiderBond, + ( + pallet_multisig::migrations::v1::MigrateToV1, + pallet_preimage::migration::v1::Migration, + pallet_democracy::migrations::v1::Migration, + pallet_scheduler::migration::v3::MigrateToV4, + zrml_prediction_markets::migrations::AddOutsiderBond, + ), >; #[cfg(not(feature = "parachain"))] @@ -68,7 +74,13 @@ macro_rules! decl_common_types { frame_system::ChainContext, Runtime, AllPalletsWithSystem, - zrml_prediction_markets::migrations::AddOutsiderBond, + ( + pallet_multisig::migrations::v1::MigrateToV1, + pallet_preimage::migration::v1::Migration, + pallet_democracy::migrations::v1::Migration, + pallet_scheduler::migration::v3::MigrateToV4, + zrml_prediction_markets::migrations::AddOutsiderBond, + ), >; pub type Header = generic::Header; From 6cd0a01ae2906e8ccbcc3b9a3d20cab1c5886f4b Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Wed, 8 Feb 2023 16:19:18 +0530 Subject: [PATCH 05/22] Set proof_size in MAXIMUM_BLOCK_WEIGHT to avoid test failures --- runtime/battery-station/Cargo.toml | 5 ++--- runtime/battery-station/src/parameters.rs | 3 ++- runtime/zeitgeist/Cargo.toml | 5 ++--- runtime/zeitgeist/src/parameters.rs | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/runtime/battery-station/Cargo.toml b/runtime/battery-station/Cargo.toml index 82d48c8cd..0dfe20cbb 100644 --- a/runtime/battery-station/Cargo.toml +++ b/runtime/battery-station/Cargo.toml @@ -95,7 +95,7 @@ orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, g orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } orml-xtokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } pallet-xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } -polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot" } polkadot-runtime-parachains = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm-builder = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } @@ -150,7 +150,6 @@ parachain = [ # XCM "kusama-runtime", - "polkadot-primitives", "polkadot-runtime-parachains", "orml-asset-registry", "orml-unknown-tokens", @@ -297,7 +296,7 @@ std = [ # XCM "kusama-runtime?/std", - "polkadot-primitives?/std", + "polkadot-primitives/std", "polkadot-runtime-parachains?/std", "orml-asset-registry?/std", "orml-unknown-tokens?/std", diff --git a/runtime/battery-station/src/parameters.rs b/runtime/battery-station/src/parameters.rs index 92e1191d1..4db908097 100644 --- a/runtime/battery-station/src/parameters.rs +++ b/runtime/battery-station/src/parameters.rs @@ -47,7 +47,8 @@ use frame_support::traits::LockIdentifier; pub(crate) const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); pub(crate) const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_ref_time(WEIGHT_PER_SECOND.ref_time() / 2); + Weight::from_ref_time(WEIGHT_PER_SECOND.ref_time() / 2) + .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); pub(crate) const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); pub(crate) const FEES_AND_TIPS_TREASURY_PERCENTAGE: u32 = 100; pub(crate) const FEES_AND_TIPS_BURN_PERCENTAGE: u32 = 0; diff --git a/runtime/zeitgeist/Cargo.toml b/runtime/zeitgeist/Cargo.toml index 65d7bc031..ec9db678a 100644 --- a/runtime/zeitgeist/Cargo.toml +++ b/runtime/zeitgeist/Cargo.toml @@ -93,7 +93,7 @@ orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, g orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } orml-xtokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } pallet-xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } -polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } +polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot" } polkadot-runtime-parachains = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm-builder = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } @@ -148,7 +148,6 @@ parachain = [ # XCM "kusama-runtime", - "polkadot-primitives", "polkadot-runtime-parachains", "orml-asset-registry", "orml-unknown-tokens", @@ -281,7 +280,7 @@ std = [ # XCM "kusama-runtime?/std", - "polkadot-primitives?/std", + "polkadot-primitives/std", "polkadot-runtime-parachains?/std", "orml-asset-registry?/std", "orml-unknown-tokens?/std", diff --git a/runtime/zeitgeist/src/parameters.rs b/runtime/zeitgeist/src/parameters.rs index 8ca41d088..cd7ff1736 100644 --- a/runtime/zeitgeist/src/parameters.rs +++ b/runtime/zeitgeist/src/parameters.rs @@ -47,7 +47,8 @@ use frame_support::traits::LockIdentifier; pub(crate) const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); pub(crate) const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_ref_time(WEIGHT_PER_SECOND.ref_time() / 2); + Weight::from_ref_time(WEIGHT_PER_SECOND.ref_time() / 2) + .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); pub(crate) const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); pub(crate) const FEES_AND_TIPS_TREASURY_PERCENTAGE: u32 = 100; pub(crate) const FEES_AND_TIPS_BURN_PERCENTAGE: u32 = 0; From df57c6116abb1c2dd0ca92ce13a184ec91afc1fd Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Wed, 8 Feb 2023 18:26:42 +0530 Subject: [PATCH 06/22] Update weights --- .../src/weights/cumulus_pallet_xcmp_queue.rs | 6 +- runtime/common/src/weights/frame_system.rs | 34 +-- runtime/common/src/weights/orml_currencies.rs | 12 +- runtime/common/src/weights/orml_tokens.rs | 12 +- .../src/weights/pallet_author_inherent.rs | 9 +- .../src/weights/pallet_author_mapping.rs | 17 +- .../src/weights/pallet_author_slot_filter.rs | 10 +- runtime/common/src/weights/pallet_balances.rs | 16 +- runtime/common/src/weights/pallet_bounties.rs | 36 ++-- .../common/src/weights/pallet_collective.rs | 104 +++++----- .../common/src/weights/pallet_democracy.rs | 175 ++++++---------- runtime/common/src/weights/pallet_identity.rs | 130 ++++++------ .../common/src/weights/pallet_membership.rs | 45 ++-- runtime/common/src/weights/pallet_multisig.rs | 115 ++++------- .../src/weights/pallet_parachain_staking.rs | 195 ++++++++++-------- runtime/common/src/weights/pallet_preimage.rs | 61 +++--- runtime/common/src/weights/pallet_proxy.rs | 97 +++++---- .../common/src/weights/pallet_scheduler.rs | 152 ++++---------- .../common/src/weights/pallet_timestamp.rs | 6 +- runtime/common/src/weights/pallet_treasury.rs | 22 +- runtime/common/src/weights/pallet_utility.rs | 24 +-- runtime/common/src/weights/pallet_vesting.rs | 68 +++--- zrml/authorized/src/weights.rs | 10 +- zrml/court/src/weights.rs | 8 +- zrml/global-disputes/src/weights.rs | 56 +++-- zrml/liquidity-mining/src/weights.rs | 4 +- zrml/prediction-markets/src/weights.rs | 193 ++++++++--------- zrml/styx/src/weights.rs | 6 +- zrml/swaps/src/weights.rs | 136 ++++++------ 29 files changed, 809 insertions(+), 950 deletions(-) diff --git a/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs b/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs index e0a20dbcd..fc7dd11ca 100644 --- a/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs +++ b/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for cumulus_pallet_xcmp_queue //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -50,13 +50,13 @@ pub struct WeightInfo(PhantomData); impl cumulus_pallet_xcmp_queue::weights::WeightInfo for WeightInfo { // Storage: XcmpQueue QueueConfig (r:1 w:1) fn set_config_with_u32() -> Weight { - Weight::from_ref_time(13_891_000) + Weight::from_ref_time(5_117_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: XcmpQueue QueueConfig (r:1 w:1) fn set_config_with_weight() -> Weight { - Weight::from_ref_time(13_630_000) + Weight::from_ref_time(4_929_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/runtime/common/src/weights/frame_system.rs b/runtime/common/src/weights/frame_system.rs index 0fce968ea..cc7c8e65f 100644 --- a/runtime/common/src/weights/frame_system.rs +++ b/runtime/common/src/weights/frame_system.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for frame_system //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -49,41 +49,41 @@ use frame_support::{ pub struct WeightInfo(PhantomData); impl frame_system::weights::WeightInfo for WeightInfo { fn remark(b: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000).saturating_mul(b.into())) + Weight::from_ref_time(14_250_344) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(221).saturating_mul(b.into())) } fn remark_with_event(b: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000).saturating_mul(b.into())) + Weight::from_ref_time(8_451_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(1_022).saturating_mul(b.into())) } // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - Weight::from_ref_time(15_370_000) + Weight::from_ref_time(5_344_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32) -> Weight { - Weight::from_ref_time(8_585_000) - // Standard Error: 8_000 - .saturating_add(Weight::from_ref_time(1_059_000).saturating_mul(i.into())) + Weight::from_ref_time(2_566_000) + // Standard Error: 641 + .saturating_add(Weight::from_ref_time(422_592).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 8_000 - .saturating_add(Weight::from_ref_time(1_075_000).saturating_mul(i.into())) + Weight::from_ref_time(171_591) + // Standard Error: 1_072 + .saturating_add(Weight::from_ref_time(374_557).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32) -> Weight { - Weight::from_ref_time(4_159_000) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(2_234_000).saturating_mul(p.into())) + Weight::from_ref_time(3_820_435) + // Standard Error: 1_116 + .saturating_add(Weight::from_ref_time(802_972).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } } diff --git a/runtime/common/src/weights/orml_currencies.rs b/runtime/common/src/weights/orml_currencies.rs index c628d5402..0ef0b1011 100644 --- a/runtime/common/src/weights/orml_currencies.rs +++ b/runtime/common/src/weights/orml_currencies.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for orml_currencies //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -48,13 +48,13 @@ impl orml_currencies::WeightInfo for WeightInfo { // Storage: Tokens Accounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_non_native_currency() -> Weight { - Weight::from_ref_time(76_920_000) + Weight::from_ref_time(32_440_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: System Account (r:1 w:1) fn transfer_native_currency() -> Weight { - Weight::from_ref_time(56_290_000) + Weight::from_ref_time(26_112_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -62,19 +62,19 @@ impl orml_currencies::WeightInfo for WeightInfo { // Storage: Tokens TotalIssuance (r:1 w:1) // Storage: System Account (r:1 w:1) fn update_balance_non_native_currency() -> Weight { - Weight::from_ref_time(53_350_000) + Weight::from_ref_time(21_841_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: System Account (r:1 w:1) fn update_balance_native_currency_creating() -> Weight { - Weight::from_ref_time(52_710_000) + Weight::from_ref_time(21_761_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn update_balance_native_currency_killing() -> Weight { - Weight::from_ref_time(48_730_000) + Weight::from_ref_time(19_903_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/runtime/common/src/weights/orml_tokens.rs b/runtime/common/src/weights/orml_tokens.rs index dc982cd42..43c0ecadd 100644 --- a/runtime/common/src/weights/orml_tokens.rs +++ b/runtime/common/src/weights/orml_tokens.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for orml_tokens //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -48,28 +48,28 @@ impl orml_tokens::WeightInfo for WeightInfo { // Storage: Tokens Accounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - Weight::from_ref_time(76_440_000) + Weight::from_ref_time(32_422_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Tokens Accounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - Weight::from_ref_time(78_740_000) + Weight::from_ref_time(33_839_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Tokens Accounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - Weight::from_ref_time(61_710_000) + Weight::from_ref_time(26_131_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Tokens Accounts (r:2 w:2) // Storage: System Account (r:2 w:1) fn force_transfer() -> Weight { - Weight::from_ref_time(68_460_000) + Weight::from_ref_time(29_017_000) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -77,7 +77,7 @@ impl orml_tokens::WeightInfo for WeightInfo { // Storage: Tokens TotalIssuance (r:1 w:1) // Storage: System Account (r:1 w:1) fn set_balance() -> Weight { - Weight::from_ref_time(51_830_000) + Weight::from_ref_time(21_766_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/runtime/common/src/weights/pallet_author_inherent.rs b/runtime/common/src/weights/pallet_author_inherent.rs index e1689a0a6..c06de9694 100644 --- a/runtime/common/src/weights/pallet_author_inherent.rs +++ b/runtime/common/src/weights/pallet_author_inherent.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_author_inherent //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,11 +39,8 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_author_inherent (automatically generated) pub struct WeightInfo(PhantomData); @@ -55,7 +52,7 @@ impl pallet_author_inherent::weights::WeightInfo for We // Storage: AuthorFilter EligibleCount (r:1 w:0) // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) fn kick_off_authorship_validation() -> Weight { - Weight::from_ref_time(47_670_000) + Weight::from_ref_time(17_682_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/runtime/common/src/weights/pallet_author_mapping.rs b/runtime/common/src/weights/pallet_author_mapping.rs index 9dc310e71..4c1090caa 100644 --- a/runtime/common/src/weights/pallet_author_mapping.rs +++ b/runtime/common/src/weights/pallet_author_mapping.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_author_mapping //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,11 +39,8 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_author_mapping (automatically generated) pub struct WeightInfo(PhantomData); @@ -52,14 +49,14 @@ impl pallet_author_mapping::weights::WeightInfo for Wei // Storage: System Account (r:1 w:1) // Storage: AuthorMapping NimbusLookup (r:0 w:1) fn add_association() -> Weight { - Weight::from_ref_time(59_320_000) + Weight::from_ref_time(22_888_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) // Storage: AuthorMapping NimbusLookup (r:0 w:1) fn update_association() -> Weight { - Weight::from_ref_time(42_141_000) + Weight::from_ref_time(19_480_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -67,7 +64,7 @@ impl pallet_author_mapping::weights::WeightInfo for Wei // Storage: System Account (r:1 w:1) // Storage: AuthorMapping NimbusLookup (r:0 w:1) fn clear_association() -> Weight { - Weight::from_ref_time(54_180_000) + Weight::from_ref_time(25_500_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -75,14 +72,14 @@ impl pallet_author_mapping::weights::WeightInfo for Wei // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) // Storage: System Account (r:1 w:1) fn remove_keys() -> Weight { - Weight::from_ref_time(66_530_000) + Weight::from_ref_time(28_334_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: AuthorMapping NimbusLookup (r:1 w:1) // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) fn set_keys() -> Weight { - Weight::from_ref_time(52_730_000) + Weight::from_ref_time(21_788_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/runtime/common/src/weights/pallet_author_slot_filter.rs b/runtime/common/src/weights/pallet_author_slot_filter.rs index 9ee05ed69..c2179a461 100644 --- a/runtime/common/src/weights/pallet_author_slot_filter.rs +++ b/runtime/common/src/weights/pallet_author_slot_filter.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_author_slot_filter //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,17 +39,15 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_author_slot_filter (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_author_slot_filter::weights::WeightInfo for WeightInfo { // Storage: AuthorFilter EligibleCount (r:0 w:1) fn set_eligible() -> Weight { - Weight::from_ref_time(24_640_000).saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(9_073_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/common/src/weights/pallet_balances.rs b/runtime/common/src/weights/pallet_balances.rs index 0ed3df5a3..8fb8592a5 100644 --- a/runtime/common/src/weights/pallet_balances.rs +++ b/runtime/common/src/weights/pallet_balances.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_balances //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -50,43 +50,43 @@ pub struct WeightInfo(PhantomData); impl pallet_balances::weights::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - Weight::from_ref_time(75_550_000) + Weight::from_ref_time(31_432_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - Weight::from_ref_time(61_350_000) + Weight::from_ref_time(23_506_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - Weight::from_ref_time(44_461_000) + Weight::from_ref_time(17_067_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - Weight::from_ref_time(47_560_000) + Weight::from_ref_time(19_078_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - Weight::from_ref_time(74_281_000) + Weight::from_ref_time(31_192_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - Weight::from_ref_time(65_200_000) + Weight::from_ref_time(26_679_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - Weight::from_ref_time(37_050_000) + Weight::from_ref_time(14_123_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/runtime/common/src/weights/pallet_bounties.rs b/runtime/common/src/weights/pallet_bounties.rs index 6d3e90d50..594f1170c 100644 --- a/runtime/common/src/weights/pallet_bounties.rs +++ b/runtime/common/src/weights/pallet_bounties.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_bounties //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -52,42 +52,42 @@ impl pallet_bounties::weights::WeightInfo for WeightInf // Storage: Bounties BountyDescriptions (r:0 w:1) // Storage: Bounties Bounties (r:0 w:1) fn propose_bounty(d: u32) -> Weight { - Weight::from_ref_time(54_421_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000).saturating_mul(d.into())) + Weight::from_ref_time(22_070_891) + // Standard Error: 7 + .saturating_add(Weight::from_ref_time(513).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - Weight::from_ref_time(28_180_000) + Weight::from_ref_time(9_036_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - Weight::from_ref_time(23_090_000) + Weight::from_ref_time(8_789_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - Weight::from_ref_time(61_871_000) + Weight::from_ref_time(25_810_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - Weight::from_ref_time(51_330_000) + Weight::from_ref_time(21_446_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:1) fn award_bounty() -> Weight { - Weight::from_ref_time(47_600_000) + Weight::from_ref_time(16_247_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -95,14 +95,14 @@ impl pallet_bounties::weights::WeightInfo for WeightInf // Storage: System Account (r:3 w:3) // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - Weight::from_ref_time(116_790_000) + Weight::from_ref_time(50_791_000) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - Weight::from_ref_time(63_830_000) + Weight::from_ref_time(26_410_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -110,23 +110,23 @@ impl pallet_bounties::weights::WeightInfo for WeightInf // Storage: System Account (r:3 w:3) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - Weight::from_ref_time(90_651_000) + Weight::from_ref_time(39_490_000) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - Weight::from_ref_time(40_350_000) + Weight::from_ref_time(16_379_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Bounties BountyApprovals (r:1 w:1) - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Storage: Bounties Bounties (r:2 w:2) + // Storage: System Account (r:3 w:3) fn spend_funds(b: u32) -> Weight { - Weight::from_ref_time(24_132_000) - // Standard Error: 235_000 - .saturating_add(Weight::from_ref_time(46_899_000).saturating_mul(b.into())) + Weight::from_ref_time(19_140_664) + // Standard Error: 26_913 + .saturating_add(Weight::from_ref_time(18_448_072).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) } diff --git a/runtime/common/src/weights/pallet_collective.rs b/runtime/common/src/weights/pallet_collective.rs index b4818d13b..b69afa018 100644 --- a/runtime/common/src/weights/pallet_collective.rs +++ b/runtime/common/src/weights/pallet_collective.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_collective //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -50,16 +50,14 @@ pub struct WeightInfo(PhantomData); impl pallet_collective::weights::WeightInfo for WeightInfo { // Storage: AdvisoryCommittee Members (r:1 w:1) // Storage: AdvisoryCommittee Proposals (r:1 w:0) - // Storage: AdvisoryCommittee Voting (r:255 w:255) // Storage: AdvisoryCommittee Prime (r:0 w:1) - fn set_members(m: u32, n: u32, p: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 195_000 - .saturating_add(Weight::from_ref_time(41_182_000).saturating_mul(m.into())) - // Standard Error: 195_000 - .saturating_add(Weight::from_ref_time(210_000).saturating_mul(n.into())) - // Standard Error: 76_000 - .saturating_add(Weight::from_ref_time(21_533_000).saturating_mul(p.into())) + // Storage: AdvisoryCommittee Voting (r:255 w:255) + fn set_members(m: u32, _n: u32, p: u32) -> Weight { + Weight::from_ref_time(12_092_000) + // Standard Error: 120_533 + .saturating_add(Weight::from_ref_time(9_830_156).saturating_mul(m.into())) + // Standard Error: 47_324 + .saturating_add(Weight::from_ref_time(5_530_913).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -67,21 +65,21 @@ impl pallet_collective::weights::WeightInfo for WeightI } // Storage: AdvisoryCommittee Members (r:1 w:0) fn execute(b: u32, m: u32) -> Weight { - Weight::from_ref_time(38_237_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(b.into())) - // Standard Error: 3_000 - .saturating_add(Weight::from_ref_time(40_000).saturating_mul(m.into())) + Weight::from_ref_time(13_910_710) + // Standard Error: 39 + .saturating_add(Weight::from_ref_time(1_329).saturating_mul(b.into())) + // Standard Error: 409 + .saturating_add(Weight::from_ref_time(13_307).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(1)) } // Storage: AdvisoryCommittee Members (r:1 w:0) // Storage: AdvisoryCommittee ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32) -> Weight { - Weight::from_ref_time(44_582_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(b.into())) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(14_000).saturating_mul(m.into())) + Weight::from_ref_time(15_156_779) + // Standard Error: 36 + .saturating_add(Weight::from_ref_time(1_439).saturating_mul(b.into())) + // Standard Error: 378 + .saturating_add(Weight::from_ref_time(17_083).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2)) } // Storage: AdvisoryCommittee Members (r:1 w:0) @@ -90,22 +88,22 @@ impl pallet_collective::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee ProposalCount (r:1 w:1) // Storage: AdvisoryCommittee Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32) -> Weight { - Weight::from_ref_time(37_436_000) - // Standard Error: 1_000 - .saturating_add(Weight::from_ref_time(20_000).saturating_mul(b.into())) - // Standard Error: 11_000 - .saturating_add(Weight::from_ref_time(39_000).saturating_mul(m.into())) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(279_000).saturating_mul(p.into())) + Weight::from_ref_time(22_819_241) + // Standard Error: 354 + .saturating_add(Weight::from_ref_time(4_011).saturating_mul(b.into())) + // Standard Error: 3_707 + .saturating_add(Weight::from_ref_time(35_095).saturating_mul(m.into())) + // Standard Error: 1_427 + .saturating_add(Weight::from_ref_time(90_320).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } // Storage: AdvisoryCommittee Members (r:1 w:0) // Storage: AdvisoryCommittee Voting (r:1 w:1) fn vote(m: u32) -> Weight { - Weight::from_ref_time(75_377_000) - // Standard Error: 18_000 - .saturating_add(Weight::from_ref_time(454_000).saturating_mul(m.into())) + Weight::from_ref_time(34_942_963) + // Standard Error: 5_250 + .saturating_add(Weight::from_ref_time(43_923).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -114,9 +112,9 @@ impl pallet_collective::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Proposals (r:1 w:1) // Storage: AdvisoryCommittee ProposalOf (r:0 w:1) fn close_early_disapproved(_m: u32, p: u32) -> Weight { - Weight::from_ref_time(125_780_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(208_000).saturating_mul(p.into())) + Weight::from_ref_time(31_521_383) + // Standard Error: 1_768 + .saturating_add(Weight::from_ref_time(91_263).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -125,13 +123,13 @@ impl pallet_collective::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee ProposalOf (r:1 w:1) // Storage: AdvisoryCommittee Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32) -> Weight { - Weight::from_ref_time(50_328_000) - // Standard Error: 1_000 - .saturating_add(Weight::from_ref_time(14_000).saturating_mul(b.into())) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(134_000).saturating_mul(m.into())) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(320_000).saturating_mul(p.into())) + Weight::from_ref_time(27_750_291) + // Standard Error: 381 + .saturating_add(Weight::from_ref_time(3_284).saturating_mul(b.into())) + // Standard Error: 4_030 + .saturating_add(Weight::from_ref_time(77_635).saturating_mul(m.into())) + // Standard Error: 1_532 + .saturating_add(Weight::from_ref_time(101_653).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -141,9 +139,9 @@ impl pallet_collective::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Proposals (r:1 w:1) // Storage: AdvisoryCommittee ProposalOf (r:0 w:1) fn close_disapproved(_m: u32, p: u32) -> Weight { - Weight::from_ref_time(77_551_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(224_000).saturating_mul(p.into())) + Weight::from_ref_time(35_447_953) + // Standard Error: 1_843 + .saturating_add(Weight::from_ref_time(82_511).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -153,13 +151,13 @@ impl pallet_collective::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee ProposalOf (r:1 w:1) // Storage: AdvisoryCommittee Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32) -> Weight { - Weight::from_ref_time(23_404_000) - // Standard Error: 1_000 - .saturating_add(Weight::from_ref_time(30_000).saturating_mul(b.into())) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(288_000).saturating_mul(m.into())) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(360_000).saturating_mul(p.into())) + Weight::from_ref_time(32_560_116) + // Standard Error: 378 + .saturating_add(Weight::from_ref_time(1_465).saturating_mul(b.into())) + // Standard Error: 4_008 + .saturating_add(Weight::from_ref_time(62_930).saturating_mul(m.into())) + // Standard Error: 1_523 + .saturating_add(Weight::from_ref_time(101_811).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -167,9 +165,9 @@ impl pallet_collective::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Voting (r:0 w:1) // Storage: AdvisoryCommittee ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32) -> Weight { - Weight::from_ref_time(48_539_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(202_000).saturating_mul(p.into())) + Weight::from_ref_time(20_281_170) + // Standard Error: 1_763 + .saturating_add(Weight::from_ref_time(84_565).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/runtime/common/src/weights/pallet_democracy.rs b/runtime/common/src/weights/pallet_democracy.rs index cf952bf8f..2083a31cb 100644 --- a/runtime/common/src/weights/pallet_democracy.rs +++ b/runtime/common/src/weights/pallet_democracy.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_democracy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,11 +39,8 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_democracy (automatically generated) pub struct WeightInfo(PhantomData); @@ -53,122 +50,102 @@ impl pallet_democracy::weights::WeightInfo for WeightIn // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - Weight::from_ref_time(85_600_000) + Weight::from_ref_time(41_898_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy DepositOf (r:1 w:1) - fn second(s: u32) -> Weight { - Weight::from_ref_time(60_373_000) - // Standard Error: 7_000 - .saturating_add(Weight::from_ref_time(160_000).saturating_mul(s.into())) + fn second() -> Weight { + Weight::from_ref_time(35_120_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn vote_new(r: u32) -> Weight { - Weight::from_ref_time(82_360_000) - // Standard Error: 16_000 - .saturating_add(Weight::from_ref_time(175_000).saturating_mul(r.into())) + fn vote_new() -> Weight { + Weight::from_ref_time(41_886_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn vote_existing(r: u32) -> Weight { - Weight::from_ref_time(78_219_000) - // Standard Error: 11_000 - .saturating_add(Weight::from_ref_time(234_000).saturating_mul(r.into())) + fn vote_existing() -> Weight { + Weight::from_ref_time(41_576_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - Weight::from_ref_time(40_670_000) + Weight::from_ref_time(14_658_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) + // Storage: Democracy DepositOf (r:1 w:1) + // Storage: System Account (r:2 w:2) // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Blacklist (r:0 w:1) - // Storage: Democracy DepositOf (r:1 w:1) - // Storage: System Account (r:2 w:2) - fn blacklist(p: u32) -> Weight { - Weight::from_ref_time(105_157_000) - // Standard Error: 22_000 - .saturating_add(Weight::from_ref_time(412_000).saturating_mul(p.into())) + fn blacklist() -> Weight { + Weight::from_ref_time(67_163_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) - fn external_propose(v: u32) -> Weight { - Weight::from_ref_time(31_020_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(16_000).saturating_mul(v.into())) + fn external_propose() -> Weight { + Weight::from_ref_time(11_206_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - Weight::from_ref_time(10_040_000).saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(3_060_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - Weight::from_ref_time(9_880_000).saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(3_068_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - Weight::from_ref_time(40_500_000) + Weight::from_ref_time(15_630_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) - fn veto_external(v: u32) -> Weight { - Weight::from_ref_time(44_735_000) - // Standard Error: 3_000 - .saturating_add(Weight::from_ref_time(37_000).saturating_mul(v.into())) + fn veto_external() -> Weight { + Weight::from_ref_time(19_253_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) - fn cancel_proposal(p: u32) -> Weight { - Weight::from_ref_time(86_644_000) - // Standard Error: 12_000 - .saturating_add(Weight::from_ref_time(307_000).saturating_mul(p.into())) + fn cancel_proposal() -> Weight { + Weight::from_ref_time(58_487_000) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - Weight::from_ref_time(43_850_000).saturating_add(T::DbWeight::get().writes(1)) - } - // Storage: Scheduler Lookup (r:1 w:1) - // Storage: Scheduler Agenda (r:1 w:1) - fn cancel_queued(r: u32) -> Weight { - Weight::from_ref_time(49_773_000) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(801_000).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + Weight::from_ref_time(9_790_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) - // Storage: Democracy ReferendumInfoOf (r:1 w:0) - fn on_initialize_base(r: u32) -> Weight { - Weight::from_ref_time(29_677_000) - // Standard Error: 32_000 - .saturating_add(Weight::from_ref_time(3_533_000).saturating_mul(r.into())) + // Storage: Democracy ReferendumInfoOf (r:2 w:0) + fn on_initialize_base(r: u32, ) -> Weight { + Weight::from_ref_time(8_978_113) + // Standard Error: 4_589 + .saturating_add(Weight::from_ref_time(1_536_205).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(1)) @@ -178,33 +155,33 @@ impl pallet_democracy::weights::WeightInfo for WeightIn // Storage: Democracy LastTabledWasExternal (r:1 w:0) // Storage: Democracy NextExternal (r:1 w:0) // Storage: Democracy PublicProps (r:1 w:0) - // Storage: Democracy ReferendumInfoOf (r:1 w:0) - fn on_initialize_base_with_launch_period(r: u32) -> Weight { - Weight::from_ref_time(31_642_000) - // Standard Error: 31_000 - .saturating_add(Weight::from_ref_time(3_606_000).saturating_mul(r.into())) + // Storage: Democracy ReferendumInfoOf (r:2 w:0) + fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { + Weight::from_ref_time(10_988_037) + // Standard Error: 4_483 + .saturating_add(Weight::from_ref_time(1_538_250).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:3 w:3) - // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn delegate(r: u32) -> Weight { - Weight::from_ref_time(92_827_000) - // Standard Error: 52_000 - .saturating_add(Weight::from_ref_time(5_479_000).saturating_mul(r.into())) + // Storage: Democracy ReferendumInfoOf (r:2 w:2) + fn delegate(r: u32, ) -> Weight { + Weight::from_ref_time(33_942_458) + // Standard Error: 6_275 + .saturating_add(Weight::from_ref_time(2_384_438).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) } // Storage: Democracy VotingOf (r:2 w:2) - // Storage: Democracy ReferendumInfoOf (r:1 w:1) - fn undelegate(r: u32) -> Weight { - Weight::from_ref_time(51_753_000) - // Standard Error: 59_000 - .saturating_add(Weight::from_ref_time(5_388_000).saturating_mul(r.into())) + // Storage: Democracy ReferendumInfoOf (r:2 w:2) + fn undelegate(r: u32, ) -> Weight { + Weight::from_ref_time(20_552_008) + // Standard Error: 4_945 + .saturating_add(Weight::from_ref_time(2_352_801).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -212,68 +189,44 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - Weight::from_ref_time(10_700_000).saturating_add(T::DbWeight::get().writes(1)) - } - // Storage: Democracy Preimages (r:1 w:1) - fn note_preimage(b: u32) -> Weight { - Weight::from_ref_time(54_036_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - // Storage: Democracy Preimages (r:1 w:1) - fn note_imminent_preimage(b: u32) -> Weight { - Weight::from_ref_time(42_055_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(1)) + Weight::from_ref_time(4_079_000) .saturating_add(T::DbWeight::get().writes(1)) } - // Storage: Democracy Preimages (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn reap_preimage(b: u32) -> Weight { - Weight::from_ref_time(71_620_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_remove(r: u32) -> Weight { - Weight::from_ref_time(57_238_000) - // Standard Error: 8_000 - .saturating_add(Weight::from_ref_time(146_000).saturating_mul(r.into())) + fn unlock_remove(r: u32, ) -> Weight { + Weight::from_ref_time(23_309_726) + // Standard Error: 1_610 + .saturating_add(Weight::from_ref_time(51_836).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_set(r: u32) -> Weight { - Weight::from_ref_time(55_627_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(214_000).saturating_mul(r.into())) + fn unlock_set(r: u32, ) -> Weight { + Weight::from_ref_time(23_116_641) + // Standard Error: 932 + .saturating_add(Weight::from_ref_time(78_997).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) - fn remove_vote(r: u32) -> Weight { - Weight::from_ref_time(35_445_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(251_000).saturating_mul(r.into())) + fn remove_vote(r: u32, ) -> Weight { + Weight::from_ref_time(13_637_289) + // Standard Error: 991 + .saturating_add(Weight::from_ref_time(83_991).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) - fn remove_other_vote(r: u32) -> Weight { - Weight::from_ref_time(36_669_000) - // Standard Error: 7_000 - .saturating_add(Weight::from_ref_time(221_000).saturating_mul(r.into())) + fn remove_other_vote(r: u32, ) -> Weight { + Weight::from_ref_time(14_220_574) + // Standard Error: 3_420 + .saturating_add(Weight::from_ref_time(81_496).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } diff --git a/runtime/common/src/weights/pallet_identity.rs b/runtime/common/src/weights/pallet_identity.rs index 75988386b..c432ae380 100644 --- a/runtime/common/src/weights/pallet_identity.rs +++ b/runtime/common/src/weights/pallet_identity.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_identity //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -50,19 +50,19 @@ pub struct WeightInfo(PhantomData); impl pallet_identity::weights::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32) -> Weight { - Weight::from_ref_time(32_453_000) - // Standard Error: 71_000 - .saturating_add(Weight::from_ref_time(830_000).saturating_mul(r.into())) + Weight::from_ref_time(12_045_217) + // Standard Error: 5_701 + .saturating_add(Weight::from_ref_time(411_913).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32) -> Weight { - Weight::from_ref_time(57_592_000) - // Standard Error: 79_000 - .saturating_add(Weight::from_ref_time(453_000).saturating_mul(r.into())) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(614_000).saturating_mul(x.into())) + Weight::from_ref_time(23_218_766) + // Standard Error: 21_173 + .saturating_add(Weight::from_ref_time(396_383).saturating_mul(r.into())) + // Standard Error: 2_459 + .saturating_add(Weight::from_ref_time(216_337).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -70,9 +70,9 @@ impl pallet_identity::weights::WeightInfo for WeightInf // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32) -> Weight { - Weight::from_ref_time(57_926_000) - // Standard Error: 76_000 - .saturating_add(Weight::from_ref_time(4_193_000).saturating_mul(s.into())) + Weight::from_ref_time(20_621_097) + // Standard Error: 5_753 + .saturating_add(Weight::from_ref_time(1_822_204).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1)) @@ -82,9 +82,9 @@ impl pallet_identity::weights::WeightInfo for WeightInf // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32) -> Weight { - Weight::from_ref_time(50_949_000) - // Standard Error: 12_000 - .saturating_add(Weight::from_ref_time(1_846_000).saturating_mul(p.into())) + Weight::from_ref_time(21_538_109) + // Standard Error: 5_896 + .saturating_add(Weight::from_ref_time(819_934).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) @@ -93,64 +93,70 @@ impl pallet_identity::weights::WeightInfo for WeightInf // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:64) fn clear_identity(r: u32, s: u32, x: u32) -> Weight { - Weight::from_ref_time(61_225_000) - // Standard Error: 216_000 - .saturating_add(Weight::from_ref_time(442_000).saturating_mul(r.into())) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(1_828_000).saturating_mul(s.into())) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(236_000).saturating_mul(x.into())) + Weight::from_ref_time(24_817_395) + // Standard Error: 18_666 + .saturating_add(Weight::from_ref_time(261_241).saturating_mul(r.into())) + // Standard Error: 2_173 + .saturating_add(Weight::from_ref_time(813_003).saturating_mul(s.into())) + // Standard Error: 2_173 + .saturating_add(Weight::from_ref_time(97_431).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) - fn request_judgement(_r: u32, x: u32) -> Weight { - Weight::from_ref_time(68_611_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(616_000).saturating_mul(x.into())) + fn request_judgement(r: u32, x: u32) -> Weight { + Weight::from_ref_time(24_883_132) + // Standard Error: 8_677 + .saturating_add(Weight::from_ref_time(391_028).saturating_mul(r.into())) + // Standard Error: 1_007 + .saturating_add(Weight::from_ref_time(209_582).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:1) - fn cancel_request(_r: u32, x: u32) -> Weight { - Weight::from_ref_time(75_094_000) - // Standard Error: 16_000 - .saturating_add(Weight::from_ref_time(550_000).saturating_mul(x.into())) + fn cancel_request(r: u32, x: u32) -> Weight { + Weight::from_ref_time(23_411_702) + // Standard Error: 8_263 + .saturating_add(Weight::from_ref_time(261_255).saturating_mul(r.into())) + // Standard Error: 959 + .saturating_add(Weight::from_ref_time(207_342).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32) -> Weight { - Weight::from_ref_time(18_492_000) - // Standard Error: 28_000 - .saturating_add(Weight::from_ref_time(339_000).saturating_mul(r.into())) + Weight::from_ref_time(6_373_117) + // Standard Error: 3_180 + .saturating_add(Weight::from_ref_time(272_816).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32) -> Weight { - Weight::from_ref_time(17_817_000) - // Standard Error: 52_000 - .saturating_add(Weight::from_ref_time(709_000).saturating_mul(r.into())) + Weight::from_ref_time(6_536_881) + // Standard Error: 3_217 + .saturating_add(Weight::from_ref_time(268_060).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) - fn set_fields(_r: u32) -> Weight { - Weight::from_ref_time(20_985_000) + fn set_fields(r: u32) -> Weight { + Weight::from_ref_time(6_379_872) + // Standard Error: 3_198 + .saturating_add(Weight::from_ref_time(284_984).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32) -> Weight { - Weight::from_ref_time(44_404_000) - // Standard Error: 84_000 - .saturating_add(Weight::from_ref_time(865_000).saturating_mul(r.into())) - // Standard Error: 8_000 - .saturating_add(Weight::from_ref_time(993_000).saturating_mul(x.into())) + Weight::from_ref_time(18_544_167) + // Standard Error: 8_411 + .saturating_add(Weight::from_ref_time(298_269).saturating_mul(r.into())) + // Standard Error: 859 + .saturating_add(Weight::from_ref_time(347_720).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -158,12 +164,14 @@ impl pallet_identity::weights::WeightInfo for WeightInf // Storage: Identity IdentityOf (r:1 w:1) // Storage: System Account (r:2 w:2) // Storage: Identity SuperOf (r:0 w:64) - fn kill_identity(_r: u32, s: u32, x: u32) -> Weight { - Weight::from_ref_time(109_373_000) - // Standard Error: 31_000 - .saturating_add(Weight::from_ref_time(1_657_000).saturating_mul(s.into())) - // Standard Error: 31_000 - .saturating_add(Weight::from_ref_time(75_000).saturating_mul(x.into())) + fn kill_identity(r: u32, s: u32, x: u32) -> Weight { + Weight::from_ref_time(33_739_768) + // Standard Error: 21_993 + .saturating_add(Weight::from_ref_time(179_160).saturating_mul(r.into())) + // Standard Error: 2_560 + .saturating_add(Weight::from_ref_time(816_776).saturating_mul(s.into())) + // Standard Error: 2_560 + .saturating_add(Weight::from_ref_time(93_630).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -172,18 +180,18 @@ impl pallet_identity::weights::WeightInfo for WeightInf // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32) -> Weight { - Weight::from_ref_time(75_288_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(50_000).saturating_mul(s.into())) + Weight::from_ref_time(26_774_459) + // Standard Error: 2_099 + .saturating_add(Weight::from_ref_time(142_653).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32) -> Weight { - Weight::from_ref_time(29_243_000) - // Standard Error: 11_000 - .saturating_add(Weight::from_ref_time(188_000).saturating_mul(s.into())) + Weight::from_ref_time(11_263_610) + // Standard Error: 1_038 + .saturating_add(Weight::from_ref_time(68_019).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -191,18 +199,18 @@ impl pallet_identity::weights::WeightInfo for WeightInf // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32) -> Weight { - Weight::from_ref_time(71_661_000) - // Standard Error: 15_000 - .saturating_add(Weight::from_ref_time(227_000).saturating_mul(s.into())) + Weight::from_ref_time(29_027_542) + // Standard Error: 2_964 + .saturating_add(Weight::from_ref_time(102_862).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32) -> Weight { - Weight::from_ref_time(57_480_000) - // Standard Error: 17_000 - .saturating_add(Weight::from_ref_time(184_000).saturating_mul(s.into())) + Weight::from_ref_time(20_501_723) + // Standard Error: 1_836 + .saturating_add(Weight::from_ref_time(126_775).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } diff --git a/runtime/common/src/weights/pallet_membership.rs b/runtime/common/src/weights/pallet_membership.rs index 3f0f627bd..cb9558f31 100644 --- a/runtime/common/src/weights/pallet_membership.rs +++ b/runtime/common/src/weights/pallet_membership.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_membership //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -53,9 +53,9 @@ impl pallet_membership::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Members (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) fn add_member(m: u32) -> Weight { - Weight::from_ref_time(44_484_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(37_000).saturating_mul(m.into())) + Weight::from_ref_time(15_790_016) + // Standard Error: 647 + .saturating_add(Weight::from_ref_time(31_177).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -65,9 +65,9 @@ impl pallet_membership::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Members (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) fn remove_member(m: u32) -> Weight { - Weight::from_ref_time(47_524_000) - // Standard Error: 6_000 - .saturating_add(Weight::from_ref_time(77_000).saturating_mul(m.into())) + Weight::from_ref_time(17_898_825) + // Standard Error: 616 + .saturating_add(Weight::from_ref_time(27_596).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -77,9 +77,9 @@ impl pallet_membership::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Members (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) fn swap_member(m: u32) -> Weight { - Weight::from_ref_time(46_637_000) - // Standard Error: 6_000 - .saturating_add(Weight::from_ref_time(128_000).saturating_mul(m.into())) + Weight::from_ref_time(17_795_029) + // Standard Error: 628 + .saturating_add(Weight::from_ref_time(36_370).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -89,9 +89,9 @@ impl pallet_membership::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Members (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) fn reset_member(m: u32) -> Weight { - Weight::from_ref_time(46_814_000) - // Standard Error: 7_000 - .saturating_add(Weight::from_ref_time(267_000).saturating_mul(m.into())) + Weight::from_ref_time(17_561_643) + // Standard Error: 691 + .saturating_add(Weight::from_ref_time(104_626).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -101,9 +101,9 @@ impl pallet_membership::weights::WeightInfo for WeightI // Storage: AdvisoryCommittee Members (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) fn change_key(m: u32) -> Weight { - Weight::from_ref_time(48_470_000) - // Standard Error: 6_000 - .saturating_add(Weight::from_ref_time(89_000).saturating_mul(m.into())) + Weight::from_ref_time(18_510_706) + // Standard Error: 686 + .saturating_add(Weight::from_ref_time(34_672).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -111,15 +111,18 @@ impl pallet_membership::weights::WeightInfo for WeightI // Storage: AdvisoryCommitteeMembership Prime (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) fn set_prime(m: u32) -> Weight { - Weight::from_ref_time(18_199_000) - // Standard Error: 6_000 - .saturating_add(Weight::from_ref_time(72_000).saturating_mul(m.into())) + Weight::from_ref_time(6_527_451) + // Standard Error: 269 + .saturating_add(Weight::from_ref_time(10_485).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: AdvisoryCommitteeMembership Prime (r:0 w:1) // Storage: AdvisoryCommittee Prime (r:0 w:1) - fn clear_prime(_m: u32) -> Weight { - Weight::from_ref_time(11_622_000).saturating_add(T::DbWeight::get().writes(2)) + fn clear_prime(m: u32) -> Weight { + Weight::from_ref_time(3_713_794) + // Standard Error: 136 + .saturating_add(Weight::from_ref_time(834).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/common/src/weights/pallet_multisig.rs b/runtime/common/src/weights/pallet_multisig.rs index d2dce8294..11934552e 100644 --- a/runtime/common/src/weights/pallet_multisig.rs +++ b/runtime/common/src/weights/pallet_multisig.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_multisig //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,109 +39,72 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_multisig (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_multisig::weights::WeightInfo for WeightInfo { - fn as_multi_threshold_1(z: u32) -> Weight { - Weight::from_ref_time(40_350_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000).saturating_mul(z.into())) + fn as_multi_threshold_1(z: u32, ) -> Weight { + Weight::from_ref_time(15_009_826) + // Standard Error: 4 + .saturating_add(Weight::from_ref_time(279).saturating_mul(z.into())) } // Storage: MultiSig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) - fn as_multi_create(_s: u32, z: u32) -> Weight { - Weight::from_ref_time(98_340_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000).saturating_mul(z.into())) + fn as_multi_create(s: u32, z: u32, ) -> Weight { + Weight::from_ref_time(26_652_211) + // Standard Error: 1_415 + .saturating_add(Weight::from_ref_time(94_659).saturating_mul(s.into())) + // Standard Error: 13 + .saturating_add(Weight::from_ref_time(1_052).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - // Storage: MultiSig Calls (r:1 w:1) - // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) - fn as_multi_create_store(s: u32, z: u32) -> Weight { - Weight::from_ref_time(89_465_000) - // Standard Error: 19_000 - .saturating_add(Weight::from_ref_time(14_000).saturating_mul(s.into())) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000).saturating_mul(z.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) - } - // Storage: MultiSig Multisigs (r:1 w:1) - fn as_multi_approve(s: u32, z: u32) -> Weight { - Weight::from_ref_time(48_826_000) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(139_000).saturating_mul(s.into())) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000).saturating_mul(z.into())) + fn as_multi_approve(s: u32, z: u32, ) -> Weight { + Weight::from_ref_time(20_049_942) + // Standard Error: 908 + .saturating_add(Weight::from_ref_time(84_603).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_ref_time(995).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - // Storage: MultiSig Calls (r:1 w:1) - fn as_multi_approve_store(s: u32, z: u32) -> Weight { - Weight::from_ref_time(73_692_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(110_000).saturating_mul(s.into())) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(z.into())) + // Storage: System Account (r:1 w:1) + fn as_multi_complete(s: u32, z: u32, ) -> Weight { + Weight::from_ref_time(27_852_359) + // Standard Error: 1_356 + .saturating_add(Weight::from_ref_time(117_468).saturating_mul(s.into())) + // Standard Error: 13 + .saturating_add(Weight::from_ref_time(1_031).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: MultiSig Multisigs (r:1 w:1) - // Storage: MultiSig Calls (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn as_multi_complete(s: u32, z: u32) -> Weight { - Weight::from_ref_time(91_645_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(105_000).saturating_mul(s.into())) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(z.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - // Storage: MultiSig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) - fn approve_as_multi_create(s: u32) -> Weight { - Weight::from_ref_time(59_874_000) - // Standard Error: 6_000 - .saturating_add(Weight::from_ref_time(182_000).saturating_mul(s.into())) + fn approve_as_multi_create(s: u32, ) -> Weight { + Weight::from_ref_time(24_697_515) + // Standard Error: 1_850 + .saturating_add(Weight::from_ref_time(97_497).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - // Storage: MultiSig Calls (r:1 w:0) - fn approve_as_multi_approve(s: u32) -> Weight { - Weight::from_ref_time(43_800_000) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(173_000).saturating_mul(s.into())) + fn approve_as_multi_approve(s: u32, ) -> Weight { + Weight::from_ref_time(17_670_882) + // Standard Error: 1_328 + .saturating_add(Weight::from_ref_time(94_493).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - // Storage: MultiSig Calls (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn approve_as_multi_complete(s: u32) -> Weight { - Weight::from_ref_time(103_694_000) - // Standard Error: 17_000 - .saturating_add(Weight::from_ref_time(194_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - // Storage: MultiSig Multisigs (r:1 w:1) - // Storage: MultiSig Calls (r:1 w:1) - fn cancel_as_multi(s: u32) -> Weight { - Weight::from_ref_time(89_339_000) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(197_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + fn cancel_as_multi(s: u32, ) -> Weight { + Weight::from_ref_time(24_687_555) + // Standard Error: 1_647 + .saturating_add(Weight::from_ref_time(108_089).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/common/src/weights/pallet_parachain_staking.rs b/runtime/common/src/weights/pallet_parachain_staking.rs index 9df5b793e..d383dfed5 100644 --- a/runtime/common/src/weights/pallet_parachain_staking.rs +++ b/runtime/common/src/weights/pallet_parachain_staking.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_parachain_staking //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,50 +39,47 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_parachain_staking (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_parachain_staking::weights::WeightInfo for WeightInfo { // Storage: ParachainStaking InflationConfig (r:1 w:1) fn set_staking_expectations() -> Weight { - Weight::from_ref_time(36_750_000) + Weight::from_ref_time(22_959_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParachainStaking InflationConfig (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) fn set_inflation() -> Weight { - Weight::from_ref_time(94_430_000) + Weight::from_ref_time(53_944_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) fn set_parachain_bond_account() -> Weight { - Weight::from_ref_time(33_460_000) + Weight::from_ref_time(12_549_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) fn set_parachain_bond_reserve_percent() -> Weight { - Weight::from_ref_time(32_350_000) + Weight::from_ref_time(12_385_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParachainStaking TotalSelected (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) fn set_total_selected() -> Weight { - Weight::from_ref_time(36_990_000) + Weight::from_ref_time(14_233_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParachainStaking CollatorCommission (r:1 w:1) fn set_collator_commission() -> Weight { - Weight::from_ref_time(31_200_000) + Weight::from_ref_time(12_029_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -90,7 +87,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking TotalSelected (r:1 w:0) // Storage: ParachainStaking InflationConfig (r:1 w:1) fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(99_720_000) + Weight::from_ref_time(35_350_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -102,20 +99,20 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking Total (r:1 w:1) // Storage: ParachainStaking TopDelegations (r:0 w:1) // Storage: ParachainStaking BottomDelegations (r:0 w:1) - fn join_candidates(x: u32) -> Weight { - Weight::from_ref_time(105_148_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(369_000).saturating_mul(x.into())) + fn join_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(32_869_323) + // Standard Error: 1_610 + .saturating_add(Weight::from_ref_time(193_154).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(7)) } // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking CandidatePool (r:1 w:1) - fn schedule_leave_candidates(x: u32) -> Weight { - Weight::from_ref_time(118_551_000) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(313_000).saturating_mul(x.into())) + fn schedule_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(25_820_357) + // Standard Error: 1_488 + .saturating_add(Weight::from_ref_time(174_057).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -129,10 +126,10 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) // Storage: ParachainStaking BottomDelegations (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) - fn execute_leave_candidates(x: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 226_000 - .saturating_add(Weight::from_ref_time(44_890_000).saturating_mul(x.into())) + fn execute_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(62_477_000) + // Standard Error: 41_796 + .saturating_add(Weight::from_ref_time(15_946_001).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into()))) .saturating_add(T::DbWeight::get().writes(5)) @@ -140,24 +137,24 @@ impl pallet_parachain_staking::weights::WeightInfo for } // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) - fn cancel_leave_candidates(x: u32) -> Weight { - Weight::from_ref_time(115_324_000) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(358_000).saturating_mul(x.into())) + fn cancel_leave_candidates(x: u32, ) -> Weight { + Weight::from_ref_time(23_095_410) + // Standard Error: 1_510 + .saturating_add(Weight::from_ref_time(190_401).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) fn go_offline() -> Weight { - Weight::from_ref_time(52_570_000) + Weight::from_ref_time(20_218_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) fn go_online() -> Weight { - Weight::from_ref_time(51_920_000) + Weight::from_ref_time(20_722_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -167,14 +164,14 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: Balances Locks (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) fn candidate_bond_more() -> Weight { - Weight::from_ref_time(97_240_000) + Weight::from_ref_time(34_948_000) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) fn schedule_candidate_bond_less() -> Weight { - Weight::from_ref_time(47_370_000) + Weight::from_ref_time(19_230_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -185,13 +182,13 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: System Account (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) fn execute_candidate_bond_less() -> Weight { - Weight::from_ref_time(94_561_000) + Weight::from_ref_time(40_550_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: ParachainStaking CandidateInfo (r:1 w:1) fn cancel_candidate_bond_less() -> Weight { - Weight::from_ref_time(50_120_000) + Weight::from_ref_time(17_798_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -202,12 +199,10 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) - fn delegate(x: u32, y: u32) -> Weight { - Weight::from_ref_time(221_620_000) - // Standard Error: 48_000 - .saturating_add(Weight::from_ref_time(372_000).saturating_mul(x.into())) - // Standard Error: 15_000 - .saturating_add(Weight::from_ref_time(527_000).saturating_mul(y.into())) + fn delegate(_x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(98_852_381) + // Standard Error: 3_632 + .saturating_add(Weight::from_ref_time(74_937).saturating_mul(y.into())) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -215,7 +210,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) fn schedule_leave_delegators() -> Weight { - Weight::from_ref_time(63_370_000) + Weight::from_ref_time(21_612_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -229,10 +224,10 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn execute_leave_delegators(x: u32) -> Weight { - Weight::from_ref_time(27_207_000) - // Standard Error: 226_000 - .saturating_add(Weight::from_ref_time(34_240_000).saturating_mul(x.into())) + fn execute_leave_delegators(x: u32, ) -> Weight { + Weight::from_ref_time(17_452_622) + // Standard Error: 21_795 + .saturating_add(Weight::from_ref_time(13_924_996).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -241,7 +236,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) fn cancel_leave_delegators() -> Weight { - Weight::from_ref_time(52_221_000) + Weight::from_ref_time(20_919_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -249,7 +244,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) fn schedule_revoke_delegation() -> Weight { - Weight::from_ref_time(51_631_000) + Weight::from_ref_time(22_510_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -262,7 +257,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) fn delegator_bond_more() -> Weight { - Weight::from_ref_time(109_970_000) + Weight::from_ref_time(47_725_000) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -270,7 +265,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) fn schedule_delegator_bond_less() -> Weight { - Weight::from_ref_time(51_671_000) + Weight::from_ref_time(22_039_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -285,7 +280,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) fn execute_revoke_delegation() -> Weight { - Weight::from_ref_time(138_000_000) + Weight::from_ref_time(62_301_000) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(8)) } @@ -299,59 +294,72 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) fn execute_delegator_bond_less() -> Weight { - Weight::from_ref_time(121_801_000) + Weight::from_ref_time(51_233_000) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(8)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) fn cancel_revoke_delegation() -> Weight { - Weight::from_ref_time(49_720_000) + Weight::from_ref_time(21_273_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: ParachainStaking DelegatorState (r:1 w:1) // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) fn cancel_delegator_bond_less() -> Weight { - Weight::from_ref_time(61_280_000) + Weight::from_ref_time(26_229_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - // Storage: ParachainStaking Round (r:1 w:1) // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking Staked (r:1 w:2) + // Storage: ParachainStaking Staked (r:1 w:1) // Storage: ParachainStaking InflationConfig (r:1 w:0) // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - // Storage: System Account (r:302 w:301) + // Storage: System Account (r:1 w:1) // Storage: ParachainStaking CollatorCommission (r:1 w:0) + // Storage: ParachainStaking DelayedPayouts (r:0 w:1) + fn prepare_staking_payouts() -> Weight { + Weight::from_ref_time(30_172_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + fn get_rewardable_delegators(y: u32, ) -> Weight { + Weight::from_ref_time(9_044_052) + // Standard Error: 934 + .saturating_add(Weight::from_ref_time(166_721).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(2)) + } // Storage: ParachainStaking CandidatePool (r:1 w:0) // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:9 w:0) - // Storage: ParachainStaking DelegationScheduledRequests (r:9 w:0) - // Storage: ParachainStaking TopDelegations (r:9 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:9 w:0) - // Storage: ParachainStaking Total (r:1 w:0) - // Storage: ParachainStaking AwardedPts (r:2 w:1) - // Storage: ParachainStaking AtStake (r:1 w:10) + // Storage: ParachainStaking CandidateInfo (r:1 w:0) + // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + // Storage: ParachainStaking TopDelegations (r:1 w:0) + // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) // Storage: ParachainStaking SelectedCandidates (r:0 w:1) - // Storage: ParachainStaking DelayedPayouts (r:0 w:1) - fn round_transition_on_initialize(x: u32, y: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 1_640_000 - .saturating_add(Weight::from_ref_time(58_147_000).saturating_mul(x.into())) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(398_000).saturating_mul(y.into())) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into()))) + // Storage: ParachainStaking AtStake (r:0 w:1) + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(19_457_000) + // Standard Error: 194_470 + .saturating_add(Weight::from_ref_time(14_446_541).saturating_mul(x.into())) + // Standard Error: 96_977 + .saturating_add(Weight::from_ref_time(2_854_011).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) } // Storage: ParachainStaking DelayedPayouts (r:1 w:0) // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking AwardedPts (r:2 w:1) - // Storage: ParachainStaking AtStake (r:1 w:1) + // Storage: ParachainStaking AtStake (r:2 w:1) + // Storage: ParachainStaking AwardedPts (r:1 w:1) // Storage: System Account (r:1 w:1) - fn pay_one_collator_reward(y: u32) -> Weight { - Weight::from_ref_time(74_512_000) - // Standard Error: 78_000 - .saturating_add(Weight::from_ref_time(18_939_000).saturating_mul(y.into())) + fn pay_one_collator_reward(y: u32, ) -> Weight { + Weight::from_ref_time(41_033_942) + // Standard Error: 5_622 + .saturating_add(Weight::from_ref_time(7_673_326).saturating_mul(y.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into()))) .saturating_add(T::DbWeight::get().writes(3)) @@ -359,16 +367,17 @@ impl pallet_parachain_staking::weights::WeightInfo for } // Storage: ParachainStaking Round (r:1 w:0) fn base_on_initialize() -> Weight { - Weight::from_ref_time(15_540_000).saturating_add(T::DbWeight::get().reads(1)) + Weight::from_ref_time(5_312_000) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: ParachainStaking DelegatorState (r:1 w:0) // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - fn set_auto_compound(x: u32, y: u32) -> Weight { - Weight::from_ref_time(172_244_000) - // Standard Error: 11_000 - .saturating_add(Weight::from_ref_time(387_000).saturating_mul(x.into())) - // Standard Error: 35_000 - .saturating_add(Weight::from_ref_time(30_000).saturating_mul(y.into())) + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + Weight::from_ref_time(42_718_871) + // Standard Error: 2_814 + .saturating_add(Weight::from_ref_time(161_876).saturating_mul(x.into())) + // Standard Error: 8_425 + .saturating_add(Weight::from_ref_time(104_510).saturating_mul(y.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -381,13 +390,19 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: Balances Locks (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) // Storage: ParachainStaking BottomDelegations (r:1 w:1) - fn delegate_with_auto_compound(x: u32, y: u32, _z: u32) -> Weight { - Weight::from_ref_time(290_047_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(115_000).saturating_mul(x.into())) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(184_000).saturating_mul(y.into())) + fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { + Weight::from_ref_time(100_631_109) + // Standard Error: 2_763 + .saturating_add(Weight::from_ref_time(81_505).saturating_mul(x.into())) + // Standard Error: 2_763 + .saturating_add(Weight::from_ref_time(48_166).saturating_mul(y.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(8)) } + // Storage: System Account (r:1 w:1) + fn mint_collator_reward() -> Weight { + Weight::from_ref_time(18_241_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/runtime/common/src/weights/pallet_preimage.rs b/runtime/common/src/weights/pallet_preimage.rs index 0536b916e..dcaf4023d 100644 --- a/runtime/common/src/weights/pallet_preimage.rs +++ b/runtime/common/src/weights/pallet_preimage.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_preimage //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -48,88 +48,87 @@ use frame_support::{ /// Weight functions for pallet_preimage (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_preimage::weights::WeightInfo for WeightInfo { - // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) fn note_preimage(s: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) + Weight::from_ref_time(21_280_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(1_231).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - // Storage: Preimage PreimageFor (r:1 w:1) - // Storage: Preimage StatusFor (r:1 w:0) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) fn note_requested_preimage(s: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(14_404_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(1_233).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } - // Storage: Preimage PreimageFor (r:1 w:1) - // Storage: Preimage StatusFor (r:1 w:0) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Preimage PreimageFor (r:0 w:1) fn note_no_deposit_preimage(s: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(3_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(13_424_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(1_231).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - Weight::from_ref_time(97_561_000) + Weight::from_ref_time(28_640_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - Weight::from_ref_time(68_920_000) + Weight::from_ref_time(16_748_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - Weight::from_ref_time(93_040_000) + Weight::from_ref_time(15_219_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - Weight::from_ref_time(72_890_000) + Weight::from_ref_time(6_886_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - Weight::from_ref_time(47_821_000) + Weight::from_ref_time(13_170_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - Weight::from_ref_time(18_310_000) + Weight::from_ref_time(6_794_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - Weight::from_ref_time(74_260_000) + Weight::from_ref_time(16_478_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) - // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_unnoted_preimage() -> Weight { - Weight::from_ref_time(38_170_000) + Weight::from_ref_time(6_985_000) .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - Weight::from_ref_time(20_180_000) + Weight::from_ref_time(6_886_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/runtime/common/src/weights/pallet_proxy.rs b/runtime/common/src/weights/pallet_proxy.rs index 216678e76..9c02efb67 100644 --- a/runtime/common/src/weights/pallet_proxy.rs +++ b/runtime/common/src/weights/pallet_proxy.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_proxy //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,104 +39,99 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_proxy (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_proxy::weights::WeightInfo for WeightInfo { // Storage: Proxy Proxies (r:1 w:0) - fn proxy(p: u32) -> Weight { - Weight::from_ref_time(39_097_000) - // Standard Error: 16_000 - .saturating_add(Weight::from_ref_time(94_000).saturating_mul(p.into())) + fn proxy(p: u32, ) -> Weight { + Weight::from_ref_time(14_846_152) + // Standard Error: 3_656 + .saturating_add(Weight::from_ref_time(20_035).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn proxy_announced(a: u32, p: u32) -> Weight { - Weight::from_ref_time(71_706_000) - // Standard Error: 26_000 - .saturating_add(Weight::from_ref_time(185_000).saturating_mul(a.into())) - // Standard Error: 27_000 - .saturating_add(Weight::from_ref_time(78_000).saturating_mul(p.into())) + fn proxy_announced(a: u32, p: u32, ) -> Weight { + Weight::from_ref_time(29_808_110) + // Standard Error: 3_086 + .saturating_add(Weight::from_ref_time(68_700).saturating_mul(a.into())) + // Standard Error: 3_189 + .saturating_add(Weight::from_ref_time(27_747).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn remove_announcement(a: u32, p: u32) -> Weight { - Weight::from_ref_time(48_284_000) - // Standard Error: 18_000 - .saturating_add(Weight::from_ref_time(166_000).saturating_mul(a.into())) - // Standard Error: 18_000 - .saturating_add(Weight::from_ref_time(69_000).saturating_mul(p.into())) + fn remove_announcement(a: u32, _p: u32, ) -> Weight { + Weight::from_ref_time(21_154_842) + // Standard Error: 2_354 + .saturating_add(Weight::from_ref_time(67_662).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn reject_announcement(a: u32, _p: u32) -> Weight { - Weight::from_ref_time(52_265_000) - // Standard Error: 16_000 - .saturating_add(Weight::from_ref_time(84_000).saturating_mul(a.into())) + fn reject_announcement(a: u32, _p: u32, ) -> Weight { + Weight::from_ref_time(20_587_474) + // Standard Error: 2_191 + .saturating_add(Weight::from_ref_time(91_044).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) // Storage: System Account (r:1 w:1) - fn announce(a: u32, p: u32) -> Weight { - Weight::from_ref_time(64_000_000) - // Standard Error: 26_000 - .saturating_add(Weight::from_ref_time(117_000).saturating_mul(a.into())) - // Standard Error: 26_000 - .saturating_add(Weight::from_ref_time(91_000).saturating_mul(p.into())) + fn announce(a: u32, p: u32, ) -> Weight { + Weight::from_ref_time(25_960_647) + // Standard Error: 3_453 + .saturating_add(Weight::from_ref_time(90_065).saturating_mul(a.into())) + // Standard Error: 3_567 + .saturating_add(Weight::from_ref_time(54_574).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Proxy Proxies (r:1 w:1) - fn add_proxy(p: u32) -> Weight { - Weight::from_ref_time(48_885_000) - // Standard Error: 76_000 - .saturating_add(Weight::from_ref_time(439_000).saturating_mul(p.into())) + fn add_proxy(p: u32, ) -> Weight { + Weight::from_ref_time(21_515_673) + // Standard Error: 9_730 + .saturating_add(Weight::from_ref_time(27_609).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) - fn remove_proxy(p: u32) -> Weight { - Weight::from_ref_time(52_080_000) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(146_000).saturating_mul(p.into())) + fn remove_proxy(p: u32, ) -> Weight { + Weight::from_ref_time(20_632_234) + // Standard Error: 2_374 + .saturating_add(Weight::from_ref_time(68_381).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) - fn remove_proxies(p: u32) -> Weight { - Weight::from_ref_time(46_847_000) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(19_000).saturating_mul(p.into())) + fn remove_proxies(p: u32, ) -> Weight { + Weight::from_ref_time(17_793_375) + // Standard Error: 1_672 + .saturating_add(Weight::from_ref_time(42_726).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) - fn anonymous(p: u32) -> Weight { - Weight::from_ref_time(55_708_000) - // Standard Error: 16_000 - .saturating_add(Weight::from_ref_time(50_000).saturating_mul(p.into())) + fn create_pure(p: u32, ) -> Weight { + Weight::from_ref_time(22_473_896) + // Standard Error: 1_953 + .saturating_add(Weight::from_ref_time(15_155).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) - fn kill_anonymous(p: u32) -> Weight { - Weight::from_ref_time(46_563_000) - // Standard Error: 30_000 - .saturating_add(Weight::from_ref_time(250_000).saturating_mul(p.into())) + fn kill_pure(p: u32, ) -> Weight { + Weight::from_ref_time(18_850_050) + // Standard Error: 1_796 + .saturating_add(Weight::from_ref_time(42_672).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/runtime/common/src/weights/pallet_scheduler.rs b/runtime/common/src/weights/pallet_scheduler.rs index d94e83b60..ddf141ff7 100644 --- a/runtime/common/src/weights/pallet_scheduler.rs +++ b/runtime/common/src/weights/pallet_scheduler.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_scheduler //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -39,158 +39,84 @@ #![allow(unused_parens)] #![allow(unused_imports)] +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; /// Weight functions for pallet_scheduler (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_scheduler::weights::WeightInfo for WeightInfo { - // Storage: Scheduler Agenda (r:2 w:2) - // Storage: Preimage PreimageFor (r:1 w:1) - // Storage: Preimage StatusFor (r:1 w:1) - // Storage: Scheduler Lookup (r:0 w:1) - fn on_initialize_periodic_named_resolved(s: u32) -> Weight { - Weight::from_ref_time(77_951_000) - // Standard Error: 354_000 - .saturating_add(Weight::from_ref_time(33_430_000).saturating_mul(s.into())) + // Storage: Scheduler IncompleteSince (r:1 w:1) + fn service_agendas_base() -> Weight { + Weight::from_ref_time(3_351_000) .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(s.into()))) } // Storage: Scheduler Agenda (r:1 w:1) - // Storage: Preimage PreimageFor (r:1 w:1) - // Storage: Preimage StatusFor (r:1 w:1) - // Storage: Scheduler Lookup (r:0 w:1) - fn on_initialize_named_resolved(s: u32) -> Weight { - Weight::from_ref_time(30_364_000) - // Standard Error: 290_000 - .saturating_add(Weight::from_ref_time(28_276_000).saturating_mul(s.into())) + fn service_agenda_base(s: u32, ) -> Weight { + Weight::from_ref_time(5_402_281) + // Standard Error: 2_213 + .saturating_add(Weight::from_ref_time(239_796).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(s.into()))) } - // Storage: Scheduler Agenda (r:2 w:2) - // Storage: Preimage PreimageFor (r:1 w:1) - // Storage: Preimage StatusFor (r:1 w:1) - fn on_initialize_periodic_resolved(s: u32) -> Weight { - Weight::from_ref_time(15_153_000) - // Standard Error: 630_000 - .saturating_add(Weight::from_ref_time(30_716_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(s.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(s.into()))) + fn service_task_base() -> Weight { + Weight::from_ref_time(6_133_000) } - // Storage: Scheduler Agenda (r:1 w:1) // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) - fn on_initialize_resolved(s: u32) -> Weight { - Weight::from_ref_time(29_624_000) - // Standard Error: 210_000 - .saturating_add(Weight::from_ref_time(26_634_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(s.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(s.into()))) - } - // Storage: Scheduler Agenda (r:2 w:2) - // Storage: Preimage PreimageFor (r:1 w:0) - // Storage: Scheduler Lookup (r:0 w:1) - fn on_initialize_named_aborted(s: u32) -> Weight { - Weight::from_ref_time(18_753_000) - // Standard Error: 74_000 - .saturating_add(Weight::from_ref_time(10_211_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) - .saturating_add(T::DbWeight::get().writes(2)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) - } - // Storage: Scheduler Agenda (r:2 w:2) - // Storage: Preimage PreimageFor (r:1 w:0) - fn on_initialize_aborted(s: u32) -> Weight { - Weight::from_ref_time(12_642_000) - // Standard Error: 91_000 - .saturating_add(Weight::from_ref_time(5_181_000).saturating_mul(s.into())) + fn service_task_fetched(s: u32, ) -> Weight { + Weight::from_ref_time(15_508_000) + // Standard Error: 6 + .saturating_add(Weight::from_ref_time(902).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(2)) } - // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:0 w:1) - fn on_initialize_periodic_named(s: u32) -> Weight { - Weight::from_ref_time(57_881_000) - // Standard Error: 117_000 - .saturating_add(Weight::from_ref_time(16_508_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) + fn service_task_named() -> Weight { + Weight::from_ref_time(7_623_000) .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(s.into()))) } - // Storage: Scheduler Agenda (r:2 w:2) - fn on_initialize_periodic(s: u32) -> Weight { - Weight::from_ref_time(32_402_000) - // Standard Error: 103_000 - .saturating_add(Weight::from_ref_time(13_081_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + fn service_task_periodic() -> Weight { + Weight::from_ref_time(6_381_000) } - // Storage: Scheduler Agenda (r:1 w:1) - // Storage: Scheduler Lookup (r:0 w:1) - fn on_initialize_named(s: u32) -> Weight { - Weight::from_ref_time(39_741_000) - // Standard Error: 73_000 - .saturating_add(Weight::from_ref_time(11_308_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + fn execute_dispatch_signed() -> Weight { + Weight::from_ref_time(2_668_000) } - // Storage: Scheduler Agenda (r:1 w:1) - fn on_initialize(s: u32) -> Weight { - Weight::from_ref_time(34_782_000) - // Standard Error: 61_000 - .saturating_add(Weight::from_ref_time(9_525_000).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + fn execute_dispatch_unsigned() -> Weight { + Weight::from_ref_time(2_690_000) } // Storage: Scheduler Agenda (r:1 w:1) - fn schedule(s: u32) -> Weight { - Weight::from_ref_time(42_112_000) - // Standard Error: 20_000 - .saturating_add(Weight::from_ref_time(179_000).saturating_mul(s.into())) + fn schedule(s: u32, ) -> Weight { + Weight::from_ref_time(14_386_290) + // Standard Error: 8_210 + .saturating_add(Weight::from_ref_time(290_508).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) - fn cancel(s: u32) -> Weight { - Weight::from_ref_time(40_100_000) - // Standard Error: 21_000 - .saturating_add(Weight::from_ref_time(996_000).saturating_mul(s.into())) + fn cancel(s: u32, ) -> Weight { + Weight::from_ref_time(14_618_067) + // Standard Error: 2_673 + .saturating_add(Weight::from_ref_time(244_365).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) - fn schedule_named(s: u32) -> Weight { - Weight::from_ref_time(44_125_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(242_000).saturating_mul(s.into())) + fn schedule_named(s: u32, ) -> Weight { + Weight::from_ref_time(17_125_968) + // Standard Error: 3_579 + .saturating_add(Weight::from_ref_time(283_692).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) - fn cancel_named(s: u32) -> Weight { - Weight::from_ref_time(42_315_000) - // Standard Error: 44_000 - .saturating_add(Weight::from_ref_time(1_239_000).saturating_mul(s.into())) + fn cancel_named(s: u32, ) -> Weight { + Weight::from_ref_time(16_091_884) + // Standard Error: 2_674 + .saturating_add(Weight::from_ref_time(274_337).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } diff --git a/runtime/common/src/weights/pallet_timestamp.rs b/runtime/common/src/weights/pallet_timestamp.rs index 083969d6d..278c43455 100644 --- a/runtime/common/src/weights/pallet_timestamp.rs +++ b/runtime/common/src/weights/pallet_timestamp.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_timestamp //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -51,11 +51,11 @@ impl pallet_timestamp::weights::WeightInfo for WeightIn // Storage: Timestamp Now (r:1 w:1) // Storage: Aura CurrentSlot (r:1 w:0) fn set() -> Weight { - Weight::from_ref_time(27_600_000) + Weight::from_ref_time(8_108_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { - Weight::from_ref_time(10_360_000) + Weight::from_ref_time(3_570_000) } } diff --git a/runtime/common/src/weights/pallet_treasury.rs b/runtime/common/src/weights/pallet_treasury.rs index 66d407d9e..7f5286a7e 100644 --- a/runtime/common/src/weights/pallet_treasury.rs +++ b/runtime/common/src/weights/pallet_treasury.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_treasury //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -49,33 +49,33 @@ use frame_support::{ pub struct WeightInfo(PhantomData); impl pallet_treasury::weights::WeightInfo for WeightInfo { fn spend() -> Weight { - Weight::from_ref_time(280_000) + Weight::from_ref_time(95_000) } // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - Weight::from_ref_time(60_380_000) + Weight::from_ref_time(20_565_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:1) fn reject_proposal() -> Weight { - Weight::from_ref_time(72_761_000) + Weight::from_ref_time(24_762_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32) -> Weight { - Weight::from_ref_time(27_423_000) - // Standard Error: 5_000 - .saturating_add(Weight::from_ref_time(174_000).saturating_mul(p.into())) + Weight::from_ref_time(10_471_736) + // Standard Error: 1_016 + .saturating_add(Weight::from_ref_time(105_175).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Treasury Approvals (r:1 w:1) fn remove_approval() -> Weight { - Weight::from_ref_time(19_090_000) + Weight::from_ref_time(6_422_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -84,9 +84,9 @@ impl pallet_treasury::weights::WeightInfo for WeightInf // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: Treasury Proposals (r:2 w:2) fn on_initialize_proposals(p: u32) -> Weight { - Weight::from_ref_time(43_929_000) - // Standard Error: 358_000 - .saturating_add(Weight::from_ref_time(45_522_000).saturating_mul(p.into())) + Weight::from_ref_time(38_410_434) + // Standard Error: 20_814 + .saturating_add(Weight::from_ref_time(18_295_935).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(2)) diff --git a/runtime/common/src/weights/pallet_utility.rs b/runtime/common/src/weights/pallet_utility.rs index 059ae9918..19feca598 100644 --- a/runtime/common/src/weights/pallet_utility.rs +++ b/runtime/common/src/weights/pallet_utility.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_utility //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -49,24 +49,24 @@ use frame_support::{ pub struct WeightInfo(PhantomData); impl pallet_utility::weights::WeightInfo for WeightInfo { fn batch(c: u32) -> Weight { - Weight::from_ref_time(73_233_000) - // Standard Error: 20_000 - .saturating_add(Weight::from_ref_time(6_159_000).saturating_mul(c.into())) + Weight::from_ref_time(31_466_915) + // Standard Error: 2_630 + .saturating_add(Weight::from_ref_time(2_383_207).saturating_mul(c.into())) } fn as_derivative() -> Weight { - Weight::from_ref_time(10_870_000) + Weight::from_ref_time(4_073_000) } fn batch_all(c: u32) -> Weight { - Weight::from_ref_time(44_965_000) - // Standard Error: 48_000 - .saturating_add(Weight::from_ref_time(6_460_000).saturating_mul(c.into())) + Weight::from_ref_time(33_997_301) + // Standard Error: 3_559 + .saturating_add(Weight::from_ref_time(2_433_000).saturating_mul(c.into())) } fn dispatch_as() -> Weight { - Weight::from_ref_time(23_170_000) + Weight::from_ref_time(9_493_000) } fn force_batch(c: u32) -> Weight { - Weight::from_ref_time(35_547_000) - // Standard Error: 28_000 - .saturating_add(Weight::from_ref_time(6_274_000).saturating_mul(c.into())) + Weight::from_ref_time(25_346_023) + // Standard Error: 3_911 + .saturating_add(Weight::from_ref_time(2_393_869).saturating_mul(c.into())) } } diff --git a/runtime/common/src/weights/pallet_vesting.rs b/runtime/common/src/weights/pallet_vesting.rs index af99820ef..07e67e789 100644 --- a/runtime/common/src/weights/pallet_vesting.rs +++ b/runtime/common/src/weights/pallet_vesting.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_vesting //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -50,19 +50,21 @@ pub struct WeightInfo(PhantomData); impl pallet_vesting::weights::WeightInfo for WeightInfo { // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn vest_locked(_l: u32, _s: u32) -> Weight { - Weight::from_ref_time(74_193_000) + fn vest_locked(l: u32, s: u32) -> Weight { + Weight::from_ref_time(28_454_811) + // Standard Error: 2_342 + .saturating_add(Weight::from_ref_time(30_427).saturating_mul(l.into())) + // Standard Error: 4_167 + .saturating_add(Weight::from_ref_time(10_709).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn vest_unlocked(l: u32, s: u32) -> Weight { - Weight::from_ref_time(59_403_000) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(142_000).saturating_mul(l.into())) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(76_000).saturating_mul(s.into())) + fn vest_unlocked(l: u32, _s: u32) -> Weight { + Weight::from_ref_time(28_053_460) + // Standard Error: 2_049 + .saturating_add(Weight::from_ref_time(24_548).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -70,9 +72,9 @@ impl pallet_vesting::weights::WeightInfo for WeightInfo // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_locked(l: u32, _s: u32) -> Weight { - Weight::from_ref_time(69_282_000) - // Standard Error: 17_000 - .saturating_add(Weight::from_ref_time(33_000).saturating_mul(l.into())) + Weight::from_ref_time(28_646_528) + // Standard Error: 2_267 + .saturating_add(Weight::from_ref_time(14_776).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -80,51 +82,51 @@ impl pallet_vesting::weights::WeightInfo for WeightInfo // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn vest_other_unlocked(l: u32, _s: u32) -> Weight { - Weight::from_ref_time(64_138_000) - // Standard Error: 10_000 - .saturating_add(Weight::from_ref_time(101_000).saturating_mul(l.into())) + Weight::from_ref_time(29_263_562) + // Standard Error: 2_411 + .saturating_add(Weight::from_ref_time(2_655).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn vested_transfer(l: u32, s: u32) -> Weight { - Weight::from_ref_time(89_063_000) - // Standard Error: 24_000 - .saturating_add(Weight::from_ref_time(74_000).saturating_mul(l.into())) - // Standard Error: 43_000 - .saturating_add(Weight::from_ref_time(240_000).saturating_mul(s.into())) + fn vested_transfer(l: u32, _s: u32) -> Weight { + Weight::from_ref_time(40_625_249) + // Standard Error: 2_877 + .saturating_add(Weight::from_ref_time(30_587).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:2 w:2) // Storage: Balances Locks (r:1 w:1) - fn force_vested_transfer(_l: u32, s: u32) -> Weight { - Weight::from_ref_time(95_489_000) - // Standard Error: 61_000 - .saturating_add(Weight::from_ref_time(44_000).saturating_mul(s.into())) + fn force_vested_transfer(l: u32, s: u32) -> Weight { + Weight::from_ref_time(38_574_791) + // Standard Error: 6_754 + .saturating_add(Weight::from_ref_time(40_472).saturating_mul(l.into())) + // Standard Error: 12_017 + .saturating_add(Weight::from_ref_time(33_756).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn not_unlocking_merge_schedules(l: u32, _s: u32) -> Weight { - Weight::from_ref_time(67_438_000) - // Standard Error: 14_000 - .saturating_add(Weight::from_ref_time(158_000).saturating_mul(l.into())) + Weight::from_ref_time(28_978_945) + // Standard Error: 1_850 + .saturating_add(Weight::from_ref_time(38_600).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn unlocking_merge_schedules(l: u32, s: u32) -> Weight { - Weight::from_ref_time(67_798_000) - // Standard Error: 22_000 - .saturating_add(Weight::from_ref_time(48_000).saturating_mul(l.into())) - // Standard Error: 41_000 - .saturating_add(Weight::from_ref_time(115_000).saturating_mul(s.into())) + Weight::from_ref_time(29_199_036) + // Standard Error: 2_331 + .saturating_add(Weight::from_ref_time(15_809).saturating_mul(l.into())) + // Standard Error: 4_306 + .saturating_add(Weight::from_ref_time(16_241).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } diff --git a/zrml/authorized/src/weights.rs b/zrml/authorized/src/weights.rs index 2aaa24742..4327b1e82 100644 --- a/zrml/authorized/src/weights.rs +++ b/zrml/authorized/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_authorized //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -56,16 +56,16 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Authorized AuthorizedOutcomeReports (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:1 w:1) fn authorize_market_outcome_first_report(m: u32) -> Weight { - Weight::from_ref_time(38_444_000) - // Standard Error: 1_000 - .saturating_add(Weight::from_ref_time(173_000).saturating_mul(m.into())) + Weight::from_ref_time(15_718_181) + // Standard Error: 220 + .saturating_add(Weight::from_ref_time(93_904).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: MarketCommons Markets (r:1 w:0) // Storage: Authorized AuthorizedOutcomeReports (r:1 w:1) fn authorize_market_outcome_existing_report() -> Weight { - Weight::from_ref_time(30_850_000) + Weight::from_ref_time(11_771_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/zrml/court/src/weights.rs b/zrml/court/src/weights.rs index 48d68f719..d00152fe0 100644 --- a/zrml/court/src/weights.rs +++ b/zrml/court/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_court //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -59,7 +59,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Court RequestedJurors (r:1 w:0) // Storage: Court Votes (r:1 w:0) fn exit_court() -> Weight { - Weight::from_ref_time(76_500_000) + Weight::from_ref_time(32_565_000) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -67,14 +67,14 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Court CounterForJurors (r:1 w:1) // Storage: Balances Reserves (r:1 w:1) fn join_court() -> Weight { - Weight::from_ref_time(54_370_000) + Weight::from_ref_time(23_581_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Court Jurors (r:1 w:0) // Storage: Court Votes (r:0 w:1) fn vote() -> Weight { - Weight::from_ref_time(25_540_000) + Weight::from_ref_time(10_028_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/zrml/global-disputes/src/weights.rs b/zrml/global-disputes/src/weights.rs index 5e8a03f6d..ffe1b204a 100644 --- a/zrml/global-disputes/src/weights.rs +++ b/zrml/global-disputes/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_global_disputes //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -61,12 +61,10 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: GlobalDisputes Outcomes (r:1 w:1) // Storage: GlobalDisputes Locks (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - fn vote_on_outcome(o: u32, v: u32) -> Weight { - Weight::from_ref_time(78_818_000) - // Standard Error: 21_000 - .saturating_add(Weight::from_ref_time(23_000).saturating_mul(o.into())) - // Standard Error: 3_000 - .saturating_add(Weight::from_ref_time(90_000).saturating_mul(v.into())) + fn vote_on_outcome(_o: u32, v: u32) -> Weight { + Weight::from_ref_time(33_191_681) + // Standard Error: 369 + .saturating_add(Weight::from_ref_time(37_828).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -75,11 +73,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: GlobalDisputes Winners (r:5 w:0) fn unlock_vote_balance_set(l: u32, o: u32) -> Weight { - Weight::from_ref_time(43_696_000) - // Standard Error: 10_000 - .saturating_add(Weight::from_ref_time(3_636_000).saturating_mul(l.into())) - // Standard Error: 61_000 - .saturating_add(Weight::from_ref_time(1_467_000).saturating_mul(o.into())) + Weight::from_ref_time(18_127_027) + // Standard Error: 839 + .saturating_add(Weight::from_ref_time(1_534_897).saturating_mul(l.into())) + // Standard Error: 4_699 + .saturating_add(Weight::from_ref_time(401_151).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(l.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -89,11 +87,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: GlobalDisputes Winners (r:5 w:0) fn unlock_vote_balance_remove(l: u32, o: u32) -> Weight { - Weight::from_ref_time(40_327_000) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(3_508_000).saturating_mul(l.into())) - // Standard Error: 55_000 - .saturating_add(Weight::from_ref_time(1_279_000).saturating_mul(o.into())) + Weight::from_ref_time(17_109_385) + // Standard Error: 607 + .saturating_add(Weight::from_ref_time(1_486_668).saturating_mul(l.into())) + // Standard Error: 3_398 + .saturating_add(Weight::from_ref_time(314_814).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(l.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -101,8 +99,10 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: GlobalDisputes Winners (r:1 w:1) // Storage: GlobalDisputes Outcomes (r:1 w:1) // Storage: System Account (r:1 w:1) - fn add_vote_outcome(_w: u32) -> Weight { - Weight::from_ref_time(87_507_000) + fn add_vote_outcome(w: u32) -> Weight { + Weight::from_ref_time(35_150_950) + // Standard Error: 1_710 + .saturating_add(Weight::from_ref_time(19_709).saturating_mul(w.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -110,9 +110,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: GlobalDisputes Winners (r:1 w:0) // Storage: System Account (r:2 w:2) fn reward_outcome_owner_with_funds(o: u32) -> Weight { - Weight::from_ref_time(54_189_000) - // Standard Error: 75_000 - .saturating_add(Weight::from_ref_time(29_563_000).saturating_mul(o.into())) + Weight::from_ref_time(24_395_149) + // Standard Error: 13_698 + .saturating_add(Weight::from_ref_time(11_889_863).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(o.into()))) .saturating_add(T::DbWeight::get().writes(1)) @@ -122,16 +122,14 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: GlobalDisputes Winners (r:1 w:0) // Storage: System Account (r:1 w:0) fn reward_outcome_owner_no_funds(_o: u32) -> Weight { - Weight::from_ref_time(46_706_000).saturating_add(T::DbWeight::get().reads(3)) + Weight::from_ref_time(17_745_809).saturating_add(T::DbWeight::get().reads(3)) } // Storage: GlobalDisputes Winners (r:1 w:1) // Storage: GlobalDisputes Outcomes (r:3 w:2) - fn purge_outcomes(k: u32, o: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 22_000 - .saturating_add(Weight::from_ref_time(18_932_000).saturating_mul(k.into())) - // Standard Error: 606_000 - .saturating_add(Weight::from_ref_time(10_914_000).saturating_mul(o.into())) + fn purge_outcomes(k: u32, _o: u32) -> Weight { + Weight::from_ref_time(34_095_000) + // Standard Error: 1_848 + .saturating_add(Weight::from_ref_time(7_103_707).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2)) diff --git a/zrml/liquidity-mining/src/weights.rs b/zrml/liquidity-mining/src/weights.rs index 42b49e781..8e0289e42 100644 --- a/zrml/liquidity-mining/src/weights.rs +++ b/zrml/liquidity-mining/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_liquidity_mining //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -53,6 +53,6 @@ pub struct WeightInfo(PhantomData); impl WeightInfoZeitgeist for WeightInfo { // Storage: LiquidityMining PerBlockIncentive (r:0 w:1) fn set_per_block_distribution() -> Weight { - Weight::from_ref_time(8_150_000).saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(2_691_000).saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/zrml/prediction-markets/src/weights.rs b/zrml/prediction-markets/src/weights.rs index bc8659033..8d4950747 100644 --- a/zrml/prediction-markets/src/weights.rs +++ b/zrml/prediction-markets/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_prediction_markets //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -91,16 +91,12 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens TotalIssuance (r:2 w:2) // Storage: PredictionMarkets Disputes (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:1 w:1) - fn admin_destroy_disputed_market(a: u32, d: u32, _o: u32, c: u32, r: u32) -> Weight { - Weight::from_ref_time(36_524_000) - // Standard Error: 41_000 - .saturating_add(Weight::from_ref_time(28_980_000).saturating_mul(a.into())) - // Standard Error: 473_000 - .saturating_add(Weight::from_ref_time(40_066_000).saturating_mul(d.into())) - // Standard Error: 41_000 - .saturating_add(Weight::from_ref_time(425_000).saturating_mul(c.into())) - // Standard Error: 41_000 - .saturating_add(Weight::from_ref_time(438_000).saturating_mul(r.into())) + fn admin_destroy_disputed_market(a: u32, d: u32, _o: u32, _c: u32, _r: u32) -> Weight { + Weight::from_ref_time(98_844_452) + // Standard Error: 1_524 + .saturating_add(Weight::from_ref_time(12_109_486).saturating_mul(a.into())) + // Standard Error: 17_423 + .saturating_add(Weight::from_ref_time(10_703_404).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into()))) @@ -117,12 +113,12 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens TotalIssuance (r:2 w:2) // Storage: PredictionMarkets MarketIdsPerReportBlock (r:1 w:1) // Storage: PredictionMarkets Disputes (r:0 w:1) - fn admin_destroy_reported_market(a: u32, _o: u32, c: u32, _r: u32) -> Weight { - Weight::from_ref_time(302_448_000) - // Standard Error: 39_000 - .saturating_add(Weight::from_ref_time(27_690_000).saturating_mul(a.into())) - // Standard Error: 39_000 - .saturating_add(Weight::from_ref_time(809_000).saturating_mul(c.into())) + fn admin_destroy_reported_market(a: u32, _o: u32, _c: u32, r: u32) -> Weight { + Weight::from_ref_time(101_907_522) + // Standard Error: 2_150 + .saturating_add(Weight::from_ref_time(11_991_328).saturating_mul(a.into())) + // Standard Error: 2_139 + .saturating_add(Weight::from_ref_time(19_182).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(8)) @@ -132,11 +128,14 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketIdsPerOpenTimeFrame (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerCloseTimeFrame (r:1 w:1) // Storage: MarketCommons MarketPool (r:1 w:0) - fn admin_move_market_to_closed(_o: u32, c: u32) -> Weight { - Weight::from_ref_time(62_951_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(69_000).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(4)) + // Storage: Timestamp Now (r:1 w:0) + fn admin_move_market_to_closed(o: u32, c: u32) -> Weight { + Weight::from_ref_time(29_677_109) + // Standard Error: 266 + .saturating_add(Weight::from_ref_time(8_751).saturating_mul(o.into())) + // Standard Error: 266 + .saturating_add(Weight::from_ref_time(20_949).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } // Storage: MarketCommons Markets (r:1 w:1) @@ -144,8 +143,10 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Balances Reserves (r:1 w:1) // Storage: MarketCommons MarketPool (r:1 w:0) // Storage: PredictionMarkets Disputes (r:0 w:1) - fn admin_move_market_to_resolved_scalar_reported(_r: u32) -> Weight { - Weight::from_ref_time(107_834_000) + fn admin_move_market_to_resolved_scalar_reported(r: u32) -> Weight { + Weight::from_ref_time(47_236_897) + // Standard Error: 334 + .saturating_add(Weight::from_ref_time(14_850).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -156,9 +157,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Swaps Pools (r:1 w:1) // Storage: PredictionMarkets Disputes (r:0 w:1) fn admin_move_market_to_resolved_categorical_reported(r: u32) -> Weight { - Weight::from_ref_time(171_263_000) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(12_000).saturating_mul(r.into())) + Weight::from_ref_time(82_465_110) + // Standard Error: 390 + .saturating_add(Weight::from_ref_time(24_567).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -171,7 +172,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: MarketCommons MarketPool (r:1 w:0) fn admin_move_market_to_resolved_scalar_disputed(_r: u32) -> Weight { - Weight::from_ref_time(174_434_000) + Weight::from_ref_time(77_566_793) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -185,9 +186,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:0) // Storage: Swaps Pools (r:1 w:1) fn admin_move_market_to_resolved_categorical_disputed(r: u32) -> Weight { - Weight::from_ref_time(226_823_000) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(85_000).saturating_mul(r.into())) + Weight::from_ref_time(111_553_988) + // Standard Error: 510 + .saturating_add(Weight::from_ref_time(24_763).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(8)) } @@ -195,16 +196,16 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketIdsForEdit (r:1 w:0) // Storage: Balances Reserves (r:1 w:1) fn approve_market() -> Weight { - Weight::from_ref_time(71_421_000) + Weight::from_ref_time(30_750_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } // Storage: MarketCommons Markets (r:1 w:0) // Storage: PredictionMarkets MarketIdsForEdit (r:1 w:1) fn request_edit(r: u32) -> Weight { - Weight::from_ref_time(40_894_000) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000).saturating_mul(r.into())) + Weight::from_ref_time(16_505_286) + // Standard Error: 17 + .saturating_add(Weight::from_ref_time(957).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -213,9 +214,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:2 w:2) // Storage: Tokens TotalIssuance (r:2 w:2) fn buy_complete_set(a: u32) -> Weight { - Weight::from_ref_time(79_725_000) - // Standard Error: 25_000 - .saturating_add(Weight::from_ref_time(19_896_000).saturating_mul(a.into())) + Weight::from_ref_time(34_786_131) + // Standard Error: 1_751 + .saturating_add(Weight::from_ref_time(8_388_765).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1)) @@ -227,9 +228,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketIdsPerCloseTimeFrame (r:1 w:1) // Storage: MarketCommons Markets (r:0 w:1) fn create_market(m: u32) -> Weight { - Weight::from_ref_time(80_436_000) - // Standard Error: 3_000 - .saturating_add(Weight::from_ref_time(9_000).saturating_mul(m.into())) + Weight::from_ref_time(31_590_932) + // Standard Error: 536 + .saturating_add(Weight::from_ref_time(19_431).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -238,9 +239,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketIdsPerCloseTimeFrame (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) fn edit_market(m: u32) -> Weight { - Weight::from_ref_time(68_686_000) - // Standard Error: 3_000 - .saturating_add(Weight::from_ref_time(150_000).saturating_mul(m.into())) + Weight::from_ref_time(27_792_538) + // Standard Error: 342 + .saturating_add(Weight::from_ref_time(27_261).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -254,11 +255,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:1) // Storage: Swaps Pools (r:0 w:1) fn deploy_swap_pool_for_market_future_pool(a: u32, o: u32) -> Weight { - Weight::from_ref_time(170_533_000) - // Standard Error: 45_000 - .saturating_add(Weight::from_ref_time(32_842_000).saturating_mul(a.into())) - // Standard Error: 45_000 - .saturating_add(Weight::from_ref_time(145_000).saturating_mul(o.into())) + Weight::from_ref_time(62_202_136) + // Standard Error: 1_823 + .saturating_add(Weight::from_ref_time(13_956_712).saturating_mul(a.into())) + // Standard Error: 1_814 + .saturating_add(Weight::from_ref_time(50_205).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(7)) @@ -273,9 +274,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:1) // Storage: Swaps Pools (r:0 w:1) fn deploy_swap_pool_for_market_open_pool(a: u32) -> Weight { - Weight::from_ref_time(100_840_000) - // Standard Error: 52_000 - .saturating_add(Weight::from_ref_time(35_669_000).saturating_mul(a.into())) + Weight::from_ref_time(67_257_811) + // Standard Error: 2_495 + .saturating_add(Weight::from_ref_time(13_993_256).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(6)) @@ -287,11 +288,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: GlobalDisputes Outcomes (r:7 w:7) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:2 w:2) fn start_global_dispute(m: u32, n: u32) -> Weight { - Weight::from_ref_time(128_368_000) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(8_000).saturating_mul(m.into())) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(96_000).saturating_mul(n.into())) + Weight::from_ref_time(59_605_523) + // Standard Error: 335 + .saturating_add(Weight::from_ref_time(8_254).saturating_mul(m.into())) + // Standard Error: 335 + .saturating_add(Weight::from_ref_time(13_974).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(10)) } @@ -299,7 +300,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons Markets (r:1 w:1) // Storage: Balances Reserves (r:1 w:1) fn dispute_authorized() -> Weight { - Weight::from_ref_time(73_020_000) + Weight::from_ref_time(32_360_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -307,7 +308,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Balances Reserves (r:1 w:1) // Storage: PredictionMarkets MarketIdsForEdit (r:0 w:1) fn handle_expired_advised_market() -> Weight { - Weight::from_ref_time(82_180_000) + Weight::from_ref_time(33_141_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -317,7 +318,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Swaps Pools (r:1 w:1) // Storage: PredictionMarkets Disputes (r:0 w:1) fn internal_resolve_categorical_reported() -> Weight { - Weight::from_ref_time(145_420_000) + Weight::from_ref_time(70_937_000) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -329,7 +330,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:0) // Storage: Swaps Pools (r:1 w:1) fn internal_resolve_categorical_disputed() -> Weight { - Weight::from_ref_time(191_701_000) + Weight::from_ref_time(94_028_000) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -338,7 +339,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:0) // Storage: PredictionMarkets Disputes (r:0 w:1) fn internal_resolve_scalar_reported() -> Weight { - Weight::from_ref_time(88_350_000) + Weight::from_ref_time(35_443_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -350,7 +351,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: MarketCommons MarketPool (r:1 w:0) fn internal_resolve_scalar_disputed() -> Weight { - Weight::from_ref_time(133_121_000) + Weight::from_ref_time(60_764_000) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -364,15 +365,15 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketIdsPerReportBlock (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:1 w:1) fn on_initialize_resolve_overhead() -> Weight { - Weight::from_ref_time(38_470_000) + Weight::from_ref_time(14_258_000) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(8)) } // Storage: PredictionMarkets MarketsCollectingSubsidy (r:1 w:1) fn process_subsidy_collecting_markets_raw(a: u32) -> Weight { - Weight::from_ref_time(8_741_000) - // Standard Error: 3_000 - .saturating_add(Weight::from_ref_time(268_000).saturating_mul(a.into())) + Weight::from_ref_time(3_089_324) + // Standard Error: 547 + .saturating_add(Weight::from_ref_time(97_367).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -381,7 +382,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: Tokens TotalIssuance (r:1 w:1) fn redeem_shares_categorical() -> Weight { - Weight::from_ref_time(118_191_000) + Weight::from_ref_time(57_384_000) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -390,7 +391,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: Tokens TotalIssuance (r:2 w:2) fn redeem_shares_scalar() -> Weight { - Weight::from_ref_time(149_560_000) + Weight::from_ref_time(60_727_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -399,20 +400,24 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketIdsPerCloseTimeFrame (r:1 w:1) // Storage: Balances Reserves (r:1 w:1) // Storage: PredictionMarkets MarketIdsForEdit (r:0 w:1) - fn reject_market(c: u32, _o: u32, r: u32) -> Weight { - Weight::from_ref_time(126_400_000) - // Standard Error: 4_000 - .saturating_add(Weight::from_ref_time(1_000).saturating_mul(c.into())) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000).saturating_mul(r.into())) + fn reject_market(c: u32, o: u32, r: u32) -> Weight { + Weight::from_ref_time(51_879_457) + // Standard Error: 358 + .saturating_add(Weight::from_ref_time(22_537).saturating_mul(c.into())) + // Standard Error: 358 + .saturating_add(Weight::from_ref_time(12_584).saturating_mul(o.into())) + // Standard Error: 22 + .saturating_add(Weight::from_ref_time(475).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: MarketCommons Markets (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) // Storage: PredictionMarkets MarketIdsPerReportBlock (r:1 w:1) - fn report(_m: u32) -> Weight { - Weight::from_ref_time(58_983_000) + fn report(m: u32) -> Weight { + Weight::from_ref_time(23_497_754) + // Standard Error: 338 + .saturating_add(Weight::from_ref_time(6_734).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -421,9 +426,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:2 w:2) // Storage: Tokens TotalIssuance (r:2 w:2) fn sell_complete_set(a: u32) -> Weight { - Weight::from_ref_time(54_681_000) - // Standard Error: 40_000 - .saturating_add(Weight::from_ref_time(27_784_000).saturating_mul(a.into())) + Weight::from_ref_time(35_416_984) + // Standard Error: 1_858 + .saturating_add(Weight::from_ref_time(11_608_572).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1)) @@ -436,9 +441,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: PredictionMarkets MarketsCollectingSubsidy (r:1 w:1) // Storage: Swaps Pools (r:0 w:1) fn start_subsidy(a: u32) -> Weight { - Weight::from_ref_time(56_316_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(110_000).saturating_mul(a.into())) + Weight::from_ref_time(23_573_263) + // Standard Error: 226 + .saturating_add(Weight::from_ref_time(42_261).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -446,11 +451,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons Markets (r:32 w:0) // Storage: PredictionMarkets MarketIdsPerOpenTimeFrame (r:1 w:1) fn market_status_manager(b: u32, f: u32) -> Weight { - Weight::from_ref_time(59_397_000) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(3_327_000).saturating_mul(b.into())) - // Standard Error: 9_000 - .saturating_add(Weight::from_ref_time(3_297_000).saturating_mul(f.into())) + Weight::from_ref_time(27_286_425) + // Standard Error: 1_160 + .saturating_add(Weight::from_ref_time(1_511_142).saturating_mul(b.into())) + // Standard Error: 1_160 + .saturating_add(Weight::from_ref_time(1_501_105).saturating_mul(f.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(f.into()))) @@ -460,11 +465,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons Markets (r:32 w:0) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:1 w:1) fn market_resolution_manager(r: u32, d: u32) -> Weight { - Weight::from_ref_time(62_079_000) - // Standard Error: 8_000 - .saturating_add(Weight::from_ref_time(3_374_000).saturating_mul(r.into())) - // Standard Error: 8_000 - .saturating_add(Weight::from_ref_time(3_206_000).saturating_mul(d.into())) + Weight::from_ref_time(25_238_195) + // Standard Error: 767 + .saturating_add(Weight::from_ref_time(1_555_436).saturating_mul(r.into())) + // Standard Error: 767 + .saturating_add(Weight::from_ref_time(1_589_138).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(d.into()))) @@ -472,7 +477,7 @@ impl WeightInfoZeitgeist for WeightInfo { } // Storage: PredictionMarkets MarketsCollectingSubsidy (r:1 w:1) fn process_subsidy_collecting_markets_dummy() -> Weight { - Weight::from_ref_time(7_620_000) + Weight::from_ref_time(2_968_000) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/zrml/styx/src/weights.rs b/zrml/styx/src/weights.rs index ec465bab8..9dfffaf89 100644 --- a/zrml/styx/src/weights.rs +++ b/zrml/styx/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_styx //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -55,12 +55,12 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Styx Crossings (r:1 w:1) // Storage: Styx BurnAmount (r:1 w:0) fn cross() -> Weight { - Weight::from_ref_time(54_610_000) + Weight::from_ref_time(23_072_000) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Styx BurnAmount (r:0 w:1) fn set_burn_amount() -> Weight { - Weight::from_ref_time(22_410_000).saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(9_025_000).saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/zrml/swaps/src/weights.rs b/zrml/swaps/src/weights.rs index db45bbe7f..b0f3b373c 100644 --- a/zrml/swaps/src/weights.rs +++ b/zrml/swaps/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for zrml_swaps //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-20, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-08, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -80,9 +80,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:0) // Storage: Swaps Pools (r:1 w:1) fn admin_clean_up_pool_cpmm_categorical(a: u32) -> Weight { - Weight::from_ref_time(58_086_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(583_000).saturating_mul(a.into())) + Weight::from_ref_time(25_692_254) + // Standard Error: 614 + .saturating_add(Weight::from_ref_time(284_413).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -90,7 +90,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons MarketPool (r:1 w:0) // Storage: Swaps Pools (r:1 w:1) fn admin_clean_up_pool_cpmm_scalar() -> Weight { - Weight::from_ref_time(58_390_000) + Weight::from_ref_time(22_556_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -100,9 +100,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:7 w:0) // Storage: Tokens TotalIssuance (r:64 w:64) fn apply_to_cached_pools_execute_arbitrage(a: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 803_000 - .saturating_add(Weight::from_ref_time(2_356_167_000).saturating_mul(a.into())) + Weight::from_ref_time(313_000) + // Standard Error: 71_767 + .saturating_add(Weight::from_ref_time(912_062_521).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(43)) .saturating_add(T::DbWeight::get().reads((70_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(42)) @@ -110,9 +110,9 @@ impl WeightInfoZeitgeist for WeightInfo { } // Storage: Swaps PoolsCachedForArbitrage (r:8 w:7) fn apply_to_cached_pools_noop(a: u32) -> Weight { - Weight::from_ref_time(6_148_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(8_898_000).saturating_mul(a.into())) + Weight::from_ref_time(313_000) + // Standard Error: 999 + .saturating_add(Weight::from_ref_time(3_519_461).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -122,9 +122,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: RikiddoSigmoidFeeMarketEma RikiddoPerPool (r:1 w:1) // Storage: Tokens Accounts (r:1 w:1) fn destroy_pool_in_subsidy_phase(a: u32) -> Weight { - Weight::from_ref_time(47_422_000) - // Standard Error: 40_000 - .saturating_add(Weight::from_ref_time(21_468_000).saturating_mul(a.into())) + Weight::from_ref_time(20_746_815) + // Standard Error: 6_870 + .saturating_add(Weight::from_ref_time(9_588_841).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -134,11 +134,11 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:46 w:21) // Storage: System Account (r:11 w:10) fn distribute_pool_share_rewards(a: u32, b: u32) -> Weight { - Weight::from_ref_time(55_071_000) - // Standard Error: 180_000 - .saturating_add(Weight::from_ref_time(28_979_000).saturating_mul(a.into())) - // Standard Error: 180_000 - .saturating_add(Weight::from_ref_time(40_233_000).saturating_mul(b.into())) + Weight::from_ref_time(22_860_268) + // Standard Error: 18_875 + .saturating_add(Weight::from_ref_time(10_760_963).saturating_mul(a.into())) + // Standard Error: 18_875 + .saturating_add(Weight::from_ref_time(19_119_205).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(b.into()))) @@ -152,26 +152,28 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens TotalIssuance (r:2 w:2) // Storage: RikiddoSigmoidFeeMarketEma RikiddoPerPool (r:1 w:0) fn end_subsidy_phase(a: u32, b: u32) -> Weight { - Weight::from_ref_time(0) - // Standard Error: 168_000 - .saturating_add(Weight::from_ref_time(26_503_000).saturating_mul(a.into())) - // Standard Error: 1_034_000 - .saturating_add(Weight::from_ref_time(126_477_000).saturating_mul(b.into())) + Weight::from_ref_time(13_533_000) + // Standard Error: 35_634 + .saturating_add(Weight::from_ref_time(8_213_437).saturating_mul(a.into())) + // Standard Error: 236_657 + .saturating_add(Weight::from_ref_time(36_459_831).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) - .saturating_add(T::DbWeight::get().reads((9_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(a.into()))) - .saturating_add(T::DbWeight::get().writes((9_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(b.into()))) } // Storage: Swaps Pools (r:1 w:0) // Storage: Tokens Accounts (r:3 w:3) // Storage: System Account (r:1 w:0) // Storage: Tokens TotalIssuance (r:1 w:1) fn execute_arbitrage_buy_burn(a: u32) -> Weight { - Weight::from_ref_time(61_994_000) - // Standard Error: 34_000 - .saturating_add(Weight::from_ref_time(36_370_000).saturating_mul(a.into())) + Weight::from_ref_time(33_878_547) + // Standard Error: 9_283 + .saturating_add(Weight::from_ref_time(15_010_607).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) + .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(a.into()))) } // Storage: Swaps Pools (r:1 w:0) @@ -179,9 +181,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:2 w:1) // Storage: Tokens TotalIssuance (r:1 w:1) fn execute_arbitrage_mint_sell(a: u32) -> Weight { - Weight::from_ref_time(80_675_000) - // Standard Error: 31_000 - .saturating_add(Weight::from_ref_time(33_433_000).saturating_mul(a.into())) + Weight::from_ref_time(38_285_437) + // Standard Error: 9_089 + .saturating_add(Weight::from_ref_time(13_998_473).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1)) @@ -190,9 +192,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Swaps Pools (r:1 w:0) // Storage: Tokens Accounts (r:2 w:0) fn execute_arbitrage_skipped(a: u32) -> Weight { - Weight::from_ref_time(29_826_000) - // Standard Error: 13_000 - .saturating_add(Weight::from_ref_time(5_199_000).saturating_mul(a.into())) + Weight::from_ref_time(14_828_448) + // Standard Error: 1_025 + .saturating_add(Weight::from_ref_time(2_204_192).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) } @@ -201,9 +203,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:5 w:5) // Storage: System Account (r:1 w:0) fn pool_exit(a: u32) -> Weight { - Weight::from_ref_time(64_421_000) - // Standard Error: 34_000 - .saturating_add(Weight::from_ref_time(27_430_000).saturating_mul(a.into())) + Weight::from_ref_time(37_507_291) + // Standard Error: 2_130 + .saturating_add(Weight::from_ref_time(11_575_025).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -213,7 +215,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Swaps SubsidyProviders (r:1 w:1) // Storage: Tokens Accounts (r:1 w:1) fn pool_exit_subsidy() -> Weight { - Weight::from_ref_time(77_761_000) + Weight::from_ref_time(37_934_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -223,7 +225,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: Swaps PoolsCachedForArbitrage (r:0 w:1) fn pool_exit_with_exact_asset_amount() -> Weight { - Weight::from_ref_time(142_560_000) + Weight::from_ref_time(69_851_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -233,7 +235,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: Swaps PoolsCachedForArbitrage (r:0 w:1) fn pool_exit_with_exact_pool_amount() -> Weight { - Weight::from_ref_time(143_190_000) + Weight::from_ref_time(69_798_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -241,9 +243,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens TotalIssuance (r:1 w:1) // Storage: Tokens Accounts (r:5 w:5) fn pool_join(a: u32) -> Weight { - Weight::from_ref_time(74_055_000) - // Standard Error: 32_000 - .saturating_add(Weight::from_ref_time(26_488_000).saturating_mul(a.into())) + Weight::from_ref_time(33_804_359) + // Standard Error: 2_236 + .saturating_add(Weight::from_ref_time(11_351_296).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(2)) @@ -253,7 +255,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:1 w:1) // Storage: Swaps SubsidyProviders (r:1 w:1) fn pool_join_subsidy() -> Weight { - Weight::from_ref_time(78_671_000) + Weight::from_ref_time(38_045_000) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -262,7 +264,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:3 w:3) // Storage: Swaps PoolsCachedForArbitrage (r:0 w:1) fn pool_join_with_exact_asset_amount() -> Weight { - Weight::from_ref_time(128_600_000) + Weight::from_ref_time(63_348_000) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -271,15 +273,15 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:3 w:3) // Storage: Swaps PoolsCachedForArbitrage (r:0 w:1) fn pool_join_with_exact_pool_amount() -> Weight { - Weight::from_ref_time(132_720_000) + Weight::from_ref_time(63_817_000) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Swaps Pools (r:1 w:1) fn clean_up_pool_categorical_without_reward_distribution(a: u32) -> Weight { - Weight::from_ref_time(16_673_000) - // Standard Error: 1_000 - .saturating_add(Weight::from_ref_time(325_000).saturating_mul(a.into())) + Weight::from_ref_time(5_597_769) + // Standard Error: 274 + .saturating_add(Weight::from_ref_time(163_354).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -288,7 +290,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: Swaps PoolsCachedForArbitrage (r:0 w:1) fn swap_exact_amount_in_cpmm() -> Weight { - Weight::from_ref_time(170_520_000) + Weight::from_ref_time(81_657_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -299,9 +301,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: Timestamp Now (r:1 w:0) fn swap_exact_amount_in_rikiddo(a: u32) -> Weight { - Weight::from_ref_time(159_946_000) - // Standard Error: 28_000 - .saturating_add(Weight::from_ref_time(19_270_000).saturating_mul(a.into())) + Weight::from_ref_time(72_975_675) + // Standard Error: 2_451 + .saturating_add(Weight::from_ref_time(7_367_384).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(5)) @@ -311,7 +313,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: Swaps PoolsCachedForArbitrage (r:0 w:1) fn swap_exact_amount_out_cpmm() -> Weight { - Weight::from_ref_time(169_581_000) + Weight::from_ref_time(81_923_000) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -321,26 +323,26 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: RikiddoSigmoidFeeMarketEma RikiddoPerPool (r:1 w:1) // Storage: Timestamp Now (r:1 w:0) fn swap_exact_amount_out_rikiddo(a: u32) -> Weight { - Weight::from_ref_time(101_410_000) - // Standard Error: 42_000 - .saturating_add(Weight::from_ref_time(35_542_000).saturating_mul(a.into())) + Weight::from_ref_time(52_010_503) + // Standard Error: 3_021 + .saturating_add(Weight::from_ref_time(12_822_294).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Swaps Pools (r:1 w:1) fn open_pool(a: u32) -> Weight { - Weight::from_ref_time(28_613_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(559_000).saturating_mul(a.into())) + Weight::from_ref_time(12_568_363) + // Standard Error: 435 + .saturating_add(Weight::from_ref_time(244_095).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Swaps Pools (r:1 w:1) fn close_pool(a: u32) -> Weight { - Weight::from_ref_time(31_634_000) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(366_000).saturating_mul(a.into())) + Weight::from_ref_time(11_445_465) + // Standard Error: 326 + .saturating_add(Weight::from_ref_time(192_402).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -349,9 +351,9 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: Tokens TotalIssuance (r:2 w:2) fn destroy_pool(a: u32) -> Weight { - Weight::from_ref_time(38_770_000) - // Standard Error: 30_000 - .saturating_add(Weight::from_ref_time(26_154_000).saturating_mul(a.into())) + Weight::from_ref_time(22_588_099) + // Standard Error: 1_893 + .saturating_add(Weight::from_ref_time(10_954_266).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(2)) From 7f90a9a5207be03857159de2be79d11da0f34d00 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Wed, 8 Feb 2023 18:45:16 +0530 Subject: [PATCH 07/22] Remove commented code which is not required --- external/pallets/author-inherent/src/mock.rs | 1 - external/pallets/author-mapping/src/mock.rs | 20 ------------------- .../pallets/parachain-staking/src/mock.rs | 1 - .../pallets/parachain-staking/src/tests.rs | 6 ------ node/src/service/service_parachain.rs | 2 -- runtime/common/src/lib.rs | 3 --- runtime/zeitgeist/src/xcm_config/config.rs | 1 - 7 files changed, 34 deletions(-) diff --git a/external/pallets/author-inherent/src/mock.rs b/external/pallets/author-inherent/src/mock.rs index adf8af605..933bcc47d 100644 --- a/external/pallets/author-inherent/src/mock.rs +++ b/external/pallets/author-inherent/src/mock.rs @@ -16,7 +16,6 @@ use crate::{self as pallet_testing, AccountLookup, NimbusId}; use frame_support::{parameter_types, traits::ConstU32, weights::RuntimeDbWeight}; -// use frame_system; use sp_core::H256; use sp_runtime::{ testing::Header, diff --git a/external/pallets/author-mapping/src/mock.rs b/external/pallets/author-mapping/src/mock.rs index dded03085..2fe143c66 100644 --- a/external/pallets/author-mapping/src/mock.rs +++ b/external/pallets/author-mapping/src/mock.rs @@ -27,7 +27,6 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_core::{ByteArray, H256}; -// use sp_io; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, Perbill, RuntimeDebug, @@ -45,16 +44,6 @@ impl Default for TestAuthor { TestAuthor::Alice } } -// impl Into for TestAuthor { -// fn into(self) -> NimbusId { -// match self { -// Self::Alice => NimbusId::from_slice(&[0u8; 32]), -// Self::Bob => NimbusId::from_slice(&[1u8; 32]), -// Self::Charlie => NimbusId::from_slice(&[2u8; 32]), -// } -// .expect("valid ids") -// } -// } impl From for NimbusId { fn from(test_author: TestAuthor) -> Self { match test_author { @@ -154,15 +143,6 @@ pub(crate) struct ExtBuilder { mappings: Vec<(NimbusId, AccountId)>, } -// impl Default for ExtBuilder { -// fn default() -> ExtBuilder { -// ExtBuilder { -// balances: vec![], -// mappings: vec![], -// } -// } -// } - impl ExtBuilder { pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { self.balances = balances; diff --git a/external/pallets/parachain-staking/src/mock.rs b/external/pallets/parachain-staking/src/mock.rs index 5aed26987..c8bf3ba3a 100644 --- a/external/pallets/parachain-staking/src/mock.rs +++ b/external/pallets/parachain-staking/src/mock.rs @@ -26,7 +26,6 @@ use frame_support::{ weights::{constants::RocksDbWeight, Weight}, }; use sp_core::H256; -// use sp_io; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, Perbill, Percent, diff --git a/external/pallets/parachain-staking/src/tests.rs b/external/pallets/parachain-staking/src/tests.rs index 464129f84..acd93210c 100644 --- a/external/pallets/parachain-staking/src/tests.rs +++ b/external/pallets/parachain-staking/src/tests.rs @@ -1722,7 +1722,6 @@ fn sufficient_delegate_weight_hint_succeeds() { .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) .build() .execute_with(|| { - // let mut count = 4u32; for (count, i) in (7..11).enumerate() { assert_ok!(ParachainStaking::delegate( RuntimeOrigin::signed(i), @@ -1731,9 +1730,7 @@ fn sufficient_delegate_weight_hint_succeeds() { count as u32, 0u32 )); - // count += 1u32; } - // let mut count = 0u32; for (count, i) in (3..11).enumerate() { assert_ok!(ParachainStaking::delegate( RuntimeOrigin::signed(i), @@ -1742,7 +1739,6 @@ fn sufficient_delegate_weight_hint_succeeds() { count as u32, 1u32 )); - // count += 1u32; } }); } @@ -5205,10 +5201,8 @@ fn no_selected_candidates_defaults_to_last_round_collators() { // check AtStake matches previous let new_selected_candidates = ParachainStaking::selected_candidates(); assert_eq!(old_selected_candidates, new_selected_candidates); - // let mut index = 0usize; for (index, account) in new_selected_candidates.into_iter().enumerate() { assert_eq!(old_at_stake_snapshots[index], >::get(new_round, account)); - // index += 1usize; } }); } diff --git a/node/src/service/service_parachain.rs b/node/src/service/service_parachain.rs index 6f4e3f7ea..c134c8ff5 100644 --- a/node/src/service/service_parachain.rs +++ b/node/src/service/service_parachain.rs @@ -19,7 +19,6 @@ use crate::{ service::{AdditionalRuntimeApiCollection, RuntimeApiCollection}, KUSAMA_BLOCK_DURATION, SOFT_DEADLINE_PERCENT, }; -// use cumulus_client_cli::CollatorOptions; use cumulus_client_consensus_common::ParachainConsensus; use cumulus_client_network::BlockAnnounceValidator; use cumulus_client_service::{ @@ -390,7 +389,6 @@ where relay_chain_interface, relay_chain_slot_duration, import_queue, - // collator_options: CollatorOptions { relay_chain_rpc_url: Default::default() }, }; start_full_node(params)?; diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 471bd642d..d0625c6cd 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -473,7 +473,6 @@ macro_rules! impl_config_traits { #[cfg(not(feature = "parachain"))] impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; - // type RuntimeCall = RuntimeCall; type KeyOwnerProofSystem = (); type KeyOwnerProof = ; type CooloffPeriod = CooloffPeriod; - // type PreimageByteDeposit = PreimageByteDeposit; - // type OperationalPreimageOrigin = pallet_collective::EnsureMember; type Slash = Treasury; type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; diff --git a/runtime/zeitgeist/src/xcm_config/config.rs b/runtime/zeitgeist/src/xcm_config/config.rs index 620bff6b8..35dde4499 100644 --- a/runtime/zeitgeist/src/xcm_config/config.rs +++ b/runtime/zeitgeist/src/xcm_config/config.rs @@ -71,7 +71,6 @@ impl Config for XcmConfig { type Barrier = Barrier; /// The outer call dispatch type. type RuntimeCall = RuntimeCall; - // type CallDispatcher = Call; /// Combinations of (Location, Asset) pairs which are trusted as reserves. // Trust the parent chain, sibling parachains and children chains of this chain. type IsReserve = MultiNativeAsset; From d74e5b1dbb88ff9a3601ddf0c597a8e5f8b1312c Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Thu, 9 Feb 2023 13:52:49 +0530 Subject: [PATCH 08/22] Minor fix --- runtime/battery-station/src/xcm_config/config.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/battery-station/src/xcm_config/config.rs b/runtime/battery-station/src/xcm_config/config.rs index c09995566..9ac97faa8 100644 --- a/runtime/battery-station/src/xcm_config/config.rs +++ b/runtime/battery-station/src/xcm_config/config.rs @@ -71,7 +71,6 @@ impl Config for XcmConfig { type Barrier = Barrier; /// The outer call dispatch type. type RuntimeCall = RuntimeCall; - // type CallDispatcher = Call; /// Combinations of (Location, Asset) pairs which are trusted as reserves. // Trust the parent chain, sibling parachains and children chains of this chain. type IsReserve = MultiNativeAsset; From 7d4f526d3c2880c5a15f71ce731633b7886d6acf Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Thu, 9 Feb 2023 14:51:42 +0530 Subject: [PATCH 09/22] Fix WeightInfo usage --- .../author-slot-filter/src/migration.rs | 2 ++ runtime/common/src/lib.rs | 18 +++++++++--------- runtime/common/src/weights/mod.rs | 12 ++++++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/external/pallets/author-slot-filter/src/migration.rs b/external/pallets/author-slot-filter/src/migration.rs index a9a7572ca..5f47afe58 100644 --- a/external/pallets/author-slot-filter/src/migration.rs +++ b/external/pallets/author-slot-filter/src/migration.rs @@ -19,8 +19,10 @@ use frame_support::{ traits::{Get, OnRuntimeUpgrade}, weights::Weight, }; +#[cfg(feature = "try-runtime")] use parity_scale_codec::{Decode, Encode}; use sp_runtime::Percent; +#[cfg(feature = "try-runtime")] use sp_std::vec::Vec; use super::{ diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index d0625c6cd..61f5f6e64 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -434,7 +434,7 @@ macro_rules! impl_config_traits { type RuntimeOrigin = RuntimeOrigin; type PalletInfo = PalletInfo; type SS58Prefix = SS58Prefix; - type SystemWeightInfo = frame_system::weights::SubstrateWeight; + type SystemWeightInfo = weights::frame_system::WeightInfo; type Version = Version; } @@ -450,7 +450,7 @@ macro_rules! impl_config_traits { type AccountLookup = AuthorMapping; type CanAuthor = AuthorFilter; type SlotBeacon = cumulus_pallet_parachain_system::RelaychainBlockNumberProvider; - type WeightInfo = pallet_author_inherent::weights::SubstrateWeight; + type WeightInfo = weights::pallet_author_inherent::WeightInfo; } #[cfg(feature = "parachain")] @@ -459,7 +459,7 @@ macro_rules! impl_config_traits { type DepositCurrency = Balances; type RuntimeEvent = RuntimeEvent; type Keys = session_keys_primitives::VrfId; - type WeightInfo = pallet_author_mapping::weights::SubstrateWeight; + type WeightInfo = weights::pallet_author_mapping::WeightInfo; } #[cfg(feature = "parachain")] @@ -467,7 +467,7 @@ macro_rules! impl_config_traits { type RuntimeEvent = RuntimeEvent; type RandomnessSource = RandomnessCollectiveFlip; type PotentialAuthors = ParachainStaking; - type WeightInfo = pallet_author_slot_filter::weights::SubstrateWeight; + type WeightInfo = weights::pallet_author_slot_filter::WeightInfo; } #[cfg(not(feature = "parachain"))] @@ -537,7 +537,7 @@ macro_rules! impl_config_traits { type OnNewRound = (); type RevokeDelegationDelay = RevokeDelegationDelay; type RewardPaymentDelay = RewardPaymentDelay; - type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; + type WeightInfo = weights::pallet_parachain_staking::WeightInfo; } #[cfg(feature = "parachain")] @@ -688,7 +688,7 @@ macro_rules! impl_config_traits { type Scheduler = Scheduler; type PalletsOrigin = OriginCaller; type MaxVotes = MaxVotes; - type WeightInfo = pallet_democracy::weights::SubstrateWeight; + type WeightInfo = weights::pallet_democracy::WeightInfo; type MaxProposals = MaxProposals; type Preimages = Preimage; type MaxBlacklisted = ConstU32<100>; @@ -756,7 +756,7 @@ macro_rules! impl_config_traits { type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = ConstU16<100>; - type WeightInfo = pallet_multisig::weights::SubstrateWeight; + type WeightInfo = weights::pallet_multisig::WeightInfo; } impl pallet_preimage::Config for Runtime { @@ -808,7 +808,7 @@ macro_rules! impl_config_traits { type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; type MaxProxies = ConstU32<32>; - type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type WeightInfo = weights::pallet_proxy::WeightInfo; type MaxPending = ConstU32<32>; type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; @@ -825,7 +825,7 @@ macro_rules! impl_config_traits { type MaximumWeight = MaximumSchedulerWeight; type ScheduleOrigin = EnsureRoot; type MaxScheduledPerBlock = MaxScheduledPerBlock; - type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type WeightInfo = weights::pallet_scheduler::WeightInfo; type OriginPrivilegeCmp = EqualPrivilegeOnly; type Preimages = Preimage; } diff --git a/runtime/common/src/weights/mod.rs b/runtime/common/src/weights/mod.rs index efb8f6fd9..77c452a24 100644 --- a/runtime/common/src/weights/mod.rs +++ b/runtime/common/src/weights/mod.rs @@ -18,6 +18,10 @@ cfg_if::cfg_if! { if #[cfg(feature = "parachain")] { pub mod cumulus_pallet_xcmp_queue; + pub mod pallet_author_mapping; + pub mod pallet_author_inherent; + pub mod pallet_author_slot_filter; + pub mod pallet_parachain_staking; } else { // Currently the benchmark does yield an invalid weight implementation // pub mod pallet_grandpa; @@ -30,13 +34,13 @@ pub mod orml_tokens; pub mod pallet_balances; pub mod pallet_bounties; pub mod pallet_collective; -// pub mod pallet_democracy; +pub mod pallet_democracy; pub mod pallet_identity; pub mod pallet_membership; -// pub mod pallet_multisig; +pub mod pallet_multisig; pub mod pallet_preimage; -// pub mod pallet_proxy; -// pub mod pallet_scheduler; +pub mod pallet_proxy; +pub mod pallet_scheduler; pub mod pallet_timestamp; pub mod pallet_treasury; pub mod pallet_utility; From 599dd5724d11d50688ddbdeff80165cab7037dc8 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Thu, 9 Feb 2023 15:55:38 +0530 Subject: [PATCH 10/22] Format --- .../src/weights/pallet_author_inherent.rs | 5 ++- .../src/weights/pallet_author_mapping.rs | 5 ++- .../src/weights/pallet_author_slot_filter.rs | 8 +++-- .../common/src/weights/pallet_democracy.rs | 33 +++++++++---------- runtime/common/src/weights/pallet_multisig.rs | 19 ++++++----- .../src/weights/pallet_parachain_staking.rs | 30 +++++++++-------- runtime/common/src/weights/pallet_proxy.rs | 25 +++++++------- .../common/src/weights/pallet_scheduler.rs | 20 ++++++----- 8 files changed, 81 insertions(+), 64 deletions(-) diff --git a/runtime/common/src/weights/pallet_author_inherent.rs b/runtime/common/src/weights/pallet_author_inherent.rs index c06de9694..36012744b 100644 --- a/runtime/common/src/weights/pallet_author_inherent.rs +++ b/runtime/common/src/weights/pallet_author_inherent.rs @@ -39,8 +39,11 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_author_inherent (automatically generated) pub struct WeightInfo(PhantomData); diff --git a/runtime/common/src/weights/pallet_author_mapping.rs b/runtime/common/src/weights/pallet_author_mapping.rs index 4c1090caa..292d70249 100644 --- a/runtime/common/src/weights/pallet_author_mapping.rs +++ b/runtime/common/src/weights/pallet_author_mapping.rs @@ -39,8 +39,11 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_author_mapping (automatically generated) pub struct WeightInfo(PhantomData); diff --git a/runtime/common/src/weights/pallet_author_slot_filter.rs b/runtime/common/src/weights/pallet_author_slot_filter.rs index c2179a461..003b07c56 100644 --- a/runtime/common/src/weights/pallet_author_slot_filter.rs +++ b/runtime/common/src/weights/pallet_author_slot_filter.rs @@ -39,15 +39,17 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_author_slot_filter (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_author_slot_filter::weights::WeightInfo for WeightInfo { // Storage: AuthorFilter EligibleCount (r:0 w:1) fn set_eligible() -> Weight { - Weight::from_ref_time(9_073_000) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(9_073_000).saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/common/src/weights/pallet_democracy.rs b/runtime/common/src/weights/pallet_democracy.rs index 2083a31cb..5613ae742 100644 --- a/runtime/common/src/weights/pallet_democracy.rs +++ b/runtime/common/src/weights/pallet_democracy.rs @@ -39,8 +39,11 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_democracy (automatically generated) pub struct WeightInfo(PhantomData); @@ -103,13 +106,11 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - Weight::from_ref_time(3_060_000) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(3_060_000).saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - Weight::from_ref_time(3_068_000) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(3_068_000).saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) @@ -136,13 +137,12 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - Weight::from_ref_time(9_790_000) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(9_790_000).saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:2 w:0) - fn on_initialize_base(r: u32, ) -> Weight { + fn on_initialize_base(r: u32) -> Weight { Weight::from_ref_time(8_978_113) // Standard Error: 4_589 .saturating_add(Weight::from_ref_time(1_536_205).saturating_mul(r.into())) @@ -156,7 +156,7 @@ impl pallet_democracy::weights::WeightInfo for WeightIn // Storage: Democracy NextExternal (r:1 w:0) // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:2 w:0) - fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { + fn on_initialize_base_with_launch_period(r: u32) -> Weight { Weight::from_ref_time(10_988_037) // Standard Error: 4_483 .saturating_add(Weight::from_ref_time(1_538_250).saturating_mul(r.into())) @@ -167,7 +167,7 @@ impl pallet_democracy::weights::WeightInfo for WeightIn // Storage: Democracy VotingOf (r:3 w:3) // Storage: Balances Locks (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:2 w:2) - fn delegate(r: u32, ) -> Weight { + fn delegate(r: u32) -> Weight { Weight::from_ref_time(33_942_458) // Standard Error: 6_275 .saturating_add(Weight::from_ref_time(2_384_438).saturating_mul(r.into())) @@ -178,7 +178,7 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:2 w:2) - fn undelegate(r: u32, ) -> Weight { + fn undelegate(r: u32) -> Weight { Weight::from_ref_time(20_552_008) // Standard Error: 4_945 .saturating_add(Weight::from_ref_time(2_352_801).saturating_mul(r.into())) @@ -189,13 +189,12 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - Weight::from_ref_time(4_079_000) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(4_079_000).saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_remove(r: u32, ) -> Weight { + fn unlock_remove(r: u32) -> Weight { Weight::from_ref_time(23_309_726) // Standard Error: 1_610 .saturating_add(Weight::from_ref_time(51_836).saturating_mul(r.into())) @@ -205,7 +204,7 @@ impl pallet_democracy::weights::WeightInfo for WeightIn // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn unlock_set(r: u32, ) -> Weight { + fn unlock_set(r: u32) -> Weight { Weight::from_ref_time(23_116_641) // Standard Error: 932 .saturating_add(Weight::from_ref_time(78_997).saturating_mul(r.into())) @@ -214,7 +213,7 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) - fn remove_vote(r: u32, ) -> Weight { + fn remove_vote(r: u32) -> Weight { Weight::from_ref_time(13_637_289) // Standard Error: 991 .saturating_add(Weight::from_ref_time(83_991).saturating_mul(r.into())) @@ -223,7 +222,7 @@ impl pallet_democracy::weights::WeightInfo for WeightIn } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) - fn remove_other_vote(r: u32, ) -> Weight { + fn remove_other_vote(r: u32) -> Weight { Weight::from_ref_time(14_220_574) // Standard Error: 3_420 .saturating_add(Weight::from_ref_time(81_496).saturating_mul(r.into())) diff --git a/runtime/common/src/weights/pallet_multisig.rs b/runtime/common/src/weights/pallet_multisig.rs index 11934552e..a72247e8f 100644 --- a/runtime/common/src/weights/pallet_multisig.rs +++ b/runtime/common/src/weights/pallet_multisig.rs @@ -39,20 +39,23 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_multisig (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_multisig::weights::WeightInfo for WeightInfo { - fn as_multi_threshold_1(z: u32, ) -> Weight { + fn as_multi_threshold_1(z: u32) -> Weight { Weight::from_ref_time(15_009_826) // Standard Error: 4 .saturating_add(Weight::from_ref_time(279).saturating_mul(z.into())) } // Storage: MultiSig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) - fn as_multi_create(s: u32, z: u32, ) -> Weight { + fn as_multi_create(s: u32, z: u32) -> Weight { Weight::from_ref_time(26_652_211) // Standard Error: 1_415 .saturating_add(Weight::from_ref_time(94_659).saturating_mul(s.into())) @@ -62,7 +65,7 @@ impl pallet_multisig::weights::WeightInfo for WeightInf .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - fn as_multi_approve(s: u32, z: u32, ) -> Weight { + fn as_multi_approve(s: u32, z: u32) -> Weight { Weight::from_ref_time(20_049_942) // Standard Error: 908 .saturating_add(Weight::from_ref_time(84_603).saturating_mul(s.into())) @@ -73,7 +76,7 @@ impl pallet_multisig::weights::WeightInfo for WeightInf } // Storage: MultiSig Multisigs (r:1 w:1) // Storage: System Account (r:1 w:1) - fn as_multi_complete(s: u32, z: u32, ) -> Weight { + fn as_multi_complete(s: u32, z: u32) -> Weight { Weight::from_ref_time(27_852_359) // Standard Error: 1_356 .saturating_add(Weight::from_ref_time(117_468).saturating_mul(s.into())) @@ -84,7 +87,7 @@ impl pallet_multisig::weights::WeightInfo for WeightInf } // Storage: MultiSig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) - fn approve_as_multi_create(s: u32, ) -> Weight { + fn approve_as_multi_create(s: u32) -> Weight { Weight::from_ref_time(24_697_515) // Standard Error: 1_850 .saturating_add(Weight::from_ref_time(97_497).saturating_mul(s.into())) @@ -92,7 +95,7 @@ impl pallet_multisig::weights::WeightInfo for WeightInf .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - fn approve_as_multi_approve(s: u32, ) -> Weight { + fn approve_as_multi_approve(s: u32) -> Weight { Weight::from_ref_time(17_670_882) // Standard Error: 1_328 .saturating_add(Weight::from_ref_time(94_493).saturating_mul(s.into())) @@ -100,7 +103,7 @@ impl pallet_multisig::weights::WeightInfo for WeightInf .saturating_add(T::DbWeight::get().writes(1)) } // Storage: MultiSig Multisigs (r:1 w:1) - fn cancel_as_multi(s: u32, ) -> Weight { + fn cancel_as_multi(s: u32) -> Weight { Weight::from_ref_time(24_687_555) // Standard Error: 1_647 .saturating_add(Weight::from_ref_time(108_089).saturating_mul(s.into())) diff --git a/runtime/common/src/weights/pallet_parachain_staking.rs b/runtime/common/src/weights/pallet_parachain_staking.rs index d383dfed5..de0928cb0 100644 --- a/runtime/common/src/weights/pallet_parachain_staking.rs +++ b/runtime/common/src/weights/pallet_parachain_staking.rs @@ -39,8 +39,11 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_parachain_staking (automatically generated) pub struct WeightInfo(PhantomData); @@ -99,7 +102,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking Total (r:1 w:1) // Storage: ParachainStaking TopDelegations (r:0 w:1) // Storage: ParachainStaking BottomDelegations (r:0 w:1) - fn join_candidates(x: u32, ) -> Weight { + fn join_candidates(x: u32) -> Weight { Weight::from_ref_time(32_869_323) // Standard Error: 1_610 .saturating_add(Weight::from_ref_time(193_154).saturating_mul(x.into())) @@ -109,7 +112,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking Round (r:1 w:0) // Storage: ParachainStaking CandidatePool (r:1 w:1) - fn schedule_leave_candidates(x: u32, ) -> Weight { + fn schedule_leave_candidates(x: u32) -> Weight { Weight::from_ref_time(25_820_357) // Standard Error: 1_488 .saturating_add(Weight::from_ref_time(174_057).saturating_mul(x.into())) @@ -126,7 +129,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) // Storage: ParachainStaking BottomDelegations (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) - fn execute_leave_candidates(x: u32, ) -> Weight { + fn execute_leave_candidates(x: u32) -> Weight { Weight::from_ref_time(62_477_000) // Standard Error: 41_796 .saturating_add(Weight::from_ref_time(15_946_001).saturating_mul(x.into())) @@ -137,7 +140,7 @@ impl pallet_parachain_staking::weights::WeightInfo for } // Storage: ParachainStaking CandidateInfo (r:1 w:1) // Storage: ParachainStaking CandidatePool (r:1 w:1) - fn cancel_leave_candidates(x: u32, ) -> Weight { + fn cancel_leave_candidates(x: u32) -> Weight { Weight::from_ref_time(23_095_410) // Standard Error: 1_510 .saturating_add(Weight::from_ref_time(190_401).saturating_mul(x.into())) @@ -199,7 +202,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking CandidatePool (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) - fn delegate(_x: u32, y: u32, ) -> Weight { + fn delegate(_x: u32, y: u32) -> Weight { Weight::from_ref_time(98_852_381) // Standard Error: 3_632 .saturating_add(Weight::from_ref_time(74_937).saturating_mul(y.into())) @@ -224,7 +227,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) - fn execute_leave_delegators(x: u32, ) -> Weight { + fn execute_leave_delegators(x: u32) -> Weight { Weight::from_ref_time(17_452_622) // Standard Error: 21_795 .saturating_add(Weight::from_ref_time(13_924_996).saturating_mul(x.into())) @@ -326,7 +329,7 @@ impl pallet_parachain_staking::weights::WeightInfo for } // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) // Storage: ParachainStaking TopDelegations (r:1 w:0) - fn get_rewardable_delegators(y: u32, ) -> Weight { + fn get_rewardable_delegators(y: u32) -> Weight { Weight::from_ref_time(9_044_052) // Standard Error: 934 .saturating_add(Weight::from_ref_time(166_721).saturating_mul(y.into())) @@ -340,7 +343,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) // Storage: ParachainStaking SelectedCandidates (r:0 w:1) // Storage: ParachainStaking AtStake (r:0 w:1) - fn select_top_candidates(x: u32, y: u32, ) -> Weight { + fn select_top_candidates(x: u32, y: u32) -> Weight { Weight::from_ref_time(19_457_000) // Standard Error: 194_470 .saturating_add(Weight::from_ref_time(14_446_541).saturating_mul(x.into())) @@ -356,7 +359,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: ParachainStaking AtStake (r:2 w:1) // Storage: ParachainStaking AwardedPts (r:1 w:1) // Storage: System Account (r:1 w:1) - fn pay_one_collator_reward(y: u32, ) -> Weight { + fn pay_one_collator_reward(y: u32) -> Weight { Weight::from_ref_time(41_033_942) // Standard Error: 5_622 .saturating_add(Weight::from_ref_time(7_673_326).saturating_mul(y.into())) @@ -367,12 +370,11 @@ impl pallet_parachain_staking::weights::WeightInfo for } // Storage: ParachainStaking Round (r:1 w:0) fn base_on_initialize() -> Weight { - Weight::from_ref_time(5_312_000) - .saturating_add(T::DbWeight::get().reads(1)) + Weight::from_ref_time(5_312_000).saturating_add(T::DbWeight::get().reads(1)) } // Storage: ParachainStaking DelegatorState (r:1 w:0) // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - fn set_auto_compound(x: u32, y: u32, ) -> Weight { + fn set_auto_compound(x: u32, y: u32) -> Weight { Weight::from_ref_time(42_718_871) // Standard Error: 2_814 .saturating_add(Weight::from_ref_time(161_876).saturating_mul(x.into())) @@ -390,7 +392,7 @@ impl pallet_parachain_staking::weights::WeightInfo for // Storage: Balances Locks (r:1 w:1) // Storage: ParachainStaking Total (r:1 w:1) // Storage: ParachainStaking BottomDelegations (r:1 w:1) - fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { + fn delegate_with_auto_compound(x: u32, y: u32, _z: u32) -> Weight { Weight::from_ref_time(100_631_109) // Standard Error: 2_763 .saturating_add(Weight::from_ref_time(81_505).saturating_mul(x.into())) diff --git a/runtime/common/src/weights/pallet_proxy.rs b/runtime/common/src/weights/pallet_proxy.rs index 9c02efb67..c35946fba 100644 --- a/runtime/common/src/weights/pallet_proxy.rs +++ b/runtime/common/src/weights/pallet_proxy.rs @@ -39,14 +39,17 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_proxy (automatically generated) pub struct WeightInfo(PhantomData); impl pallet_proxy::weights::WeightInfo for WeightInfo { // Storage: Proxy Proxies (r:1 w:0) - fn proxy(p: u32, ) -> Weight { + fn proxy(p: u32) -> Weight { Weight::from_ref_time(14_846_152) // Standard Error: 3_656 .saturating_add(Weight::from_ref_time(20_035).saturating_mul(p.into())) @@ -55,7 +58,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn proxy_announced(a: u32, p: u32) -> Weight { Weight::from_ref_time(29_808_110) // Standard Error: 3_086 .saturating_add(Weight::from_ref_time(68_700).saturating_mul(a.into())) @@ -66,7 +69,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn remove_announcement(a: u32, _p: u32) -> Weight { Weight::from_ref_time(21_154_842) // Standard Error: 2_354 .saturating_add(Weight::from_ref_time(67_662).saturating_mul(a.into())) @@ -75,7 +78,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn reject_announcement(a: u32, _p: u32) -> Weight { Weight::from_ref_time(20_587_474) // Standard Error: 2_191 .saturating_add(Weight::from_ref_time(91_044).saturating_mul(a.into())) @@ -85,7 +88,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn announce(a: u32, p: u32) -> Weight { Weight::from_ref_time(25_960_647) // Standard Error: 3_453 .saturating_add(Weight::from_ref_time(90_065).saturating_mul(a.into())) @@ -95,7 +98,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn add_proxy(p: u32) -> Weight { Weight::from_ref_time(21_515_673) // Standard Error: 9_730 .saturating_add(Weight::from_ref_time(27_609).saturating_mul(p.into())) @@ -103,7 +106,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn remove_proxy(p: u32) -> Weight { Weight::from_ref_time(20_632_234) // Standard Error: 2_374 .saturating_add(Weight::from_ref_time(68_381).saturating_mul(p.into())) @@ -111,7 +114,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn remove_proxies(p: u32) -> Weight { Weight::from_ref_time(17_793_375) // Standard Error: 1_672 .saturating_add(Weight::from_ref_time(42_726).saturating_mul(p.into())) @@ -120,7 +123,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn create_pure(p: u32) -> Weight { Weight::from_ref_time(22_473_896) // Standard Error: 1_953 .saturating_add(Weight::from_ref_time(15_155).saturating_mul(p.into())) @@ -128,7 +131,7 @@ impl pallet_proxy::weights::WeightInfo for WeightInfo Weight { + fn kill_pure(p: u32) -> Weight { Weight::from_ref_time(18_850_050) // Standard Error: 1_796 .saturating_add(Weight::from_ref_time(42_672).saturating_mul(p.into())) diff --git a/runtime/common/src/weights/pallet_scheduler.rs b/runtime/common/src/weights/pallet_scheduler.rs index ddf141ff7..fa11f06f5 100644 --- a/runtime/common/src/weights/pallet_scheduler.rs +++ b/runtime/common/src/weights/pallet_scheduler.rs @@ -39,8 +39,11 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; /// Weight functions for pallet_scheduler (automatically generated) pub struct WeightInfo(PhantomData); @@ -52,7 +55,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Scheduler Agenda (r:1 w:1) - fn service_agenda_base(s: u32, ) -> Weight { + fn service_agenda_base(s: u32) -> Weight { Weight::from_ref_time(5_402_281) // Standard Error: 2_213 .saturating_add(Weight::from_ref_time(239_796).saturating_mul(s.into())) @@ -64,7 +67,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn } // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) - fn service_task_fetched(s: u32, ) -> Weight { + fn service_task_fetched(s: u32) -> Weight { Weight::from_ref_time(15_508_000) // Standard Error: 6 .saturating_add(Weight::from_ref_time(902).saturating_mul(s.into())) @@ -73,8 +76,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn } // Storage: Scheduler Lookup (r:0 w:1) fn service_task_named() -> Weight { - Weight::from_ref_time(7_623_000) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_ref_time(7_623_000).saturating_add(T::DbWeight::get().writes(1)) } fn service_task_periodic() -> Weight { Weight::from_ref_time(6_381_000) @@ -86,7 +88,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn Weight::from_ref_time(2_690_000) } // Storage: Scheduler Agenda (r:1 w:1) - fn schedule(s: u32, ) -> Weight { + fn schedule(s: u32) -> Weight { Weight::from_ref_time(14_386_290) // Standard Error: 8_210 .saturating_add(Weight::from_ref_time(290_508).saturating_mul(s.into())) @@ -95,7 +97,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) - fn cancel(s: u32, ) -> Weight { + fn cancel(s: u32) -> Weight { Weight::from_ref_time(14_618_067) // Standard Error: 2_673 .saturating_add(Weight::from_ref_time(244_365).saturating_mul(s.into())) @@ -104,7 +106,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) - fn schedule_named(s: u32, ) -> Weight { + fn schedule_named(s: u32) -> Weight { Weight::from_ref_time(17_125_968) // Standard Error: 3_579 .saturating_add(Weight::from_ref_time(283_692).saturating_mul(s.into())) @@ -113,7 +115,7 @@ impl pallet_scheduler::weights::WeightInfo for WeightIn } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) - fn cancel_named(s: u32, ) -> Weight { + fn cancel_named(s: u32) -> Weight { Weight::from_ref_time(16_091_884) // Standard Error: 2_674 .saturating_add(Weight::from_ref_time(274_337).saturating_mul(s.into())) From 648a761a317e193570e053ed412da5ed58fa5c6a Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Fri, 10 Feb 2023 12:10:36 +0530 Subject: [PATCH 11/22] Fix migration for pallet scheduler --- runtime/common/src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 61f5f6e64..bef099e49 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -45,12 +45,20 @@ pub mod weights; macro_rules! decl_common_types { {} => { use sp_runtime::generic; - use frame_support::traits::{Currency, Imbalance, OnUnbalanced, NeverEnsureOrigin, TryStateSelect}; + use frame_support::traits::{Currency, Imbalance, OnRuntimeUpgrade, OnUnbalanced, NeverEnsureOrigin, TryStateSelect}; pub type Block = generic::Block; type Address = sp_runtime::MultiAddress; + // Migration for scheduler pallet to move from a plain RuntimeCall to a CallOrHash. + pub struct SchedulerMigrationV1toV4; + impl OnRuntimeUpgrade for SchedulerMigrationV1toV4 { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + Scheduler::migrate_v1_to_v4() + } + } + #[cfg(feature = "parachain")] pub type Executive = frame_executive::Executive< Runtime, @@ -59,10 +67,10 @@ macro_rules! decl_common_types { Runtime, AllPalletsWithSystem, ( + SchedulerMigrationV1toV4, pallet_multisig::migrations::v1::MigrateToV1, pallet_preimage::migration::v1::Migration, pallet_democracy::migrations::v1::Migration, - pallet_scheduler::migration::v3::MigrateToV4, zrml_prediction_markets::migrations::AddOutsiderBond, ), >; @@ -75,10 +83,10 @@ macro_rules! decl_common_types { Runtime, AllPalletsWithSystem, ( + SchedulerMigrationV1toV4, pallet_multisig::migrations::v1::MigrateToV1, pallet_preimage::migration::v1::Migration, pallet_democracy::migrations::v1::Migration, - pallet_scheduler::migration::v3::MigrateToV4, zrml_prediction_markets::migrations::AddOutsiderBond, ), >; From 1920fc43d1319ff44c333bd5b6918131870fd2e9 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Fri, 10 Feb 2023 13:30:58 +0530 Subject: [PATCH 12/22] Upgrade log crate version --- external/pallets/author-mapping/Cargo.toml | 2 +- external/pallets/parachain-staking/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/external/pallets/author-mapping/Cargo.toml b/external/pallets/author-mapping/Cargo.toml index 9727abba7..83442efa3 100644 --- a/external/pallets/author-mapping/Cargo.toml +++ b/external/pallets/author-mapping/Cargo.toml @@ -6,7 +6,7 @@ name = "pallet-author-mapping" version = "2.0.5" [dependencies] -log = { version = "0.4", default-features = false } +log = { version = "0.4.17", default-features = false } serde = { version = "1.0.124", optional = true } # Substrate diff --git a/external/pallets/parachain-staking/Cargo.toml b/external/pallets/parachain-staking/Cargo.toml index 3b596e3fa..f0777ee6a 100644 --- a/external/pallets/parachain-staking/Cargo.toml +++ b/external/pallets/parachain-staking/Cargo.toml @@ -6,7 +6,7 @@ name = "pallet-parachain-staking" version = "3.0.0" [dependencies] -log = "0.4" +log = "0.4.17" serde = { version = "1.0.101", optional = true } # Substrate From 39be367b451bf85a88882530c8fa5ad010d891f8 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Fri, 10 Feb 2023 15:25:21 +0530 Subject: [PATCH 13/22] Fix CI issue --- .github/workflows/benchmark.yml | 3 +++ .github/workflows/migration.yml | 3 +++ .github/workflows/rust.yml | 15 +++++++++++++++ .github/workflows/tag.yml | 6 ++++++ 4 files changed, 27 insertions(+) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index e39b9c046..83b3d1660 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -17,6 +17,9 @@ jobs: run: shell: bash steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler # Ensure that at most one benchmark worklow runs across all workflows - name: Turnstyle uses: softprops/turnstyle@v1 diff --git a/.github/workflows/migration.yml b/.github/workflows/migration.yml index 02b4857cd..c7b2785c0 100644 --- a/.github/workflows/migration.yml +++ b/.github/workflows/migration.yml @@ -11,6 +11,9 @@ jobs: name: Test migration runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v2 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6921659a6..a2a2474a5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,6 +14,9 @@ jobs: name: Format runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v2 @@ -45,6 +48,9 @@ jobs: "standalone" ] steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v2 @@ -60,6 +66,9 @@ jobs: name: Quick check benchmarks runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v2 @@ -72,6 +81,9 @@ jobs: name: Tests runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v2 @@ -110,6 +122,9 @@ jobs: name: Fuzz runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v2 diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 49b2fe453..1c4af3b64 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -10,6 +10,9 @@ jobs: name: Test Try Runtime runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v3 @@ -27,6 +30,9 @@ jobs: name: Test Try Runtime runs-on: ubuntu-latest steps: + - name: Install ProtoBuf Compiler + run: | + sudo apt-get install protobuf-compiler - name: Checkout repository uses: actions/checkout@v3 From ef859b68c1a4bbed58e53c3ee6504081f23ced0a Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Fri, 10 Feb 2023 17:59:38 +0530 Subject: [PATCH 14/22] Fix fuzz test --- zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs b/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs index 718c2837e..7f43e5f9f 100644 --- a/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs +++ b/zrml/orderbook-v1/fuzz/orderbook_v1_full_workflow.rs @@ -21,7 +21,7 @@ use frame_system::ensure_signed; use libfuzzer_sys::fuzz_target; use zeitgeist_primitives::types::{Asset, ScalarPosition, SerdeWrapper}; use zrml_orderbook_v1::{ - mock::{ExtBuilder, Orderbook, Origin}, + mock::{ExtBuilder, Orderbook, RuntimeOrigin}, OrderSide, }; From 574029ad2438d6aa797e44102f3d7ed8e905364e Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Tue, 21 Feb 2023 15:45:08 +0530 Subject: [PATCH 15/22] Move code from external directory to separate repo on github.com --- Cargo.lock | 177 +- Cargo.toml | 16 - external/nimbus-consensus/Cargo.toml | 39 - external/nimbus-consensus/src/import_queue.rs | 253 - external/nimbus-consensus/src/lib.rs | 415 - external/nimbus-consensus/src/manual_seal.rs | 130 - external/nimbus-primitives/Cargo.toml | 40 - external/nimbus-primitives/src/digests.rs | 80 - external/nimbus-primitives/src/inherents.rs | 52 - external/nimbus-primitives/src/lib.rs | 184 - external/pallets/author-inherent/Cargo.toml | 53 - .../pallets/author-inherent/src/benchmarks.rs | 29 - external/pallets/author-inherent/src/exec.rs | 94 - external/pallets/author-inherent/src/lib.rs | 245 - external/pallets/author-inherent/src/mock.rs | 103 - external/pallets/author-inherent/src/tests.rs | 71 - .../pallets/author-inherent/src/weights.rs | 91 - external/pallets/author-mapping/Cargo.toml | 50 - external/pallets/author-mapping/migrations.md | 10 - .../pallets/author-mapping/src/benchmarks.rs | 154 - external/pallets/author-mapping/src/lib.rs | 366 - .../pallets/author-mapping/src/migrations.rs | 179 - external/pallets/author-mapping/src/mock.rs | 178 - external/pallets/author-mapping/src/tests.rs | 432 -- .../pallets/author-mapping/src/weights.rs | 159 - .../pallets/author-slot-filter/Cargo.toml | 45 - .../author-slot-filter/src/benchmarks.rs | 43 - .../pallets/author-slot-filter/src/lib.rs | 225 - .../author-slot-filter/src/migration.rs | 103 - .../pallets/author-slot-filter/src/mock.rs | 86 - .../pallets/author-slot-filter/src/num.rs | 122 - .../pallets/author-slot-filter/src/tests.rs | 93 - .../pallets/author-slot-filter/src/weights.rs | 70 - external/pallets/parachain-staking/Cargo.toml | 45 - external/pallets/parachain-staking/README.md | 26 - .../pallets/parachain-staking/migrations.md | 42 - .../parachain-staking/src/auto_compound.rs | 326 - .../parachain-staking/src/benchmarks.rs | 1483 ---- .../src/delegation_requests.rs | 647 -- .../parachain-staking/src/inflation.rs | 208 - external/pallets/parachain-staking/src/lib.rs | 1850 ----- .../parachain-staking/src/migrations.rs | 181 - .../pallets/parachain-staking/src/mock.rs | 970 --- external/pallets/parachain-staking/src/set.rs | 89 - .../pallets/parachain-staking/src/tests.rs | 6909 ----------------- .../pallets/parachain-staking/src/traits.rs | 66 - .../pallets/parachain-staking/src/types.rs | 1630 ---- .../pallets/parachain-staking/src/weights.rs | 903 --- external/session-keys/Cargo.toml | 42 - external/session-keys/src/digest.rs | 63 - external/session-keys/src/inherent.rs | 76 - external/session-keys/src/lib.rs | 45 - external/session-keys/src/vrf.rs | 100 - external/vrf/Cargo.toml | 27 - external/vrf/src/lib.rs | 71 - node/Cargo.toml | 12 +- runtime/battery-station/Cargo.toml | 12 +- runtime/common/Cargo.toml | 8 +- runtime/zeitgeist/Cargo.toml | 12 +- 59 files changed, 32 insertions(+), 20198 deletions(-) delete mode 100644 external/nimbus-consensus/Cargo.toml delete mode 100644 external/nimbus-consensus/src/import_queue.rs delete mode 100644 external/nimbus-consensus/src/lib.rs delete mode 100644 external/nimbus-consensus/src/manual_seal.rs delete mode 100644 external/nimbus-primitives/Cargo.toml delete mode 100644 external/nimbus-primitives/src/digests.rs delete mode 100644 external/nimbus-primitives/src/inherents.rs delete mode 100644 external/nimbus-primitives/src/lib.rs delete mode 100644 external/pallets/author-inherent/Cargo.toml delete mode 100644 external/pallets/author-inherent/src/benchmarks.rs delete mode 100644 external/pallets/author-inherent/src/exec.rs delete mode 100644 external/pallets/author-inherent/src/lib.rs delete mode 100644 external/pallets/author-inherent/src/mock.rs delete mode 100644 external/pallets/author-inherent/src/tests.rs delete mode 100644 external/pallets/author-inherent/src/weights.rs delete mode 100644 external/pallets/author-mapping/Cargo.toml delete mode 100644 external/pallets/author-mapping/migrations.md delete mode 100644 external/pallets/author-mapping/src/benchmarks.rs delete mode 100644 external/pallets/author-mapping/src/lib.rs delete mode 100644 external/pallets/author-mapping/src/migrations.rs delete mode 100644 external/pallets/author-mapping/src/mock.rs delete mode 100644 external/pallets/author-mapping/src/tests.rs delete mode 100644 external/pallets/author-mapping/src/weights.rs delete mode 100644 external/pallets/author-slot-filter/Cargo.toml delete mode 100644 external/pallets/author-slot-filter/src/benchmarks.rs delete mode 100644 external/pallets/author-slot-filter/src/lib.rs delete mode 100644 external/pallets/author-slot-filter/src/migration.rs delete mode 100644 external/pallets/author-slot-filter/src/mock.rs delete mode 100644 external/pallets/author-slot-filter/src/num.rs delete mode 100644 external/pallets/author-slot-filter/src/tests.rs delete mode 100644 external/pallets/author-slot-filter/src/weights.rs delete mode 100644 external/pallets/parachain-staking/Cargo.toml delete mode 100644 external/pallets/parachain-staking/README.md delete mode 100644 external/pallets/parachain-staking/migrations.md delete mode 100644 external/pallets/parachain-staking/src/auto_compound.rs delete mode 100644 external/pallets/parachain-staking/src/benchmarks.rs delete mode 100644 external/pallets/parachain-staking/src/delegation_requests.rs delete mode 100644 external/pallets/parachain-staking/src/inflation.rs delete mode 100644 external/pallets/parachain-staking/src/lib.rs delete mode 100644 external/pallets/parachain-staking/src/migrations.rs delete mode 100644 external/pallets/parachain-staking/src/mock.rs delete mode 100644 external/pallets/parachain-staking/src/set.rs delete mode 100644 external/pallets/parachain-staking/src/tests.rs delete mode 100644 external/pallets/parachain-staking/src/traits.rs delete mode 100644 external/pallets/parachain-staking/src/types.rs delete mode 100644 external/pallets/parachain-staking/src/weights.rs delete mode 100644 external/session-keys/Cargo.toml delete mode 100644 external/session-keys/src/digest.rs delete mode 100644 external/session-keys/src/inherent.rs delete mode 100644 external/session-keys/src/lib.rs delete mode 100644 external/session-keys/src/vrf.rs delete mode 100644 external/vrf/Cargo.toml delete mode 100644 external/vrf/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e911c2518..d850e6412 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -443,15 +443,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" -[[package]] -name = "basic-toml" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e819b667739967cd44d308b8c7b71305d8bb0729ac44a248aa08f33d01950b4" -dependencies = [ - "serde", -] - [[package]] name = "battery-station-runtime" version = "0.3.8" @@ -812,17 +803,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", -] - [[package]] name = "bstr" version = "1.1.0" @@ -1168,18 +1148,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "console" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "windows-sys 0.42.0", -] - [[package]] name = "const-oid" version = "0.7.1" @@ -2021,12 +1989,6 @@ dependencies = [ "syn", ] -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - [[package]] name = "difflib" version = "0.4.0" @@ -2103,12 +2065,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "dissimilar" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e" - [[package]] name = "dns-parser" version = "0.8.0" @@ -2237,12 +2193,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "enum-as-inner" version = "0.5.1" @@ -2753,40 +2703,6 @@ dependencies = [ "syn", ] -[[package]] -name = "frame-support-test" -version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" -dependencies = [ - "frame-support", - "frame-support-test-pallet", - "frame-system", - "parity-scale-codec", - "pretty_assertions", - "rustversion", - "scale-info", - "serde", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-version", - "trybuild", -] - -[[package]] -name = "frame-support-test-pallet" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.32#5ea6d95309aaccfa399c5f72e5a14a4b7c6c4ca1" -dependencies = [ - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", -] - [[package]] name = "frame-system" version = "4.0.0-dev" @@ -3100,7 +3016,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", - "bstr 1.1.0", + "bstr", "fnv", "log", "regex", @@ -4664,6 +4580,7 @@ dependencies = [ [[package]] name = "moonbeam-vrf" version = "0.1.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "nimbus-primitives", "parity-scale-codec", @@ -4876,6 +4793,7 @@ dependencies = [ [[package]] name = "nimbus-consensus" version = "0.9.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -4906,6 +4824,7 @@ dependencies = [ [[package]] name = "nimbus-primitives" version = "0.9.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "async-trait", "frame-benchmarking", @@ -5308,15 +5227,6 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - [[package]] name = "packed_simd_2" version = "0.3.8" @@ -5346,10 +5256,10 @@ dependencies = [ [[package]] name = "pallet-author-inherent" version = "0.9.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "frame-benchmarking", "frame-support", - "frame-support-test", "frame-system", "log", "nimbus-primitives", @@ -5358,9 +5268,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-authorship", - "sp-core", "sp-inherents", - "sp-io", "sp-runtime", "sp-std", ] @@ -5368,19 +5276,17 @@ dependencies = [ [[package]] name = "pallet-author-mapping" version = "2.0.5" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "nimbus-primitives", - "pallet-balances", "parity-scale-codec", "scale-info", "serde", "session-keys-primitives", - "sp-core", - "sp-io", "sp-runtime", "sp-std", ] @@ -5388,10 +5294,10 @@ dependencies = [ [[package]] name = "pallet-author-slot-filter" version = "0.9.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "frame-benchmarking", "frame-support", - "frame-support-test", "frame-system", "log", "nimbus-primitives", @@ -5399,7 +5305,6 @@ dependencies = [ "scale-info", "serde", "sp-core", - "sp-io", "sp-runtime", "sp-std", ] @@ -5945,19 +5850,16 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", "nimbus-primitives", - "pallet-balances", "parity-scale-codec", "scale-info", "serde", - "similar-asserts", - "sp-core", - "sp-io", "sp-runtime", "sp-std", "substrate-fixed", @@ -7999,18 +7901,6 @@ dependencies = [ "termtree", ] -[[package]] -name = "pretty_assertions" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" -dependencies = [ - "ctor", - "diff", - "output_vt100", - "yansi", -] - [[package]] name = "prettyplease" version = "0.1.23" @@ -10129,6 +10019,7 @@ dependencies = [ [[package]] name = "session-keys-primitives" version = "0.1.0" +source = "git+https://github.com/zeitgeistpm/external#fc957f4629c4a4ee650d912e5d1cf1d50c1a2126" dependencies = [ "async-trait", "frame-support", @@ -10261,26 +10152,6 @@ dependencies = [ "paste", ] -[[package]] -name = "similar" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" -dependencies = [ - "bstr 0.2.17", - "unicode-segmentation", -] - -[[package]] -name = "similar-asserts" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18" -dependencies = [ - "console", - "similar", -] - [[package]] name = "slab" version = "0.4.7" @@ -11934,22 +11805,6 @@ dependencies = [ "zstd", ] -[[package]] -name = "trybuild" -version = "1.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44da5a6f2164c8e14d3bbc0657d69c5966af9f5f6930d4f600b1f5c4a673413" -dependencies = [ - "basic-toml", - "dissimilar", - "glob", - "once_cell", - "serde", - "serde_derive", - "serde_json", - "termcolor", -] - [[package]] name = "tt-call" version = "1.0.9" @@ -11962,7 +11817,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.6", "rand 0.8.5", "static_assertions", @@ -12031,12 +11886,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - [[package]] name = "unicode-width" version = "0.1.10" @@ -12945,12 +12794,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - [[package]] name = "zeitgeist-node" version = "0.3.8" diff --git a/Cargo.toml b/Cargo.toml index 98144fe60..d38578d8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,5 @@ [workspace] default-members = [ - "external/nimbus-consensus", - "external/nimbus-primitives", - "external/pallets/author-inherent", - "external/pallets/author-mapping", - "external/pallets/author-slot-filter", - "external/pallets/parachain-staking", - "external/session-keys", - "external/vrf", "node", "primitives", "runtime/common", @@ -29,14 +21,6 @@ default-members = [ "zrml/styx", ] members = [ - "external/nimbus-consensus", - "external/nimbus-primitives", - "external/pallets/author-inherent", - "external/pallets/author-mapping", - "external/pallets/author-slot-filter", - "external/pallets/parachain-staking", - "external/session-keys", - "external/vrf", "node", "primitives", "runtime/common", diff --git a/external/nimbus-consensus/Cargo.toml b/external/nimbus-consensus/Cargo.toml deleted file mode 100644 index 783b1f44d..000000000 --- a/external/nimbus-consensus/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -description = "Client-side worker for the Nimbus family of consensus algorithms" -edition = "2021" -name = "nimbus-consensus" -version = "0.9.0" -[dependencies] -# Substrate deps -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } - -# Polkadot dependencies -polkadot-client = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.32" } - -# Cumulus dependencies -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.32" } - -# Nimbus Dependencies -nimbus-primitives = { path = "../nimbus-primitives" } - -# Other deps -async-trait = "0.1" -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } -futures = { version = "0.3.24", features = ["compat"] } -log = "0.4.17" -parking_lot = "0.12" -tracing = "0.1.22" diff --git a/external/nimbus-consensus/src/import_queue.rs b/external/nimbus-consensus/src/import_queue.rs deleted file mode 100644 index 09560669a..000000000 --- a/external/nimbus-consensus/src/import_queue.rs +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use std::{marker::PhantomData, sync::Arc}; - -use log::debug; -use nimbus_primitives::{digests::CompatibleDigestItem, NimbusId, NimbusPair, NIMBUS_ENGINE_ID}; -use sc_consensus::{ - import_queue::{BasicQueue, Verifier as VerifierT}, - BlockImport, BlockImportParams, -}; -use sp_api::ProvideRuntimeApi; -use sp_application_crypto::{ByteArray, Pair as _}; -use sp_block_builder::BlockBuilder as BlockBuilderApi; -use sp_blockchain::Result as ClientResult; -use sp_consensus::{error::Error as ConsensusError, CacheKeyId}; -use sp_inherents::{CreateInherentDataProviders, InherentDataProvider}; -use sp_runtime::{ - generic::BlockId, - traits::{Block as BlockT, Header as HeaderT}, - DigestItem, -}; - -/// The Nimbus verifier strips the seal digest, and checks that it is a valid signature by -/// the same key that was injected into the runtime and noted in the Seal digest. -/// From Nimbu's perspective any block that faithfully reports its authorship to the runtime -/// is valid. The intention is that the runtime itself may then put further restrictions on -/// the identity of the author. -struct Verifier { - client: Arc, - create_inherent_data_providers: CIDP, - _marker: PhantomData, -} - -#[async_trait::async_trait] -impl VerifierT for Verifier -where - Block: BlockT, - Client: ProvideRuntimeApi + Send + Sync, - >::Api: BlockBuilderApi, - CIDP: CreateInherentDataProviders, -{ - async fn verify( - &mut self, - mut block_params: BlockImportParams, - ) -> Result<(BlockImportParams, Option)>>), String> { - debug!( - target: crate::LOG_TARGET, - "🪲 Header hash before popping digest {:?}", - block_params.header.hash() - ); - // Grab the seal digest. Assume it is last (since it is a seal after-all). - let seal = block_params - .header - .digest_mut() - .pop() - .expect("Block should have at least one digest on it"); - - let signature = seal.as_nimbus_seal().ok_or_else(|| String::from("HeaderUnsealed"))?; - - debug!( - target: crate::LOG_TARGET, - "🪲 Header hash after popping digest {:?}", - block_params.header.hash() - ); - - debug!(target: crate::LOG_TARGET, "🪲 Signature according to verifier is {:?}", signature); - - // Grab the author information from either the preruntime digest or the consensus digest - //TODO use the trait - let claimed_author = block_params - .header - .digest() - .logs - .iter() - .find_map(|digest| match *digest { - DigestItem::Consensus(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - _ => None, - }) - .expect("Expected one consensus or pre-runtime digest that contains author id bytes"); - - debug!( - target: crate::LOG_TARGET, - "🪲 Claimed Author according to verifier is {:?}", claimed_author - ); - - // Verify the signature - let valid_signature = NimbusPair::verify( - &signature, - block_params.header.hash(), - &NimbusId::from_slice(&claimed_author) - .map_err(|_| "Invalid Nimbus ID (wrong length)")?, - ); - - debug!(target: crate::LOG_TARGET, "🪲 Valid signature? {:?}", valid_signature); - - if !valid_signature { - return Err("Block signature invalid".into()); - } - - // This part copied from RelayChainConsensus. I guess this is the inherent checking. - if let Some(inner_body) = block_params.body.take() { - let inherent_data_providers = self - .create_inherent_data_providers - .create_inherent_data_providers(*block_params.header.parent_hash(), ()) - .await - .map_err(|e| e.to_string())?; - - let inherent_data = - inherent_data_providers.create_inherent_data().map_err(|e| format!("{:?}", e))?; - - let block = Block::new(block_params.header.clone(), inner_body); - - let inherent_res = self - .client - .runtime_api() - .check_inherents( - &BlockId::Hash(*block_params.header.parent_hash()), - block.clone(), - inherent_data, - ) - .map_err(|e| format!("{:?}", e))?; - - if !inherent_res.ok() { - for (i, e) in inherent_res.into_errors() { - match inherent_data_providers.try_handle_error(&i, &e).await { - Some(r) => r.map_err(|e| format!("{:?}", e))?, - None => Err(format!( - "Unhandled inherent error from `{}`.", - String::from_utf8_lossy(&i) - ))?, - } - } - } - - let (_, inner_body) = block.deconstruct(); - block_params.body = Some(inner_body); - } - - block_params.post_digests.push(seal); - - // The standard is to use the longest chain rule. This is overridden by the `NimbusBlockImport` in the parachain context. - block_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::LongestChain); - - debug!( - target: crate::LOG_TARGET, - "🪲 Just finished verifier. posthash from params is {:?}", - &block_params.post_hash() - ); - - Ok((block_params, None)) - } -} - -/// Start an import queue for a Cumulus collator that does not uses any special authoring logic. -pub fn import_queue( - client: Arc, - block_import: I, - create_inherent_data_providers: CIDP, - spawner: &impl sp_core::traits::SpawnEssentialNamed, - registry: Option<&substrate_prometheus_endpoint::Registry>, - parachain: bool, -) -> ClientResult> -where - I: BlockImport + Send + Sync + 'static, - I::Transaction: Send, - Client: ProvideRuntimeApi + Send + Sync + 'static, - >::Api: BlockBuilderApi, - CIDP: CreateInherentDataProviders + 'static, -{ - let verifier = Verifier { client, create_inherent_data_providers, _marker: PhantomData }; - - Ok(BasicQueue::new( - verifier, - Box::new(NimbusBlockImport::new(block_import, parachain)), - None, - spawner, - registry, - )) -} - -/// Nimbus specific block import. -/// -/// Nimbus supports both parachain and non-parachain contexts. In the parachain -/// context, new blocks should not be imported as best. Cumulus's ParachainBlockImport -/// handles this correctly, but does not work in non-parachain contexts. -/// This block import has a field indicating whether we should apply parachain rules or not. -/// -/// There may be additional nimbus-specific logic here in the future, but for now it is -/// only the conditional parachain logic -pub struct NimbusBlockImport { - inner: I, - parachain_context: bool, -} - -impl NimbusBlockImport { - /// Create a new instance. - pub fn new(inner: I, parachain_context: bool) -> Self { - Self { inner, parachain_context } - } -} - -#[async_trait::async_trait] -impl BlockImport for NimbusBlockImport -where - Block: BlockT, - I: BlockImport + Send, -{ - type Error = I::Error; - type Transaction = I::Transaction; - - async fn check_block( - &mut self, - block: sc_consensus::BlockCheckParams, - ) -> Result { - self.inner.check_block(block).await - } - - async fn import_block( - &mut self, - mut block_import_params: sc_consensus::BlockImportParams, - cache: std::collections::HashMap>, - ) -> Result { - // If we are in the parachain context, best block is determined by the relay chain - // except during initial sync - if self.parachain_context { - block_import_params.fork_choice = Some(sc_consensus::ForkChoiceStrategy::Custom( - block_import_params.origin == sp_consensus::BlockOrigin::NetworkInitialSync, - )); - } - - // Now continue on to the rest of the import pipeline. - self.inner.import_block(block_import_params, cache).await - } -} diff --git a/external/nimbus-consensus/src/lib.rs b/external/nimbus-consensus/src/lib.rs deleted file mode 100644 index e4a711fee..000000000 --- a/external/nimbus-consensus/src/lib.rs +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! The nimbus consensus client-side worker -//! -//! It queries the in-runtime filter to determine whether any keys -//! stored in its keystore are eligible to author at this slot. If it has an eligible -//! key it authors. - -use cumulus_client_consensus_common::{ - ParachainBlockImport, ParachainCandidate, ParachainConsensus, -}; -use cumulus_primitives_core::{relay_chain::v2::Hash as PHash, ParaId, PersistedValidationData}; -pub use import_queue::import_queue; -use log::{debug, info, warn}; -use nimbus_primitives::{ - CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_KEY_ID, -}; -use parking_lot::Mutex; -use sc_consensus::{BlockImport, BlockImportParams}; -use sp_api::{BlockId, ProvideRuntimeApi}; -use sp_application_crypto::{ByteArray, CryptoTypePublicPair}; -use sp_consensus::{ - BlockOrigin, EnableProofRecording, Environment, ProofRecording, Proposal, Proposer, -}; -use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; -use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; -use sp_runtime::{ - traits::{Block as BlockT, Header as HeaderT}, - DigestItem, -}; -use std::{convert::TryInto, marker::PhantomData, sync::Arc, time::Duration}; -use tracing::error; -mod import_queue; -mod manual_seal; -pub use manual_seal::NimbusManualSealConsensusDataProvider; - -const LOG_TARGET: &str = "filtering-consensus"; - -/// The implementation of the relay-chain provided consensus for parachains. -pub struct NimbusConsensus { - para_id: ParaId, - proposer_factory: Arc>, - create_inherent_data_providers: Arc, - block_import: Arc>>, - parachain_client: Arc, - keystore: SyncCryptoStorePtr, - skip_prediction: bool, - additional_digests_provider: Arc, - _phantom: PhantomData, -} - -impl Clone for NimbusConsensus { - fn clone(&self) -> Self { - Self { - para_id: self.para_id, - proposer_factory: self.proposer_factory.clone(), - create_inherent_data_providers: self.create_inherent_data_providers.clone(), - block_import: self.block_import.clone(), - parachain_client: self.parachain_client.clone(), - keystore: self.keystore.clone(), - skip_prediction: self.skip_prediction, - additional_digests_provider: self.additional_digests_provider.clone(), - _phantom: PhantomData, - } - } -} - -impl NimbusConsensus -where - B: BlockT, - PF: 'static, - BI: 'static, - ParaClient: ProvideRuntimeApi + 'static, - CIDP: CreateInherentDataProviders + 'static, - DP: DigestsProvider::Hash> + 'static, -{ - /// Create a new instance of nimbus consensus. - pub fn build( - BuildNimbusConsensusParams { - para_id, - proposer_factory, - create_inherent_data_providers, - block_import, - parachain_client, - keystore, - skip_prediction, - additional_digests_provider, - }: BuildNimbusConsensusParams, - ) -> Box> - where - Self: ParachainConsensus, - { - Box::new(Self { - para_id, - proposer_factory: Arc::new(Mutex::new(proposer_factory)), - create_inherent_data_providers: Arc::new(create_inherent_data_providers), - block_import: Arc::new(futures::lock::Mutex::new(ParachainBlockImport::new( - block_import, - ))), - parachain_client, - keystore, - skip_prediction, - additional_digests_provider: Arc::new(additional_digests_provider), - _phantom: PhantomData, - }) - } - - //TODO Could this be a provided implementation now that we have this async inherent stuff? - /// Create the data. - async fn inherent_data( - &self, - parent: B::Hash, - validation_data: &PersistedValidationData, - relay_parent: PHash, - author_id: NimbusId, - ) -> Option { - let inherent_data_providers = self - .create_inherent_data_providers - .create_inherent_data_providers( - parent, - (relay_parent, validation_data.clone(), author_id), - ) - .await - .map_err(|e| { - tracing::error!( - target: LOG_TARGET, - error = ?e, - "Failed to create inherent data providers.", - ) - }) - .ok()?; - - inherent_data_providers - .create_inherent_data() - .map_err(|e| { - tracing::error!( - target: LOG_TARGET, - error = ?e, - "Failed to create inherent data.", - ) - }) - .ok() - } -} - -/// Grabs any available nimbus key from the keystore. -/// This may be useful in situations where you expect exactly one key -/// and intend to perform an operation with it regardless of whether it is -/// expected to be eligible. Concretely, this is used in the consensus worker -/// to implement the `skip_prediction` feature. -pub(crate) fn first_available_key(keystore: &dyn SyncCryptoStore) -> Option { - // Get all the available keys - let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) - .expect("keystore should return the keys it has"); - - // Print a more helpful message than "not eligible" when there are no keys at all. - if available_keys.is_empty() { - warn!(target: LOG_TARGET, "🔏 No Nimbus keys available. We will not be able to author."); - return None; - } - - Some(available_keys[0].clone()) -} - -/// Grab the first eligible nimbus key from the keystore -/// If multiple keys are eligible this function still only returns one -/// and makes no guarantees which one as that depends on the keystore's iterator behavior. -/// This is the standard way of determining which key to author with. -pub(crate) fn first_eligible_key( - client: Arc, - keystore: &dyn SyncCryptoStore, - parent: &B::Header, - slot_number: u32, -) -> Option -where - C: ProvideRuntimeApi, - C::Api: NimbusApi, -{ - // Get all the available keys - let available_keys = SyncCryptoStore::keys(keystore, NIMBUS_KEY_ID) - .expect("keystore should return the keys it has"); - - // Print a more helpful message than "not eligible" when there are no keys at all. - if available_keys.is_empty() { - warn!(target: LOG_TARGET, "🔏 No Nimbus keys available. We will not be able to author."); - return None; - } - - let at = BlockId::Hash(parent.hash()); - - // Iterate keys until we find an eligible one, or run out of candidates. - // If we are skipping prediction, then we author with the first key we find. - // prediction skipping only really makes sense when there is a single key in the keystore. - let maybe_key = available_keys.into_iter().find(|type_public_pair| { - // Have to convert to a typed NimbusId to pass to the runtime API. Maybe this is a clue - // That I should be passing Vec across the wasm boundary? - NimbusApi::can_author( - &*client.runtime_api(), - &at, - NimbusId::from_slice(&type_public_pair.1).expect("Provided keys should be valid"), - slot_number, - parent, - ) - .expect("NimbusAPI should not return error") - }); - - // If there are no eligible keys, print the log, and exit early. - if maybe_key.is_none() { - info!( - target: LOG_TARGET, - "🔮 Skipping candidate production because we are not eligible for slot {}", slot_number - ); - } - - maybe_key -} - -pub(crate) fn seal_header( - header: &B::Header, - keystore: &dyn SyncCryptoStore, - type_public_pair: &CryptoTypePublicPair, -) -> DigestItem -where - B: BlockT, -{ - let pre_hash = header.hash(); - - let raw_sig = - SyncCryptoStore::sign_with(keystore, NIMBUS_KEY_ID, type_public_pair, pre_hash.as_ref()) - .expect("Keystore should be able to sign") - .expect("We already checked that the key was present"); - - debug!(target: LOG_TARGET, "The signature is \n{:?}", raw_sig); - - let signature = - raw_sig.try_into().expect("signature bytes produced by keystore should be right length"); - - ::nimbus_seal(signature) -} - -#[async_trait::async_trait] -impl ParachainConsensus - for NimbusConsensus -where - B: BlockT, - BI: BlockImport + Send + Sync + 'static, - PF: Environment + Send + Sync + 'static, - PF::Proposer: Proposer< - B, - Transaction = BI::Transaction, - ProofRecording = EnableProofRecording, - Proof = ::Proof, - >, - ParaClient: ProvideRuntimeApi + Send + Sync + 'static, - ParaClient::Api: NimbusApi, - CIDP: CreateInherentDataProviders + 'static, - DP: DigestsProvider::Hash> + 'static + Send + Sync, -{ - async fn produce_candidate( - &mut self, - parent: &B::Header, - relay_parent: PHash, - validation_data: &PersistedValidationData, - ) -> Option> { - // Determine if runtime change - let runtime_upgraded = if *parent.number() > sp_runtime::traits::Zero::zero() { - let at = BlockId::Hash(parent.hash()); - let parent_at = BlockId::::Hash(*parent.parent_hash()); - use sp_api::Core as _; - let previous_runtime_version: sp_api::RuntimeVersion = self - .parachain_client - .runtime_api() - .version(&parent_at) - .expect("Runtime api access to not error."); - let runtime_version: sp_api::RuntimeVersion = self - .parachain_client - .runtime_api() - .version(&at) - .expect("Runtime api access to not error."); - - previous_runtime_version != runtime_version - } else { - false - }; - - let maybe_key = if self.skip_prediction || runtime_upgraded { - first_available_key(&*self.keystore) - } else { - first_eligible_key::( - self.parachain_client.clone(), - &*self.keystore, - parent, - validation_data.relay_parent_number, - ) - }; - - // If there are no eligible keys, print the log, and exit early. - let type_public_pair = match maybe_key { - Some(p) => p, - None => { - return None; - } - }; - - let proposer_future = self.proposer_factory.lock().init(parent); - - let proposer = proposer_future - .await - .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Could not create proposer.")) - .ok()?; - - let nimbus_id = NimbusId::from_slice(&type_public_pair.1) - .map_err( - |e| error!(target: LOG_TARGET, error = ?e, "Invalid Nimbus ID (wrong length)."), - ) - .ok()?; - - let inherent_data = self - .inherent_data(parent.hash(), validation_data, relay_parent, nimbus_id.clone()) - .await?; - - let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; - logs.extend(self.additional_digests_provider.provide_digests(nimbus_id, parent.hash())); - let inherent_digests = sp_runtime::generic::Digest { logs }; - - let Proposal { block, storage_changes, proof } = proposer - .propose( - inherent_data, - inherent_digests, - //TODO: Fix this. - Duration::from_millis(500), - // Set the block limit to 50% of the maximum PoV size. - // - // TODO: If we got benchmarking that includes that encapsulates the proof size, - // we should be able to use the maximum pov size. - Some((validation_data.max_pov_size / 2) as usize), - ) - .await - .map_err(|e| error!(target: LOG_TARGET, error = ?e, "Proposing failed.")) - .ok()?; - - let (header, extrinsics) = block.clone().deconstruct(); - - let sig_digest = seal_header::(&header, &*self.keystore, &type_public_pair); - - let mut block_import_params = BlockImportParams::new(BlockOrigin::Own, header.clone()); - block_import_params.post_digests.push(sig_digest.clone()); - block_import_params.body = Some(extrinsics.clone()); - block_import_params.state_action = sc_consensus::StateAction::ApplyChanges( - sc_consensus::StorageChanges::Changes(storage_changes), - ); - - // Print the same log line as slots (aura and babe) - info!( - "🔖 Sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - *header.number(), - block_import_params.post_hash(), - header.hash(), - ); - - if let Err(err) = self - .block_import - .lock() - .await - .import_block(block_import_params, Default::default()) - .await - { - error!( - target: LOG_TARGET, - at = ?parent.hash(), - error = ?err, - "Error importing built block.", - ); - - return None; - } - - // Compute info about the block after the digest is added - let mut post_header = header.clone(); - post_header.digest_mut().logs.push(sig_digest.clone()); - let post_block = B::new(post_header, extrinsics); - - // Returning the block WITH the seal for distribution around the network. - Some(ParachainCandidate { block: post_block, proof }) - } -} - -/// Paramaters of [`build_relay_chain_consensus`]. -/// -/// I briefly tried the async keystore approach, but decided to go sync so I can copy -/// code from Aura. Maybe after it is working, Jeremy can help me go async. -pub struct BuildNimbusConsensusParams { - pub para_id: ParaId, - pub proposer_factory: PF, - pub create_inherent_data_providers: CIDP, - pub block_import: BI, - pub parachain_client: Arc, - pub keystore: SyncCryptoStorePtr, - pub skip_prediction: bool, - pub additional_digests_provider: DP, -} diff --git a/external/nimbus-consensus/src/manual_seal.rs b/external/nimbus-consensus/src/manual_seal.rs deleted file mode 100644 index e104eac7f..000000000 --- a/external/nimbus-consensus/src/manual_seal.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use cumulus_primitives_parachain_inherent::{ - ParachainInherentData, INHERENT_IDENTIFIER as PARACHAIN_INHERENT_IDENTIFIER, -}; -use nimbus_primitives::{ - CompatibleDigestItem, DigestsProvider, NimbusApi, NimbusId, NIMBUS_ENGINE_ID, -}; -use sc_consensus::BlockImportParams; -use sc_consensus_manual_seal::{ConsensusDataProvider, Error}; -use sp_api::{BlockT, HeaderT, ProvideRuntimeApi, TransactionFor}; -use sp_application_crypto::ByteArray; -use sp_inherents::InherentData; -use sp_keystore::SyncCryptoStorePtr; -use sp_runtime::{Digest, DigestItem}; -use std::{marker::PhantomData, sync::Arc}; - -/// Provides nimbus-compatible pre-runtime digests for use with manual seal consensus -pub struct NimbusManualSealConsensusDataProvider { - /// Shared reference to keystore - pub keystore: SyncCryptoStorePtr, - - /// Shared reference to the client - pub client: Arc, - // Could have a skip_prediction field here if it becomes desireable - /// Additional digests provider - pub additional_digests_provider: DP, - - pub _phantom: PhantomData

, -} - -impl ConsensusDataProvider for NimbusManualSealConsensusDataProvider -where - B: BlockT, - C: ProvideRuntimeApi + Send + Sync, - C::Api: NimbusApi, - DP: DigestsProvider::Hash> + Send + Sync, - P: Send + Sync, -{ - type Transaction = TransactionFor; - type Proof = P; - - fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result { - // Retrieve the relay chain block number to use as the slot number from the parachain inherent - let slot_number = inherents - .get_data::(&PARACHAIN_INHERENT_IDENTIFIER) - .expect("Parachain inherent should decode correctly") - .expect("Parachain inherent should be present because we are mocking it") - .validation_data - .relay_parent_number; - - // Fetch first eligible key from keystore - let maybe_key = crate::first_eligible_key::( - self.client.clone(), - &*self.keystore, - parent, - // For now we author all blocks in slot zero, which is consistent with how we are - // mocking the relay chain height which the runtime uses for slot beacon. - // This should improve. See https://github.com/PureStake/nimbus/issues/3 - slot_number, - ); - - // If we aren't eligible, return an appropriate error - match maybe_key { - Some(key) => { - let nimbus_id = NimbusId::from_slice(&key.1).map_err(|_| { - Error::StringError(String::from("invalid nimbus id (wrong length)")) - })?; - let mut logs = vec![CompatibleDigestItem::nimbus_pre_digest(nimbus_id.clone())]; - logs.extend( - self.additional_digests_provider.provide_digests(nimbus_id, parent.hash()), - ); - Ok(Digest { logs }) - } - None => { - Err(Error::StringError(String::from("no nimbus keys available to manual seal"))) - } - } - } - - // This is where we actually sign with the nimbus key and attach the seal - fn append_block_import( - &self, - _parent: &B::Header, - params: &mut BlockImportParams, - _inherents: &InherentData, - _proof: Self::Proof, - ) -> Result<(), Error> { - // We have to reconstruct the type-public pair which is only communicated through the pre-runtime digest - let claimed_author = params - .header - .digest() - .logs - .iter() - .find_map(|digest| { - match *digest { - // We do not support the older author inherent in manual seal - DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - _ => None, - } - }) - .expect("Expected one pre-runtime digest that contains author id bytes"); - - let nimbus_public = NimbusId::from_slice(&claimed_author) - .map_err(|_| Error::StringError(String::from("invalid nimbus id (wrong length)")))?; - - let sig_digest = - crate::seal_header::(¶ms.header, &*self.keystore, &nimbus_public.into()); - - params.post_digests.push(sig_digest); - - Ok(()) - } -} diff --git a/external/nimbus-primitives/Cargo.toml b/external/nimbus-primitives/Cargo.toml deleted file mode 100644 index 76f4d69f1..000000000 --- a/external/nimbus-primitives/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -authors = ["PureStake"] -description = "Primitive types and traits used in the Nimbus consensus framework" -edition = "2021" -name = "nimbus-primitives" -version = "0.9.0" - -[dependencies] -async-trait = { version = "0.1", optional = true } -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } - -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } - -frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.32" } - -[features] -default = ["std"] -std = [ - "async-trait", - "frame-support/std", - "frame-system/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-api/std", - "sp-application-crypto/std", - "sp-inherents/std", - "sp-runtime/std", - "sp-std/std", -] - -runtime-benchmarks = ["frame-benchmarking", "sp-runtime/runtime-benchmarks"] - -try-runtime = ["frame-support/try-runtime"] diff --git a/external/nimbus-primitives/src/digests.rs b/external/nimbus-primitives/src/digests.rs deleted file mode 100644 index 7364f05a7..000000000 --- a/external/nimbus-primitives/src/digests.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! A convenient interface over the digests used in nimbus. -//! -//! Currently Nimbus has two digests; -//! 1. A consensus digest that contains the block author identity -//! This information is copied from the author inehrent. -//! This may be replaced with a pre-runtime digest in the future. -//! 2. A seal digest that contains a signature over the rest of the -//! block including the first digest. - -use crate::{NimbusId, NimbusSignature, NIMBUS_ENGINE_ID}; -use parity_scale_codec::Encode; -use sp_runtime::generic::DigestItem; - -/// A digest item which is usable with aura consensus. -pub trait CompatibleDigestItem: Sized { - /// Construct a pre-runtime digest from the given AuthorId - fn nimbus_pre_digest(author: NimbusId) -> Self; - - /// If this item is a nimbus pre-runtime digest, return the author - fn as_nimbus_pre_digest(&self) -> Option; - - /// Construct a seal digest item from the given signature - fn nimbus_seal(signature: NimbusSignature) -> Self; - - /// If this item is a nimbus seal, return the signature. - fn as_nimbus_seal(&self) -> Option; - - /// This will be deprecated in the future - /// Construct a consensus digest from the given AuthorId - fn nimbus_consensus_digest(author: NimbusId) -> Self; - - /// This will be deprecated in the future - /// If this item is a nimbus consensus digest, return the author - fn as_nimbus_consensus_digest(&self) -> Option; -} - -impl CompatibleDigestItem for DigestItem { - fn nimbus_pre_digest(author: NimbusId) -> Self { - DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode()) - } - - fn as_nimbus_pre_digest(&self) -> Option { - self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) - } - - fn nimbus_seal(signature: NimbusSignature) -> Self { - DigestItem::Seal(NIMBUS_ENGINE_ID, signature.encode()) - } - - fn as_nimbus_seal(&self) -> Option { - self.seal_try_to(&NIMBUS_ENGINE_ID) - } - - // Remove this once deprecated - fn nimbus_consensus_digest(author: NimbusId) -> Self { - DigestItem::Consensus(NIMBUS_ENGINE_ID, author.encode()) - } - - // Remove this once deprecated. I don't think it is used anyway. - // Notice that it calls the pre_runtime helper function. - fn as_nimbus_consensus_digest(&self) -> Option { - self.pre_runtime_try_to(&NIMBUS_ENGINE_ID) - } -} diff --git a/external/nimbus-primitives/src/inherents.rs b/external/nimbus-primitives/src/inherents.rs deleted file mode 100644 index e5e5023f1..000000000 --- a/external/nimbus-primitives/src/inherents.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use sp_inherents::{InherentData, InherentIdentifier}; - -/// The InherentIdentifier for nimbus's author inherent -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"author__"; - -/// A bare minimum inherent data provider that provides no real data. -/// The inherent is simply used as a way to kick off some computation -/// until https://github.com/paritytech/substrate/pull/10128 lands. -pub struct InherentDataProvider; - -#[cfg(feature = "std")] -#[async_trait::async_trait] -impl sp_inherents::InherentDataProvider for InherentDataProvider { - fn provide_inherent_data( - &self, - inherent_data: &mut InherentData, - ) -> Result<(), sp_inherents::Error> { - inherent_data.put_data(INHERENT_IDENTIFIER, &()) - } - - async fn try_handle_error( - &self, - identifier: &InherentIdentifier, - _error: &[u8], - ) -> Option> { - // Dont' process modules from other inherents - if *identifier != INHERENT_IDENTIFIER { - return None; - } - - // All errors with the author inehrent are fatal - Some(Err(sp_inherents::Error::Application(Box::from(String::from( - "Error processing dummy nimbus inherent", - ))))) - } -} diff --git a/external/nimbus-primitives/src/lib.rs b/external/nimbus-primitives/src/lib.rs deleted file mode 100644 index 365e3b606..000000000 --- a/external/nimbus-primitives/src/lib.rs +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! Nimbus Consensus Primitives -//! -//! Primitive types and traits for working with the Nimbus consensus framework. -//! This code can be built to no_std for use in the runtime - -#![cfg_attr(not(feature = "std"), no_std)] - -use sp_application_crypto::KeyTypeId; -use sp_runtime::{generic::DigestItem, traits::BlockNumberProvider, ConsensusEngineId}; -#[cfg(feature = "runtime-benchmarks")] -use sp_std::vec; -#[cfg(feature = "runtime-benchmarks")] -use sp_std::vec::Vec; - -pub mod digests; -mod inherents; - -pub use digests::CompatibleDigestItem; - -pub use inherents::{InherentDataProvider, INHERENT_IDENTIFIER}; - -pub trait DigestsProvider { - type Digests: IntoIterator; - fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests; -} - -impl DigestsProvider for () { - type Digests = [DigestItem; 0]; - fn provide_digests(&self, _id: Id, _parent: BlockHash) -> Self::Digests { - [] - } -} - -impl DigestsProvider for F -where - F: Fn(Id, BlockHash) -> D, - D: IntoIterator, -{ - type Digests = D; - - fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests { - (*self)(id, parent) - } -} - -/// The given account ID is the author of the current block. -pub trait EventHandler { - //TODO should we be tking ownership here? - fn note_author(author: Author); -} - -impl EventHandler for () { - fn note_author(_author: T) {} -} - -/// A mechanism for determining the current slot. -/// For now we use u32 as the slot type everywhere. Let's see how long we can get away with that. -pub trait SlotBeacon { - fn slot() -> u32; - #[cfg(feature = "runtime-benchmarks")] - fn set_slot(_slot: u32) {} -} - -/// Anything that can provide a block height can be used as a slot beacon. This could be -/// used in at least two realistic ways. -/// 1. Use your own chain's height as the slot number -/// 2. If you're a parachain, use the relay chain's height as the slot number. -impl> SlotBeacon for T { - fn slot() -> u32 { - Self::current_block_number() - } - #[cfg(feature = "runtime-benchmarks")] - fn set_slot(slot: u32) { - Self::set_block_number(slot); - } -} - -/// PLANNED: A SlotBeacon that starts a new slot based on the timestamp. Behaviorally, this is -/// similar to what aura, babe and company do. Implementation-wise it is different because it -/// depends on the timestamp pallet for its notion of time. -pub struct IntervalBeacon; - -impl SlotBeacon for IntervalBeacon { - fn slot() -> u32 { - todo!() - } -} - -/// Trait to determine whether this author is eligible to author in this slot. -/// This is the primary trait your nimbus filter needs to implement. -/// -/// This is the proposition-logic variant. -/// That is to say the caller specifies an author an author and the implementation -/// replies whether that author is eligible. This is useful in many cases and is -/// particularly useful when the active set is unbounded. -/// There may be another variant where the caller only supplies a slot and the -/// implementation replies with a complete set of eligible authors. -pub trait CanAuthor { - #[cfg(feature = "try-runtime")] - // With `try-runtime` the local author should always be able to author a block. - fn can_author(_author: &AuthorId, _slot: &u32) -> bool { - true - } - #[cfg(not(feature = "try-runtime"))] - fn can_author(author: &AuthorId, slot: &u32) -> bool; - #[cfg(feature = "runtime-benchmarks")] - fn get_authors(_slot: &u32) -> Vec { - vec![] - } - #[cfg(feature = "runtime-benchmarks")] - fn set_eligible_author(_slot: &u32) {} -} -/// Default implementation where anyone can author. -/// -/// This is identical to Cumulus's RelayChainConsensus -impl CanAuthor for () { - fn can_author(_: &T, _: &u32) -> bool { - true - } -} - -/// A Trait to lookup runtime AccountIds from AuthorIds (probably NimbusIds) -/// The trait is generic over the AccountId, becuase different runtimes use -/// different notions of AccoutId. It is also generic over the AuthorId to -/// support the usecase where the author inherent is used for beneficiary info -/// and contains an AccountId directly. -pub trait AccountLookup { - fn lookup_account(author: &NimbusId) -> Option; -} - -// A dummy impl used in simple tests -impl AccountLookup for () { - fn lookup_account(_: &NimbusId) -> Option { - None - } -} - -/// The ConsensusEngineId for nimbus consensus -/// this same identifier will be used regardless of the filters installed -pub const NIMBUS_ENGINE_ID: ConsensusEngineId = *b"nmbs"; - -/// The KeyTypeId used in the Nimbus consensus framework regardles of wat filters are in place. -/// If this gets well adopted, we could move this definition to sp_core to avoid conflicts. -pub const NIMBUS_KEY_ID: KeyTypeId = KeyTypeId(*b"nmbs"); - -// The strongly-typed crypto wrappers to be used by Nimbus in the keystore -mod nimbus_crypto { - use sp_application_crypto::{app_crypto, sr25519}; - app_crypto!(sr25519, crate::NIMBUS_KEY_ID); -} - -/// A nimbus author identifier (A public key). -pub type NimbusId = nimbus_crypto::Public; - -/// A nimbus signature. -pub type NimbusSignature = nimbus_crypto::Signature; - -sp_application_crypto::with_pair! { - /// A nimbus keypair - pub type NimbusPair = nimbus_crypto::Pair; -} - -sp_api::decl_runtime_apis! { - /// The runtime api used to predict whether a Nimbus author will be eligible in the given slot - pub trait NimbusApi { - fn can_author(author: NimbusId, relay_parent: u32, parent_header: &Block::Header) -> bool; - } -} diff --git a/external/pallets/author-inherent/Cargo.toml b/external/pallets/author-inherent/Cargo.toml deleted file mode 100644 index c35a6a2f8..000000000 --- a/external/pallets/author-inherent/Cargo.toml +++ /dev/null @@ -1,53 +0,0 @@ -[package] -authors = ["PureStake"] -description = "This pallet is the core of the in-runtime portion of Nimbus." -edition = "2021" -license = "GPL-3.0-only" -name = "pallet-author-inherent" -version = "0.9.0" - -[dependencies] -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -log = { version = "0.4.17", default-features = false } -nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } - -# Benchmarks -frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.32" } - -[dev-dependencies] -frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0", branch = "polkadot-v0.9.32" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } - -[features] -default = ["std"] -std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-api/std", - "sp-application-crypto/std", - "sp-authorship/std", - "sp-inherents/std", - "sp-runtime/std", - "sp-std/std", -] - -runtime-benchmarks = [ - "frame-benchmarking", - "nimbus-primitives/runtime-benchmarks", -] -try-runtime = ["frame-support/try-runtime", "frame-system/try-runtime"] diff --git a/external/pallets/author-inherent/src/benchmarks.rs b/external/pallets/author-inherent/src/benchmarks.rs deleted file mode 100644 index 7a988f901..000000000 --- a/external/pallets/author-inherent/src/benchmarks.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -#![cfg(feature = "runtime-benchmarks")] - -use crate::{Call, Config, Pallet}; -use frame_benchmarking::benchmarks; -use frame_system::RawOrigin; -use nimbus_primitives::{CanAuthor, SlotBeacon}; -benchmarks! { - kick_off_authorship_validation { - // The slot inserted needs to be higher than that already in storage - T::SlotBeacon::set_slot(100); - Pallet::::set_eligible_author(&T::SlotBeacon::slot()); - }: _(RawOrigin::None) -} diff --git a/external/pallets/author-inherent/src/exec.rs b/external/pallets/author-inherent/src/exec.rs deleted file mode 100644 index b9fb50d7b..000000000 --- a/external/pallets/author-inherent/src/exec.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! Block executive to be used by relay chain validators when validating parachain blocks built -//! with the nimubs consensus family. - -use frame_support::traits::ExecuteBlock; -use sp_api::{BlockT, HeaderT}; -// For some reason I can't get these logs to actually print -use log::debug; -use nimbus_primitives::{digests::CompatibleDigestItem, NimbusId, NIMBUS_ENGINE_ID}; -use sp_application_crypto::ByteArray; -use sp_runtime::{generic::DigestItem, RuntimeAppPublic}; - -/// Block executive to be used by relay chain validators when validating parachain blocks built -/// with the nimubs consensus family. -/// -/// This will strip the seal digest, and confirm that it contains a valid signature -/// By the block author reported in the author inherent. -/// -/// Essentially this contains the logic of the verifier plus the inner executive. -/// TODO Degisn improvement: -/// Can we share code with the verifier? -/// Can this struct take a verifier as an associated type? -/// Or maybe this will just get simpler in general when https://github.com/paritytech/polkadot/issues/2888 lands -pub struct BlockExecutor(sp_std::marker::PhantomData<(T, I)>); - -impl ExecuteBlock for BlockExecutor -where - Block: BlockT, - I: ExecuteBlock, -{ - fn execute_block(block: Block) { - let (mut header, extrinsics) = block.deconstruct(); - - debug!(target: "executive", "In hacked Executive. Initial digests are {:?}", header.digest()); - - // Set the seal aside for checking. - let seal = header.digest_mut().pop().expect("Seal digest is present and is last item"); - - debug!(target: "executive", "In hacked Executive. digests after stripping {:?}", header.digest()); - debug!(target: "executive", "The seal we got {:?}", seal); - - let signature = seal.as_nimbus_seal().unwrap_or_else(|| panic!("HeaderUnsealed")); - - debug!(target: "executive", "🪲 Header hash after popping digest {:?}", header.hash()); - - debug!(target: "executive", "🪲 Signature according to executive is {:?}", signature); - - // Grab the author information from the preruntime digest - //TODO use the trait - let claimed_author = header - .digest() - .logs - .iter() - .find_map(|digest| match *digest { - DigestItem::PreRuntime(id, ref author_id) if id == NIMBUS_ENGINE_ID => { - Some(author_id.clone()) - } - _ => None, - }) - .expect("Expected pre-runtime digest that contains author id bytes"); - - debug!(target: "executive", "🪲 Claimed Author according to executive is {:?}", claimed_author); - - // Verify the signature - let valid_signature = NimbusId::from_slice(&claimed_author) - .expect("Expected claimed author to be a valid NimbusId.") - .verify(&header.hash(), &signature); - - debug!(target: "executive", "🪲 Valid signature? {:?}", valid_signature); - - if !valid_signature { - panic!("Block signature invalid"); - } - - // Now that we've verified the signature, hand execution off to the inner executor - // which is probably the normal frame executive. - I::execute_block(Block::new(header, extrinsics)); - } -} diff --git a/external/pallets/author-inherent/src/lib.rs b/external/pallets/author-inherent/src/lib.rs deleted file mode 100644 index 745387cb0..000000000 --- a/external/pallets/author-inherent/src/lib.rs +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! Pallet that allows block authors to include their identity in a block via an inherent. -//! Currently the author does not _prove_ their identity, just states it. So it should not be used, -//! for things like equivocation slashing that require authenticated authorship information. - -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::traits::{FindAuthor, Get}; -use nimbus_primitives::{ - AccountLookup, CanAuthor, NimbusId, SlotBeacon, INHERENT_IDENTIFIER, NIMBUS_ENGINE_ID, -}; -use parity_scale_codec::{Decode, Encode}; -use sp_inherents::{InherentIdentifier, IsFatalError}; -use sp_runtime::{ConsensusEngineId, RuntimeString}; - -mod exec; -pub use exec::BlockExecutor; - -pub use pallet::*; - -#[cfg(any(test, feature = "runtime-benchmarks"))] -mod benchmarks; - -pub mod weights; - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use crate::weights::WeightInfo; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - /// The Author Inherent pallet. The core of the nimbus consensus framework's runtime presence. - #[pallet::pallet] - pub struct Pallet(PhantomData); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// A type to convert between AuthorId and AccountId. This is useful when you want to associate - /// Block authoring behavior with an AccoutId for rewards or slashing. If you do not need to - /// hold an AccountID responsible for authoring use `()` which acts as an identity mapping. - type AccountLookup: AccountLookup; - - /// The final word on whether the reported author can author at this height. - /// This will be used when executing the inherent. This check is often stricter than the - /// Preliminary check, because it can use more data. - /// If the pallet that implements this trait depends on an inherent, that inherent **must** - /// be included before this one. - type CanAuthor: CanAuthor; - - /// Some way of determining the current slot for purposes of verifying the author's eligibility - type SlotBeacon: SlotBeacon; - - type WeightInfo: WeightInfo; - } - - impl sp_runtime::BoundToRuntimeAppPublic for Pallet { - type Public = NimbusId; - } - - #[pallet::error] - pub enum Error { - /// Author already set in block. - AuthorAlreadySet, - /// No AccountId was found to be associated with this author - NoAccountId, - /// The author in the inherent is not an eligible author. - CannotBeAuthor, - } - - /// Author of current block. - #[pallet::storage] - pub type Author = StorageValue<_, T::AccountId, OptionQuery>; - - /// The highest slot that has been seen in the history of this chain. - /// This is a strictly-increasing value. - #[pallet::storage] - pub type HighestSlotSeen = StorageValue<_, u32, ValueQuery>; - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(_: T::BlockNumber) -> Weight { - // Now extract the author from the digest - let digest = >::digest(); - let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - if let Some(author) = Self::find_author(pre_runtime_digests) { - // Store the author so we can confirm eligibility after the inherents have executed - >::put(&author); - } - - T::DbWeight::get().writes(1) - } - } - - #[pallet::call] - impl Pallet { - /// This inherent is a workaround to run code after the "real" inherents have executed, - /// but before transactions are executed. - // This should go into on_post_inherents when it is ready https://github.com/paritytech/substrate/pull/10128 - // TODO better weight. For now we just set a somewhat conservative fudge factor - #[pallet::weight((T::WeightInfo::kick_off_authorship_validation(), DispatchClass::Mandatory))] - pub fn kick_off_authorship_validation(origin: OriginFor) -> DispatchResultWithPostInfo { - ensure_none(origin)?; - - // First check that the slot number is valid (greater than the previous highest) - let slot = T::SlotBeacon::slot(); - assert!( - slot > HighestSlotSeen::::get(), - "Block invalid; Supplied slot number is not high enough" - ); - - // Now check that the author is valid in this slot - assert!( - T::CanAuthor::can_author(&Self::get(), &slot), - "Block invalid, supplied author is not eligible." - ); - - // Once that is validated, update the stored slot number - HighestSlotSeen::::put(slot); - - Ok(Pays::No.into()) - } - } - - #[pallet::inherent] - impl ProvideInherent for Pallet { - type Call = Call; - type Error = InherentError; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - fn is_inherent_required(_: &InherentData) -> Result, Self::Error> { - // Return Ok(Some(_)) unconditionally because this inherent is required in every block - // If it is not found, throw an AuthorInherentRequired error. - Ok(Some(InherentError::Other(sp_runtime::RuntimeString::Borrowed( - "Inherent required to manually initiate author validation", - )))) - } - - // Regardless of whether the client is still supplying the author id, - // we will create the new empty-payload inherent extrinsic. - fn create_inherent(_data: &InherentData) -> Option { - Some(Call::kick_off_authorship_validation {}) - } - - fn is_inherent(call: &Self::Call) -> bool { - matches!(call, Call::kick_off_authorship_validation { .. }) - } - } - - impl FindAuthor for Pallet { - fn find_author<'a, I>(digests: I) -> Option - where - I: 'a + IntoIterator, - { - for (id, mut data) in digests.into_iter() { - if id == NIMBUS_ENGINE_ID { - let author_id = NimbusId::decode(&mut data) - .expect("NimbusId encoded in preruntime digest must be valid"); - - let author_account = T::AccountLookup::lookup_account(&author_id) - .expect("No Account Mapped to this NimbusId"); - - return Some(author_account); - } - } - - None - } - } - - impl Get for Pallet { - fn get() -> T::AccountId { - Author::::get().expect("Block author not inserted into Author Inherent Pallet") - } - } - - /// To learn whether a given NimbusId can author, as opposed to an account id, you - /// can ask this pallet directly. It will do the mapping for you. - impl CanAuthor for Pallet { - fn can_author(author: &NimbusId, slot: &u32) -> bool { - let account = match T::AccountLookup::lookup_account(author) { - Some(account) => account, - // Authors whose account lookups fail will not be eligible - None => { - return false; - } - }; - - T::CanAuthor::can_author(&account, slot) - } - #[cfg(feature = "runtime-benchmarks")] - fn set_eligible_author(slot: &u32) { - let eligible_authors = T::CanAuthor::get_authors(slot); - if let Some(author) = eligible_authors.first() { - Author::::put(author) - } - } - } -} - -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(Debug, Decode))] -pub enum InherentError { - Other(RuntimeString), -} - -impl IsFatalError for InherentError { - fn is_fatal_error(&self) -> bool { - match *self { - InherentError::Other(_) => true, - } - } -} - -impl InherentError { - /// Try to create an instance ouf of the given identifier and data. - #[cfg(feature = "std")] - pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { - if id == &INHERENT_IDENTIFIER { - ::decode(&mut &data[..]).ok() - } else { - None - } - } -} diff --git a/external/pallets/author-inherent/src/mock.rs b/external/pallets/author-inherent/src/mock.rs deleted file mode 100644 index 933bcc47d..000000000 --- a/external/pallets/author-inherent/src/mock.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use crate::{self as pallet_testing, AccountLookup, NimbusId}; -use frame_support::{parameter_types, traits::ConstU32, weights::RuntimeDbWeight}; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, -}; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - AuthorInherent: pallet_testing::{Pallet, Call, Storage}, - } -); - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub Authors: Vec = vec![1, 2, 3, 4, 5]; - pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 1, - write: 10, - }; -} - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = TestDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} - -pub struct DummyBeacon {} -impl nimbus_primitives::SlotBeacon for DummyBeacon { - fn slot() -> u32 { - 0 - } -} - -pub const ALICE: u64 = 1; -pub const ALICE_NIMBUS: [u8; 32] = [1; 32]; -pub struct MockAccountLookup; -impl AccountLookup for MockAccountLookup { - fn lookup_account(nimbus_id: &NimbusId) -> Option { - let nimbus_id_bytes: &[u8] = nimbus_id.as_ref(); - - if *nimbus_id_bytes == ALICE_NIMBUS { Some(ALICE) } else { None } - } -} - -impl pallet_testing::Config for Test { - type AccountLookup = MockAccountLookup; - type CanAuthor = (); - type SlotBeacon = DummyBeacon; - type WeightInfo = (); -} - -/// Build genesis storage according to the mock runtime. -pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::default().build_storage::().unwrap().into() -} diff --git a/external/pallets/author-inherent/src/tests.rs b/external/pallets/author-inherent/src/tests.rs deleted file mode 100644 index 26b6e87e4..000000000 --- a/external/pallets/author-inherent/src/tests.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use crate::{mock::*, pallet::Author}; -use frame_support::traits::{OnFinalize, OnInitialize}; -use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID}; -use parity_scale_codec::Encode; -use sp_core::{ByteArray, H256}; -use sp_runtime::{Digest, DigestItem}; - -#[test] -fn kick_off_authorship_validation_is_mandatory() { - use frame_support::dispatch::{DispatchClass, GetDispatchInfo}; - - let info = crate::Call::::kick_off_authorship_validation {}.get_dispatch_info(); - assert_eq!(info.class, DispatchClass::Mandatory); -} - -#[test] -fn test_author_is_available_after_on_initialize() { - new_test_ext().execute_with(|| { - let block_number = 1; - System::initialize( - &block_number, - &H256::default(), - &Digest { - logs: vec![DigestItem::PreRuntime( - NIMBUS_ENGINE_ID, - NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), - )], - }, - ); - - AuthorInherent::on_initialize(block_number); - assert_eq!(Some(ALICE), >::get()); - }); -} - -#[test] -fn test_author_is_still_available_after_on_finalize() { - new_test_ext().execute_with(|| { - let block_number = 1; - System::initialize( - &block_number, - &H256::default(), - &Digest { - logs: vec![DigestItem::PreRuntime( - NIMBUS_ENGINE_ID, - NimbusId::from_slice(&ALICE_NIMBUS).unwrap().encode(), - )], - }, - ); - - AuthorInherent::on_initialize(block_number); - AuthorInherent::on_finalize(block_number); - assert_eq!(Some(ALICE), >::get()); - }); -} diff --git a/external/pallets/author-inherent/src/weights.rs b/external/pallets/author-inherent/src/weights.rs deleted file mode 100644 index 045ef4675..000000000 --- a/external/pallets/author-inherent/src/weights.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Autogenerated weights for pallet_author_inherent -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-04-22, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/release/moonbeam -// benchmark -// --chain -// dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet -// pallet_author_inherent -// --extrinsic -// kick_off_authorship_validation -// --steps -// 50 -// --repeat -// 20 -// --template=./benchmarking/frame-weight-template.hbs -// --record-proof -// --json-file -// raw.json -// --output -// weights.rs - -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for pallet_author_inherent. -pub trait WeightInfo { - #[rustfmt::skip] - fn kick_off_authorship_validation() -> Weight; -} - -/// Weights for pallet_author_inherent using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: ParachainSystem ValidationData (r:1 w:0) - // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) - // Storage: AuthorInherent Author (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:1 w:0) - // Storage: AuthorFilter EligibleCount (r:1 w:0) - // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) - #[rustfmt::skip] - fn kick_off_authorship_validation() -> Weight { - Weight::from_ref_time(20_862_000_u64) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: ParachainSystem ValidationData (r:1 w:0) - // Storage: AuthorInherent HighestSlotSeen (r:1 w:1) - // Storage: AuthorInherent Author (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:1 w:0) - // Storage: AuthorFilter EligibleCount (r:1 w:0) - // Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) - #[rustfmt::skip] - fn kick_off_authorship_validation() -> Weight { - Weight::from_ref_time(20_862_000_u64) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} diff --git a/external/pallets/author-mapping/Cargo.toml b/external/pallets/author-mapping/Cargo.toml deleted file mode 100644 index 83442efa3..000000000 --- a/external/pallets/author-mapping/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -authors = ["PureStake"] -description = "Maps AuthorIds to AccountIds Useful for associating consensus authors with in-runtime accounts" -edition = "2021" -name = "pallet-author-mapping" -version = "2.0.5" - -[dependencies] -log = { version = "0.4.17", default-features = false } -serde = { version = "1.0.124", optional = true } - -# Substrate -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } - -# Nimbus -nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } - -session-keys-primitives = { path = "../../session-keys", default-features = false } - -[dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } - -[features] -default = ["std"] -runtime-benchmarks = [ - "frame-benchmarking", - "session-keys-primitives/runtime-benchmarks", -] -std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "serde", - "session-keys-primitives/std", - "sp-runtime/std", - "sp-std/std", -] -try-runtime = ["frame-support/try-runtime"] diff --git a/external/pallets/author-mapping/migrations.md b/external/pallets/author-mapping/migrations.md deleted file mode 100644 index 7f0c0b19c..000000000 --- a/external/pallets/author-mapping/migrations.md +++ /dev/null @@ -1,10 +0,0 @@ -# Migration History - -## Add session keys to author mapping pallet - -- [Migration PR `#1407`](https://github.com/PureStake/moonbeam/pull/1407) - -## Manage author mapping blake2 migration - -- [Migration PR `#796`](https://github.com/PureStake/moonbeam/pull/796) -- [Migration Removal PR `#1434`](https://github.com/PureStake/moonbeam/pull/1434) diff --git a/external/pallets/author-mapping/src/benchmarks.rs b/external/pallets/author-mapping/src/benchmarks.rs deleted file mode 100644 index b38957a65..000000000 --- a/external/pallets/author-mapping/src/benchmarks.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -#![cfg(feature = "runtime-benchmarks")] - -//! Benchmarking -use crate::{keys_wrapper, BalanceOf, Call, Config, Pallet}; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; -use frame_support::{ - assert_ok, - traits::{Currency, Get}, -}; -use frame_system::RawOrigin; -use nimbus_primitives::NimbusId; -use parity_scale_codec::Decode; - -/// Create a funded user. -fn create_funded_user() -> T::AccountId { - let user = account("account id", 0u32, 0u32); - T::DepositCurrency::make_free_balance_be( - &user, - <::DepositAmount as Get>>::get(), - ); - T::DepositCurrency::issue(<::DepositAmount as Get>>::get()); - user -} - -/// Create a valid nimbus id from a simple u8 seed -pub fn nimbus_id(seed: u8) -> NimbusId { - let id = [seed; 32]; - NimbusId::decode(&mut &id[..]).expect("valid input") -} - -benchmarks! { - add_association { - let caller = create_funded_user::(); - let id = nimbus_id(1u8); - }: _(RawOrigin::Signed(caller.clone()), id.clone()) - verify { - assert_eq!(Pallet::::account_id_of(&id), Some(caller)); - } - - update_association { - let caller = create_funded_user::(); - let first_id = nimbus_id(1u8); - let second_id = nimbus_id(2u8); - assert_ok!(Pallet::::add_association( - RawOrigin::Signed(caller.clone()).into(), - first_id.clone()) - ); - }: _(RawOrigin::Signed(caller.clone()), first_id.clone(), second_id.clone()) - verify { - assert_eq!(Pallet::::account_id_of(&first_id), None); - assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); - } - - clear_association { - let caller = create_funded_user::(); - let first_id = nimbus_id(1u8); - assert_ok!(Pallet::::add_association( - RawOrigin::Signed(caller.clone()).into(), - first_id.clone()) - ); - }: _(RawOrigin::Signed(caller.clone()), first_id.clone()) - verify { - assert_eq!(Pallet::::account_id_of(&first_id), None); - } - - remove_keys { - let caller = create_funded_user::(); - let id = nimbus_id(1u8); - let keys: T::Keys = nimbus_id(3u8).into(); - assert_ok!(Pallet::::set_keys( - RawOrigin::Signed(caller.clone()).into(), - keys_wrapper::(id.clone(), keys), - ) - ); - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert_eq!(Pallet::::account_id_of(&id), None); - assert_eq!(Pallet::::nimbus_id_of(&caller), None); - } - - set_keys { - let caller = create_funded_user::(); - let first_id = nimbus_id(1u8); - let first_keys: T::Keys = nimbus_id(3u8).into(); - let second_id = nimbus_id(2u8); - let second_keys: T::Keys = nimbus_id(3u8).into(); - // we benchmark set_keys after already calling set_keys because - // key rotation is more common than initially setting them - assert_ok!(Pallet::::set_keys( - RawOrigin::Signed(caller.clone()).into(), - keys_wrapper::(first_id.clone(), - first_keys), - ) - ); - }: _(RawOrigin::Signed(caller.clone()), keys_wrapper::(second_id.clone(), second_keys.clone()) - ) verify { - assert_eq!(Pallet::::account_id_of(&first_id), None); - assert_eq!(Pallet::::keys_of(&first_id), None); - assert_eq!(Pallet::::account_id_of(&second_id), Some(caller)); - assert_eq!(Pallet::::keys_of(&second_id), Some(second_keys)); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::Runtime; - use frame_support::assert_ok; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t) - } - - #[test] - fn bench_add_association() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_add_association()); - }); - } - - #[test] - fn bench_update_association() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_update_association()); - }); - } - - #[test] - fn bench_clear_association() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_clear_association()); - }); - } -} - -impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Runtime); diff --git a/external/pallets/author-mapping/src/lib.rs b/external/pallets/author-mapping/src/lib.rs deleted file mode 100644 index aa002ce3e..000000000 --- a/external/pallets/author-mapping/src/lib.rs +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Maps Author Ids as used in nimbus consensus layer to account ids as used in the runtime. -//! This should likely be moved to nimbus eventually. -//! -//! This pallet maps NimbusId => AccountId which is most useful when using propositional style -//! queries. This mapping will likely need to go the other way if using exhaustive authority sets. -//! That could either be a separate pallet, or this pallet could implement a two-way mapping. But -//! for now it it one-way - -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::pallet; - -pub use pallet::*; - -pub mod weights; -use weights::WeightInfo; -#[cfg(any(test, feature = "runtime-benchmarks"))] -mod benchmarks; -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -pub mod migrations; - -#[pallet] -pub mod pallet { - use crate::WeightInfo; - use frame_support::{ - pallet_prelude::*, - traits::{Currency, ReservableCurrency}, - }; - use frame_system::pallet_prelude::*; - use nimbus_primitives::{AccountLookup, NimbusId}; - use session_keys_primitives::KeysLookup; - use sp_std::{mem::size_of, vec::Vec}; - - pub type BalanceOf = <::DepositCurrency as Currency< - ::AccountId, - >>::Balance; - - #[derive(Clone, Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] - #[scale_info(skip_type_params(T))] - pub struct RegistrationInfo { - pub(crate) account: T::AccountId, - pub(crate) deposit: BalanceOf, - pub(crate) keys: T::Keys, - } - - /// Wrapper to form the input to `set_keys` from NimbusId + keys - pub fn keys_wrapper(nimbus_id: NimbusId, keys: T::Keys) -> Vec { - let mut r = nimbus_id.encode(); - r.extend(&keys.encode()); - r - } - - /// Size of NimbusId + T::Keys to check size of `set_keys` input before trying to decode - pub fn keys_size() -> usize { - size_of::() as usize + size_of::() as usize - } - - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - /// Configuration trait of this pallet - #[pallet::config] - pub trait Config: frame_system::Config { - /// Overarching event type - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// Currency in which the security deposit will be taken. - type DepositCurrency: Currency + ReservableCurrency; - /// The amount that should be taken as a security deposit when registering a NimbusId. - type DepositAmount: Get<>::Balance>; - /// Additional keys - /// Convertible From to get default keys for each mapping (for the migration) - type Keys: Parameter + Member + MaybeSerializeDeserialize + From; - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - } - - /// An error that can occur while executing the mapping pallet's logic. - #[pallet::error] - pub enum Error { - /// The association can't be cleared because it is not found. - AssociationNotFound, - /// The association can't be cleared because it belongs to another account. - NotYourAssociation, - /// This account cannot set an author because it cannon afford the security deposit - CannotAffordSecurityDeposit, - /// The NimbusId in question is already associated and cannot be overwritten - AlreadyAssociated, - /// No existing NimbusId can be found for the account - OldAuthorIdNotFound, - /// Keys have wrong size - WrongKeySize, - /// Failed to decode NimbusId for `set_keys` - DecodeNimbusFailed, - /// Failed to decode T::Keys for `set_keys` - DecodeKeysFailed, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// A NimbusId has been registered and mapped to an AccountId. - KeysRegistered { nimbus_id: NimbusId, account_id: T::AccountId, keys: T::Keys }, - /// An NimbusId has been de-registered, and its AccountId mapping removed. - KeysRemoved { nimbus_id: NimbusId, account_id: T::AccountId, keys: T::Keys }, - /// An NimbusId has been registered, replacing a previous registration and its mapping. - KeysRotated { new_nimbus_id: NimbusId, account_id: T::AccountId, new_keys: T::Keys }, - } - - #[pallet::call] - impl Pallet { - /// Register your NimbusId onchain so blocks you author are associated with your account. - /// - /// Users who have been (or will soon be) elected active collators in staking, - /// should submit this extrinsic to have their blocks accepted and earn rewards. - #[pallet::weight(::WeightInfo::add_association())] - pub fn add_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { - let account_id = ensure_signed(origin)?; - - Self::register_keys(nimbus_id.clone(), account_id, nimbus_id.into()) - } - - /// Change your Mapping. - /// - /// This is useful for normal key rotation or for when switching from one physical collator - /// machine to another. No new security deposit is required. - /// This sets keys to new_nimbus_id.into() by default. - #[pallet::weight(::WeightInfo::update_association())] - pub fn update_association( - origin: OriginFor, - old_nimbus_id: NimbusId, - new_nimbus_id: NimbusId, - ) -> DispatchResult { - let account_id = ensure_signed(origin)?; - - Self::rotate_keys( - old_nimbus_id, - new_nimbus_id.clone(), - account_id, - new_nimbus_id.into(), - ) - } - - /// Clear your Mapping. - /// - /// This is useful when you are no longer an author and would like to re-claim your security - /// deposit. - #[pallet::weight(::WeightInfo::clear_association())] - pub fn clear_association(origin: OriginFor, nimbus_id: NimbusId) -> DispatchResult { - let account_id = ensure_signed(origin)?; - - Self::rm_keys(nimbus_id, account_id) - } - - /// Remove your Mapping. - /// - /// This is useful when you are no longer an author and would like to re-claim your security - /// deposit. - #[pallet::weight(::WeightInfo::remove_keys())] - pub fn remove_keys(origin: OriginFor) -> DispatchResult { - let account_id = ensure_signed(origin)?; - let nimbus_id = - Self::nimbus_id_of(&account_id).ok_or(Error::::OldAuthorIdNotFound)?; - - Self::rm_keys(nimbus_id, account_id) - } - - /// Set association and session keys at once. - /// - /// This is useful for key rotation to update Nimbus and VRF keys in one call. - /// No new security deposit is required. Will replace `update_association` which is kept - /// now for backwards compatibility reasons. - #[pallet::weight(::WeightInfo::set_keys())] - pub fn set_keys(origin: OriginFor, keys: Vec) -> DispatchResult { - let account_id = ensure_signed(origin)?; - ensure!(keys.len() == keys_size::(), Error::::WrongKeySize); - let encoded = &mut keys.as_slice(); - let new_nimbus_id = - NimbusId::decode(encoded).map_err(|_| Error::::DecodeNimbusFailed)?; - let keys = T::Keys::decode(encoded).map_err(|_| Error::::DecodeKeysFailed)?; - - if let Some(old_nimbus_id) = Self::nimbus_id_of(&account_id) { - Self::rotate_keys(old_nimbus_id, new_nimbus_id, account_id, keys) - } else { - Self::register_keys(new_nimbus_id, account_id, keys) - } - } - } - - impl Pallet { - fn rm_keys(nimbus_id: NimbusId, account_id: T::AccountId) -> DispatchResult { - let stored_info = MappingWithDeposit::::try_get(&nimbus_id) - .map_err(|_| Error::::AssociationNotFound)?; - - ensure!(account_id == stored_info.account, Error::::NotYourAssociation); - - MappingWithDeposit::::remove(&nimbus_id); - NimbusLookup::::remove(&account_id); - - T::DepositCurrency::unreserve(&account_id, stored_info.deposit); - - >::deposit_event(Event::KeysRemoved { - nimbus_id, - account_id, - keys: stored_info.keys, - }); - Ok(()) - } - fn register_keys( - nimbus_id: NimbusId, - account_id: T::AccountId, - keys: T::Keys, - ) -> DispatchResult { - ensure!( - MappingWithDeposit::::get(&nimbus_id).is_none(), - Error::::AlreadyAssociated - ); - Self::enact_registration(&nimbus_id, &account_id, keys.clone())?; - - >::deposit_event(Event::KeysRegistered { nimbus_id, account_id, keys }); - Ok(()) - } - fn rotate_keys( - old_nimbus_id: NimbusId, - new_nimbus_id: NimbusId, - account_id: T::AccountId, - new_keys: T::Keys, - ) -> DispatchResult { - let stored_info = MappingWithDeposit::::try_get(&old_nimbus_id) - .map_err(|_| Error::::AssociationNotFound)?; - - ensure!(account_id == stored_info.account, Error::::NotYourAssociation); - if old_nimbus_id != new_nimbus_id { - // cannot overwrite a NimbusId if it is not yours - ensure!( - MappingWithDeposit::::get(&new_nimbus_id).is_none(), - Error::::AlreadyAssociated - ); - } - - MappingWithDeposit::::remove(&old_nimbus_id); - let new_stored_info = RegistrationInfo { keys: new_keys.clone(), ..stored_info }; - MappingWithDeposit::::insert(&new_nimbus_id, &new_stored_info); - NimbusLookup::::insert(&account_id, &new_nimbus_id); - - >::deposit_event(Event::KeysRotated { new_nimbus_id, account_id, new_keys }); - Ok(()) - } - pub fn enact_registration( - nimbus_id: &NimbusId, - account_id: &T::AccountId, - keys: T::Keys, - ) -> DispatchResult { - let deposit = T::DepositAmount::get(); - - T::DepositCurrency::reserve(account_id, deposit) - .map_err(|_| Error::::CannotAffordSecurityDeposit)?; - - let info = RegistrationInfo { account: account_id.clone(), deposit, keys }; - - MappingWithDeposit::::insert(nimbus_id, info); - NimbusLookup::::insert(account_id, nimbus_id); - - Ok(()) - } - } - - #[pallet::storage] - #[pallet::getter(fn account_and_deposit_of)] - /// We maintain a mapping from the NimbusIds used in the consensus layer - /// to the AccountIds runtime. - pub type MappingWithDeposit = - StorageMap<_, Blake2_128Concat, NimbusId, RegistrationInfo, OptionQuery>; - - #[pallet::storage] - #[pallet::getter(fn nimbus_lookup)] - /// We maintain a reverse mapping from AccountIds to NimbusIDS - pub type NimbusLookup = - StorageMap<_, Blake2_128Concat, T::AccountId, NimbusId, OptionQuery>; - - #[pallet::genesis_config] - /// Genesis config for author mapping pallet - pub struct GenesisConfig { - /// The associations that should exist at chain genesis - pub mappings: Vec<(NimbusId, T::AccountId)>, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { mappings: vec![] } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - for (nimbus_id, account_id) in &self.mappings { - if let Err(e) = - Pallet::::enact_registration(nimbus_id, account_id, nimbus_id.clone().into()) - { - log::warn!("Error with genesis author mapping registration: {:?}", e); - } - } - } - } - - impl AccountLookup for Pallet { - fn lookup_account(author: &NimbusId) -> Option { - Self::account_id_of(author) - } - } - - impl KeysLookup for Pallet { - #[cfg(feature = "runtime-benchmarks")] - type Account = T::AccountId; - fn lookup_keys(author: &NimbusId) -> Option { - Self::keys_of(author) - } - /// Sets keys WITHOUT reserving deposit, for benchmarking purposes only - #[cfg(feature = "runtime-benchmarks")] - fn set_keys(id: NimbusId, account: T::AccountId, keys: T::Keys) { - use sp_runtime::traits::Zero; - MappingWithDeposit::::insert( - id, - RegistrationInfo { account, deposit: Zero::zero(), keys }, - ); - } - } - - impl Pallet { - /// A helper function to lookup the account id associated with the given author id. This is - /// the primary lookup that this pallet is responsible for. - pub fn account_id_of(nimbus_id: &NimbusId) -> Option { - Self::account_and_deposit_of(nimbus_id).map(|info| info.account) - } - /// A helper function to lookup the keys associated with the given author id. - pub fn keys_of(nimbus_id: &NimbusId) -> Option { - Self::account_and_deposit_of(nimbus_id).map(|info| info.keys) - } - /// A helper function to lookup NimbusId associated with a given AccountId - pub fn nimbus_id_of(account_id: &T::AccountId) -> Option { - NimbusLookup::::get(account_id) - } - } -} diff --git a/external/pallets/author-mapping/src/migrations.rs b/external/pallets/author-mapping/src/migrations.rs deleted file mode 100644 index fe07aafe7..000000000 --- a/external/pallets/author-mapping/src/migrations.rs +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -use crate::{BalanceOf, Config, Event, MappingWithDeposit, NimbusLookup, Pallet, RegistrationInfo}; -use frame_support::{ - pallet_prelude::PhantomData, - traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, - weights::Weight, -}; -use nimbus_primitives::NimbusId; -use parity_scale_codec::{Decode, Encode}; - -#[cfg(feature = "try-runtime")] -use sp_std::vec::Vec; -/// Migrates MappingWithDeposit map value from RegistrationInfo to RegistrationInformation, -/// thereby adding a keys: T::Keys field to the value to support VRF keys that can be looked up -/// via NimbusId. -pub struct AddAccountIdToNimbusLookup(PhantomData); -impl OnRuntimeUpgrade for AddAccountIdToNimbusLookup { - fn on_runtime_upgrade() -> Weight { - log::info!(target: "AddAccountIdToNimbusLookup", "running migration"); - - let mut read_write_count = 0u64; - >::translate(|nimbus_id, registration_info: RegistrationInfo| { - read_write_count += 2u64; - if NimbusLookup::::get(®istration_info.account).is_none() { - >::insert(®istration_info.account, nimbus_id); - Some(registration_info) - } else { - // revoke the additional association and return the funds - T::DepositCurrency::unreserve( - ®istration_info.account, - registration_info.deposit, - ); - - >::deposit_event(Event::KeysRemoved { - nimbus_id, - account_id: registration_info.account, - keys: registration_info.keys, - }); - None - } - }); - // return weight - - T::DbWeight::get() - .reads(read_write_count) - .saturating_add(T::DbWeight::get().writes(read_write_count)) - } - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let mut nimbus_set: Vec = Vec::new(); - let mut state_map: BTreeMap = BTreeMap::new(); - for (nimbus_id, info) in >::iter() { - if !nimbus_set.contains(&nimbus_id) { - state_map.insert(nimbus_id.clone(), info.account); - nimbus_set.push(nimbus_id); - } - } - Ok(state_map.encode()) - } - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let state_map: BTreeMap = - Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - for (nimbus_id, _) in >::iter() { - let old_account = state_map.get(&nimbus_id).expect("qed"); - let maybe_account_of_nimbus = >::get(old_account); - assert_eq!( - Some(nimbus_id), - maybe_account_of_nimbus, - "New NimbusLookup dne expected NimbusID" - ); - } - Ok(()) - } -} - -/// Migrates MappingWithDeposit map value from RegistrationInfo to RegistrationInformation, -/// thereby adding a keys: T::Keys field to the value to support VRF keys that can be looked up -/// via NimbusId. -pub struct AddKeysToRegistrationInfo(PhantomData); -#[derive(Encode, Decode, PartialEq, Eq, Debug, scale_info::TypeInfo)] -struct OldRegistrationInfo { - account: AccountId, - deposit: Balance, -} -fn migrate_registration_info( - nimbus_id: NimbusId, - old: OldRegistrationInfo>, -) -> RegistrationInfo { - RegistrationInfo { account: old.account, deposit: old.deposit, keys: nimbus_id.into() } -} -impl OnRuntimeUpgrade for AddKeysToRegistrationInfo { - fn on_runtime_upgrade() -> Weight { - log::info!(target: "AddKeysToRegistrationInfo", "running migration"); - - let mut read_write_count = 0u64; - >::translate( - |nimbus_id, old_registration_info: OldRegistrationInfo>| { - read_write_count = read_write_count.saturating_add(1u64); - Some(migrate_registration_info(nimbus_id, old_registration_info)) - }, - ); - // return weight - T::DbWeight::get() - .reads(read_write_count) - .saturating_add(T::DbWeight::get().writes(read_write_count)) - } - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let mut state_map: BTreeMap)> = BTreeMap::new(); - - // get total deposited and account for all nimbus_keys - for (nimbus_id, info) in >::iter() { - state_map.insert(nimbus_id, (info.account, info.deposit)); - } - Ok(state_map.encode()) - } - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let state_map: BTreeMap)> = - Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - // ensure new deposit and account are the same as the old ones - // ensure new keys are equal to nimbus_id - for (nimbus_id, info) in >::iter() { - let (old_account, old_deposit) = state_map.get(&nimbus_id).expect("qed"); - - let new_account = info.account; - assert_eq!( - old_account.clone(), - new_account, - "Old Account {:?} dne New Account {:?} for NimbusID {:?}", - old_account.clone(), - new_account, - nimbus_id - ); - let new_deposit = info.deposit; - assert_eq!( - old_deposit.clone(), - new_deposit, - "Old Deposit {:?} dne New Deposit {:?} for NimbusID {:?}", - old_deposit.clone(), - new_deposit, - nimbus_id - ); - let nimbus_id_as_keys: T::Keys = nimbus_id.into(); - assert_eq!( - nimbus_id_as_keys, info.keys, - "Old NimbusID {:?} dne New Keys {:?}", - nimbus_id_as_keys, info.keys, - ); - } - Ok(()) - } -} diff --git a/external/pallets/author-mapping/src/mock.rs b/external/pallets/author-mapping/src/mock.rs deleted file mode 100644 index 2fe143c66..000000000 --- a/external/pallets/author-mapping/src/mock.rs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! A minimal runtime including the author-mapping pallet -use crate as pallet_author_mapping; -use frame_support::{ - construct_runtime, parameter_types, - traits::{Everything, GenesisBuild}, - weights::Weight, -}; -use nimbus_primitives::NimbusId; -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_core::{ByteArray, H256}; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - Perbill, RuntimeDebug, -}; - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] -pub enum TestAuthor { - Alice, - Bob, - Charlie, -} -impl Default for TestAuthor { - fn default() -> TestAuthor { - TestAuthor::Alice - } -} -impl From for NimbusId { - fn from(test_author: TestAuthor) -> Self { - match test_author { - TestAuthor::Alice => NimbusId::from_slice(&[0u8; 32]), - TestAuthor::Bob => NimbusId::from_slice(&[1u8; 32]), - TestAuthor::Charlie => NimbusId::from_slice(&[2u8; 32]), - } - .expect("valid ids") - } -} - -pub type AccountId = u64; -pub type Balance = u128; -pub type BlockNumber = u32; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -// Configure a mock runtime to test the pallet. -construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - AuthorMapping: pallet_author_mapping::{Pallet, Call, Storage, Config, Event}, - } -); - -parameter_types! { - pub const BlockHashCount: u32 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl frame_system::Config for Runtime { - type BaseCallFilter = Everything; - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = sp_runtime::generic::Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u128 = 1; -} -impl pallet_balances::Config for Runtime { - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type MaxLocks = (); - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} - -parameter_types! { - pub const DepositAmount: Balance = 100; -} -impl pallet_author_mapping::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type DepositCurrency = Balances; - type DepositAmount = DepositAmount; - type Keys = NimbusId; - type WeightInfo = (); -} - -/// Externality builder for pallet author mapping's mock runtime -/// Allows configuring balances and initial mappings -#[derive(Default)] -pub(crate) struct ExtBuilder { - /// Accounts endowed with balances - balances: Vec<(AccountId, Balance)>, - /// AuthorId -> AccoutId mappings - mappings: Vec<(NimbusId, AccountId)>, -} - -impl ExtBuilder { - pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { - self.balances = balances; - self - } - - pub(crate) fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { - self.mappings = mappings; - self - } - - pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { balances: self.balances } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - pallet_author_mapping::GenesisConfig:: { mappings: self.mappings } - .assimilate_storage(&mut t) - .expect("Pallet author mapping's storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } -} - -pub(crate) fn last_event() -> RuntimeEvent { - System::events().pop().expect("Event expected").event -} diff --git a/external/pallets/author-mapping/src/tests.rs b/external/pallets/author-mapping/src/tests.rs deleted file mode 100644 index 6bde4bf35..000000000 --- a/external/pallets/author-mapping/src/tests.rs +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Unit testing -use crate::{ - keys_size, keys_wrapper, - mock::{ - last_event, AuthorMapping, Balances, DepositAmount, ExtBuilder, Runtime, - RuntimeEvent as MetaEvent, RuntimeOrigin, System, TestAuthor, - }, - Error, Event, MappingWithDeposit, RegistrationInfo, -}; -use frame_support::{ - assert_noop, assert_ok, - traits::{OnRuntimeUpgrade, ReservableCurrency}, -}; -use nimbus_primitives::NimbusId; - -#[test] -fn check_key_size() { - // NimbusId (32) + NimbusId (32) - assert_eq!(keys_size::(), 64usize); -} - -#[test] -fn genesis_builder_works() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - assert_eq!(Balances::free_balance(&1), 900); - assert_eq!(Balances::reserved_balance(&1), 100); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), Some(1)); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); - }) -} - -#[test] -fn eligible_account_can_register() { - ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { - assert_ok!(AuthorMapping::add_association( - RuntimeOrigin::signed(2), - TestAuthor::Bob.into() - )); - - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Bob.into(), - account_id: 2, - keys: TestAuthor::Bob.into(), - }) - ); - }) -} - -#[test] -fn cannot_add_association_without_deposit() { - ExtBuilder::default().with_balances(vec![(2, 10)]).build().execute_with(|| { - assert_noop!( - AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), - Error::::CannotAffordSecurityDeposit - ); - - assert_eq!(Balances::free_balance(&2), 10); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), None); - }) -} - -#[test] -fn double_registration_costs_twice_as_much() { - ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { - // Register once as Bob - assert_ok!(AuthorMapping::add_association( - RuntimeOrigin::signed(2), - TestAuthor::Bob.into() - )); - - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Bob.into(), - account_id: 2, - keys: TestAuthor::Bob.into(), - }) - ); - - // Register again as Alice - assert_ok!(AuthorMapping::add_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into() - )); - - assert_eq!(Balances::free_balance(&2), 800); - assert_eq!(Balances::reserved_balance(&2), 200); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), Some(2)); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Alice.into(), - account_id: 2, - keys: TestAuthor::Alice.into(), - }) - ); - - // Should still be registered as Bob as well - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); - }) -} - -#[test] -fn registered_account_can_clear() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::remove_keys(RuntimeOrigin::signed(1))); - - assert_eq!(Balances::free_balance(&1), 1000); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Alice.into()), None); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRemoved { - nimbus_id: TestAuthor::Alice.into(), - account_id: 1, - keys: TestAuthor::Alice.into(), - }) - ); - }) -} - -#[test] -fn unregistered_author_cannot_be_cleared() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - AuthorMapping::remove_keys(RuntimeOrigin::signed(1)), - Error::::OldAuthorIdNotFound - ); - }) -} - -#[test] -fn registered_author_cannot_be_cleared_by_non_owner() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::clear_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into() - ), - Error::::NotYourAssociation - ); - }) -} - -#[test] -fn registered_author_cannot_be_overwritten() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::add_association(RuntimeOrigin::signed(2), TestAuthor::Alice.into()), - Error::::AlreadyAssociated - ); - }) -} - -#[test] -fn registered_can_rotate() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::update_association( - RuntimeOrigin::signed(2), - TestAuthor::Bob.into(), - TestAuthor::Charlie.into() - )); - - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), Some(2)); - - // Should still only have paid a single security deposit - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - }) -} - -#[test] -fn unregistered_author_cannot_be_rotated() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - AuthorMapping::update_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into(), - TestAuthor::Bob.into() - ), - Error::::AssociationNotFound - ); - }) -} - -#[test] -fn registered_author_cannot_be_rotated_by_non_owner() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::update_association( - RuntimeOrigin::signed(2), - TestAuthor::Alice.into(), - TestAuthor::Bob.into() - ), - Error::::NotYourAssociation - ); - }) -} - -#[test] -fn rotating_to_the_same_nimbus_id_leaves_registration_in_tact() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::update_association( - RuntimeOrigin::signed(1), - TestAuthor::Alice.into(), - TestAuthor::Alice.into() - )); - }) -} - -#[test] -fn eligible_account_can_full_register() { - ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Alice.into()), - )); - - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), Some(2)); - - assert_eq!( - last_event(), - MetaEvent::AuthorMapping(Event::KeysRegistered { - nimbus_id: TestAuthor::Bob.into(), - account_id: 2, - keys: TestAuthor::Alice.into(), - }) - ); - }) -} - -#[test] -fn cannot_set_keys_without_deposit() { - ExtBuilder::default().with_balances(vec![(2, 10)]).build().execute_with(|| { - assert_noop!( - AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), - ), - Error::::CannotAffordSecurityDeposit - ); - - assert_eq!(Balances::free_balance(&2), 10); - assert_eq!(AuthorMapping::keys_of(&TestAuthor::Alice.into()), None); - }) -} - -#[test] -fn full_registered_author_cannot_be_overwritten() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()), - ), - Error::::AlreadyAssociated - ); - }) -} - -#[test] -fn registered_can_full_rotate() { - ExtBuilder::default() - .with_balances(vec![(2, 1000)]) - .with_mappings(vec![(TestAuthor::Bob.into(), 2)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Charlie.into(), TestAuthor::Charlie.into()) - )); - - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Bob.into()), None); - assert_eq!(AuthorMapping::account_id_of(&TestAuthor::Charlie.into()), Some(2)); - assert_eq!( - AuthorMapping::keys_of(&TestAuthor::Charlie.into()), - Some(TestAuthor::Charlie.into()) - ); - - // Should still only have paid a single security deposit - assert_eq!(Balances::free_balance(&2), 900); - assert_eq!(Balances::reserved_balance(&2), 100); - }) -} - -#[test] -fn unregistered_author_can_be_full_rotated() { - ExtBuilder::default().with_balances(vec![(2, 1000)]).build().execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Bob.into(), TestAuthor::Bob.into()), - )); - }) -} - -#[test] -fn registered_author_cannot_be_full_rotated_by_non_owner() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_noop!( - AuthorMapping::set_keys( - RuntimeOrigin::signed(2), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Bob.into()) - ), - Error::::AlreadyAssociated - ); - }) -} - -#[test] -fn full_rotating_to_the_same_nimbus_id_leaves_registration_in_tact() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_mappings(vec![(TestAuthor::Alice.into(), 1)]) - .build() - .execute_with(|| { - assert_ok!(AuthorMapping::set_keys( - RuntimeOrigin::signed(1), - keys_wrapper::(TestAuthor::Alice.into(), TestAuthor::Alice.into()) - )); - }) -} - -#[test] -fn add_reverse_mapping_migration_works() { - ExtBuilder::default().with_balances(vec![(1, 300)]).build().execute_with(|| { - // register 3 NimbusId owned by 1 account - let alice_as_nimbus: NimbusId = TestAuthor::Alice.into(); - let bob_as_nimbus: NimbusId = TestAuthor::Bob.into(); - let charlie_as_nimbus: NimbusId = TestAuthor::Charlie.into(); - MappingWithDeposit::::insert( - alice_as_nimbus.clone(), - RegistrationInfo { - account: 1, - deposit: DepositAmount::get(), - keys: alice_as_nimbus.clone(), - }, - ); - MappingWithDeposit::::insert( - bob_as_nimbus.clone(), - RegistrationInfo { - account: 1, - deposit: DepositAmount::get(), - keys: bob_as_nimbus.clone(), - }, - ); - MappingWithDeposit::::insert( - charlie_as_nimbus.clone(), - RegistrationInfo { - account: 1, - deposit: DepositAmount::get(), - keys: charlie_as_nimbus.clone(), - }, - ); - assert_ok!(Balances::reserve(&1, DepositAmount::get() * 3)); - // run migration - crate::migrations::AddAccountIdToNimbusLookup::::on_runtime_upgrade(); - // ensure last 2 mappings revoked => 200 unreserved but still 100 reserved - assert_eq!(Balances::free_balance(&1), DepositAmount::get() * 2); - assert_eq!(Balances::reserved_balance(&1), DepositAmount::get()); - assert!(MappingWithDeposit::::get(bob_as_nimbus).is_some()); - assert!(MappingWithDeposit::::get(alice_as_nimbus).is_none()); - assert!(MappingWithDeposit::::get(charlie_as_nimbus).is_none()); - }) -} diff --git a/external/pallets/author-mapping/src/weights.rs b/external/pallets/author-mapping/src/weights.rs deleted file mode 100644 index 7fc754f33..000000000 --- a/external/pallets/author-mapping/src/weights.rs +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Autogenerated weights for pallet_author_mapping -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 - -// Executed Command: -// ./target/release/moonbeam -// benchmark -// pallet -// --execution=wasm -// --wasm-execution=compiled -// --pallet -// * -// --extrinsic -// * -// --steps -// 50 -// --repeat -// 20 -// --template=./benchmarking/frame-weight-template.hbs -// --json-file -// raw.json -// --output -// ./tmp/ - -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for pallet_author_mapping. -pub trait WeightInfo { - #[rustfmt::skip] - fn add_association() -> Weight; - #[rustfmt::skip] - fn update_association() -> Weight; - #[rustfmt::skip] - fn clear_association() -> Weight; - #[rustfmt::skip] - fn remove_keys() -> Weight; - #[rustfmt::skip] - fn set_keys() -> Weight; -} - -/// Weights for pallet_author_mapping using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) - #[rustfmt::skip] - fn add_association() -> Weight { - Weight::from_ref_time(50_753_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) - #[rustfmt::skip] - fn update_association() -> Weight { - Weight::from_ref_time(41_499_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) - #[rustfmt::skip] - fn clear_association() -> Weight { - Weight::from_ref_time(55_398_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn remove_keys() -> Weight { - Weight::from_ref_time(60_757_000_u64) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) - #[rustfmt::skip] - fn set_keys() -> Weight { - Weight::from_ref_time(45_388_000_u64) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) - #[rustfmt::skip] - fn add_association() -> Weight { - Weight::from_ref_time(50_753_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) - #[rustfmt::skip] - fn update_association() -> Weight { - Weight::from_ref_time(41_499_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: AuthorMapping NimbusLookup (r:0 w:1) - #[rustfmt::skip] - fn clear_association() -> Weight { - Weight::from_ref_time(55_398_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:1 w:1) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn remove_keys() -> Weight { - Weight::from_ref_time(60_757_000_u64) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - // Storage: AuthorMapping NimbusLookup (r:1 w:1) - // Storage: AuthorMapping MappingWithDeposit (r:2 w:2) - #[rustfmt::skip] - fn set_keys() -> Weight { - Weight::from_ref_time(45_388_000_u64) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } -} diff --git a/external/pallets/author-slot-filter/Cargo.toml b/external/pallets/author-slot-filter/Cargo.toml deleted file mode 100644 index 236372328..000000000 --- a/external/pallets/author-slot-filter/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -authors = ["PureStake"] -description = "Selects a pseudorandom Subset of eligible (probably staked) authors at each slot" -edition = "2021" -name = "pallet-author-slot-filter" -version = "0.9.0" - -[dependencies] -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -log = { version = "0.4.17", default-features = false } -nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", default-features = false, features = ["derive"] } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.32" } - -# Benchmarks -frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.32" } - -[dev-dependencies] -frame-support-test = { git = "https://github.com/paritytech/substrate", version = "3.0.0", branch = "polkadot-v0.9.32" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } - -[features] -default = ["std"] -std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "serde/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", -] - -runtime-benchmarks = ["frame-benchmarking", "nimbus-primitives/runtime-benchmarks"] - -try-runtime = ["frame-support/try-runtime", "nimbus-primitives/try-runtime"] diff --git a/external/pallets/author-slot-filter/src/benchmarks.rs b/external/pallets/author-slot-filter/src/benchmarks.rs deleted file mode 100644 index eb037ce49..000000000 --- a/external/pallets/author-slot-filter/src/benchmarks.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -#![cfg(feature = "runtime-benchmarks")] - -use crate::{num::NonZeroU32, Call, Config, Pallet}; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite}; -use frame_system::RawOrigin; - -benchmarks! { - set_eligible { - let count = NonZeroU32::new_unchecked(34); - }: _(RawOrigin::Root, count.clone()) - verify { - assert_eq!(Pallet::::eligible_count(), count); - } -} - -#[cfg(test)] -mod tests { - use crate::mock::Test; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t) - } -} - -impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Test); diff --git a/external/pallets/author-slot-filter/src/lib.rs b/external/pallets/author-slot-filter/src/lib.rs deleted file mode 100644 index 011eb0b56..000000000 --- a/external/pallets/author-slot-filter/src/lib.rs +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! Small pallet responsible determining which accounts are eligible to author at the current -//! slot. -//! -//! Using a randomness beacon supplied by the `Randomness` trait, this pallet takes the set of -//! currently active accounts from an upstream source, and filters them down to a pseudorandom subset. -//! The current technique gives no preference to any particular author. In the future, we could -//! disfavor authors who are authoring a disproportionate amount of the time in an attempt to -//! "even the playing field". - -#![allow(deprecated)] -#![cfg_attr(not(feature = "std"), no_std)] - -pub use pallet::*; - -#[cfg(any(test, feature = "runtime-benchmarks"))] -mod benchmarks; - -pub mod migration; -pub mod num; -pub mod weights; - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -#[frame_support::pallet] -pub mod pallet { - - use crate::{num::NonZeroU32, weights::WeightInfo}; - use frame_support::{pallet_prelude::*, traits::Randomness}; - use frame_system::pallet_prelude::*; - use log::debug; - use nimbus_primitives::CanAuthor; - use sp_core::H256; - use sp_runtime::Percent; - use sp_std::vec::Vec; - - /// The Author Filter pallet - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - /// Configuration trait of this pallet. - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type - type RuntimeEvent: From + IsType<::RuntimeEvent>; - /// Deterministic on-chain pseudo-randomness used to do the filtering - type RandomnessSource: Randomness; - //TODO introduce a new trait for exhaustive sets and use it here. - // Oh actually, we can use the same trait. First we call the inner one - // to determine whether this particular author is eligible there. then we - // use the author as part of the subject when querying eligibility. I like this better. - /// A source for the complete set of potential authors. - /// The starting point of the filtering. - type PotentialAuthors: Get>; - type WeightInfo: WeightInfo; - } - - /// Compute a pseudo-random subset of the input accounts by using Pallet's - /// source of randomness, `Config::RandomnessSource`. - /// Returns (Eligible, Ineligible), each is a set of accounts - pub fn compute_pseudo_random_subset( - mut active: Vec, - seed: &u32, - ) -> (Vec, Vec) { - let mut num_eligible = EligibleCount::::get().get() as usize; - if num_eligible > active.len() { - num_eligible = active.len(); - } - - let mut eligible = Vec::with_capacity(num_eligible); - - for i in 0..num_eligible { - // A context identifier for grabbing the randomness. Consists of three parts - // 1. Constant string *b"filter" - to identify this pallet - // 2. First 2 bytes of index.to_le_bytes when selecting the ith eligible author - // 3. First 4 bytes of seed.to_be_bytes - let first_two_bytes_of_index = &i.to_le_bytes()[..2]; - let first_four_bytes_of_seed = &seed.to_be_bytes()[..4]; - let constant_string: [u8; 6] = [b'f', b'i', b'l', b't', b'e', b'r']; - let mut subject: [u8; 12] = [0u8; 12]; - subject[..6].copy_from_slice(&constant_string); - subject[6..8].copy_from_slice(first_two_bytes_of_index); - subject[8..].copy_from_slice(first_four_bytes_of_seed); - let (randomness, _) = T::RandomnessSource::random(&subject); - debug!(target: "author-filter", "🎲Randomness sample {}: {:?}", i, &randomness); - - // Cast to u32 first so we get consistent results on 32- and 64-bit platforms. - let bytes: [u8; 4] = randomness.to_fixed_bytes()[0..4] - .try_into() - .expect("H256 has at least 4 bytes; qed"); - let randomness = u32::from_le_bytes(bytes) as usize; - - // Move the selected author from the original vector into the eligible vector - // TODO we could short-circuit this check by returning early when the claimed - // author is selected. For now I'll leave it like this because: - // 1. it is easier to understand what our core filtering logic is - // 2. we currently show the entire filtered set in the debug event - eligible.push(active.remove(randomness % active.len())); - } - (eligible, active) - } - - // This code will be called by the author-inherent pallet to check whether the reported author - // of this block is eligible in this slot. We calculate that result on demand and do not - // record it in storage (although we do emit a debugging event for now). - impl CanAuthor for Pallet { - #[cfg(not(feature = "try-runtime"))] - fn can_author(author: &T::AccountId, slot: &u32) -> bool { - // Compute pseudo-random subset of potential authors - let (eligible, ineligible) = - compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); - - // Print some logs for debugging purposes. - debug!(target: "author-filter", "Eligible Authors: {:?}", eligible); - debug!(target: "author-filter", "Ineligible Authors: {:?}", &ineligible); - debug!(target: "author-filter", - "Current author, {:?}, is eligible: {}", - author, - eligible.contains(author) - ); - - eligible.contains(author) - } - #[cfg(feature = "runtime-benchmarks")] - fn get_authors(slot: &u32) -> Vec { - // Compute pseudo-random subset of potential authors - let (eligible, _) = compute_pseudo_random_subset::(T::PotentialAuthors::get(), slot); - eligible - } - } - - #[pallet::call] - impl Pallet { - /// Update the eligible count. Intended to be called by governance. - #[pallet::weight(T::WeightInfo::set_eligible())] - pub fn set_eligible( - origin: OriginFor, - new: EligibilityValue, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - EligibleCount::::put(&new); - >::deposit_event(Event::EligibleUpdated(new)); - - Ok(Default::default()) - } - } - - /// The type of eligibility to use - pub type EligibilityValue = NonZeroU32; - - impl EligibilityValue { - /// Default total number of eligible authors, must NOT be 0. - pub fn default() -> Self { - NonZeroU32::new_unchecked(50) - } - } - - #[pallet::storage] - #[pallet::getter(fn eligible_ratio)] - #[deprecated(note = "use `pallet::EligibleCount` instead")] - pub type EligibleRatio = StorageValue<_, Percent, ValueQuery, Half>; - - // Default value for the `EligibleRatio` is one half. - #[pallet::type_value] - pub fn Half() -> Percent { - Percent::from_percent(50) - } - - /// The number of active authors that will be eligible at each height. - #[pallet::storage] - #[pallet::getter(fn eligible_count)] - pub type EligibleCount = - StorageValue<_, EligibilityValue, ValueQuery, DefaultEligibilityValue>; - - // Default value for the `EligibleCount`. - #[pallet::type_value] - pub fn DefaultEligibilityValue() -> EligibilityValue { - EligibilityValue::default() - } - - #[pallet::genesis_config] - pub struct GenesisConfig { - pub eligible_count: EligibilityValue, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { eligible_count: EligibilityValue::default() } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - EligibleCount::::put(self.eligible_count.clone()); - } - } - - #[pallet::event] - #[pallet::generate_deposit(fn deposit_event)] - pub enum Event { - /// The amount of eligible authors for the filter to select has been changed. - EligibleUpdated(EligibilityValue), - } -} diff --git a/external/pallets/author-slot-filter/src/migration.rs b/external/pallets/author-slot-filter/src/migration.rs deleted file mode 100644 index 5f47afe58..000000000 --- a/external/pallets/author-slot-filter/src/migration.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use core::marker::PhantomData; -use frame_support::{ - traits::{Get, OnRuntimeUpgrade}, - weights::Weight, -}; -#[cfg(feature = "try-runtime")] -use parity_scale_codec::{Decode, Encode}; -use sp_runtime::Percent; -#[cfg(feature = "try-runtime")] -use sp_std::vec::Vec; - -use super::{ - num::NonZeroU32, - pallet::{Config, EligibilityValue, EligibleCount, Pallet}, -}; -pub struct EligibleRatioToEligiblityCount(PhantomData); - -impl OnRuntimeUpgrade for EligibleRatioToEligiblityCount -where - T: Config, -{ - fn on_runtime_upgrade() -> Weight { - log::info!(target: "EligibleRatioToEligiblityCount", "starting migration"); - - let old_value = >::eligible_ratio(); - let total_authors = ::PotentialAuthors::get().len(); - let new_value = percent_of_num(old_value, total_authors as u32); - let new_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); - >::put(new_value); - - T::DbWeight::get().reads_writes(1, 1) - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - let old_value = >::eligible_ratio(); - - let total_authors = ::PotentialAuthors::get().len(); - let new_value = percent_of_num(old_value, total_authors as u32); - let expected_value = NonZeroU32::new(new_value).unwrap_or_else(EligibilityValue::default); - - Ok(expected_value.encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - let expected: NonZeroU32 = - Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - let actual = >::eligible_count(); - - assert_eq!(expected, actual); - - Ok(()) - } -} - -fn percent_of_num(percent: Percent, num: u32) -> u32 { - percent.mul_ceil(num as u32) -} - -#[cfg(test)] -mod tests { - use super::{percent_of_num, *}; - - #[test] - fn test_percent_of_num_ceils_value() { - let fifty_percent = Percent::from_float(0.5); - - let actual = percent_of_num(fifty_percent, 5); - assert_eq!(3, actual); - - let actual = percent_of_num(fifty_percent, 20); - assert_eq!(10, actual); - } - - #[test] - fn test_percent_of_num_hundred_percent_uses_full_value() { - let one_hundred_percent = Percent::from_float(1.0); - - let actual = percent_of_num(one_hundred_percent, 5); - assert_eq!(5, actual); - - let actual = percent_of_num(one_hundred_percent, 20); - assert_eq!(20, actual); - } -} diff --git a/external/pallets/author-slot-filter/src/mock.rs b/external/pallets/author-slot-filter/src/mock.rs deleted file mode 100644 index 7354a20db..000000000 --- a/external/pallets/author-slot-filter/src/mock.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use crate as pallet_testing; -use frame_support::{parameter_types, sp_io, traits::ConstU32, weights::RuntimeDbWeight}; -use frame_support_test::TestRandomness; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, -}; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - AuthorSlotFilter: pallet_testing::{Pallet, Call, Storage, Event}, - } -); - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub Authors: Vec = vec![1, 2, 3, 4, 5]; - pub const TestDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 1, - write: 10, - }; -} - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = TestDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} - -impl pallet_testing::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RandomnessSource = TestRandomness; - type PotentialAuthors = Authors; - type WeightInfo = (); -} - -/// Build genesis storage according to the mock runtime. -pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::default().build_storage::().unwrap().into() -} diff --git a/external/pallets/author-slot-filter/src/num.rs b/external/pallets/author-slot-filter/src/num.rs deleted file mode 100644 index 765423c61..000000000 --- a/external/pallets/author-slot-filter/src/num.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -//! Implements a [NonZeroU32] type that interplays nicely with the -//! subtrate storage and the SCALE codec. - -use parity_scale_codec::{Decode, Encode, Error, Input}; -use scale_info::TypeInfo; -use serde::{de::Error as DeserializeError, Deserialize, Deserializer, Serialize, Serializer}; - -#[derive(Clone, Debug, TypeInfo, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct NonZeroU32(u32); - -impl core::ops::Deref for NonZeroU32 { - type Target = u32; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl parity_scale_codec::EncodeLike for NonZeroU32 {} - -impl NonZeroU32 { - /// Creates a new `Some(NonZeroU32)` instance if value is 0, `None` otherwise. - #[inline] - pub const fn new(n: u32) -> Option { - if n != 0 { Some(Self(n)) } else { None } - } - - /// new_unchecked creats a `NonZeroU32` where the user MUST guarantee - /// that the value is nonzero. - #[inline] - pub const fn new_unchecked(n: u32) -> Self { - Self(n) - } - - /// Returns the the underlying number - pub fn get(&self) -> u32 { - self.0 - } -} - -#[cfg(feature = "std")] -impl Serialize for NonZeroU32 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.clone().get().serialize(serializer) - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for NonZeroU32 { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let value = Deserialize::deserialize(deserializer)?; - match NonZeroU32::new(value) { - Some(nonzero) => Ok(nonzero), - None => Err(DeserializeError::custom("expected a non-zero value")), - } - } -} - -impl Decode for NonZeroU32 { - fn decode(input: &mut I) -> Result { - Self::new(Decode::decode(input)?) - .ok_or_else(|| Error::from("cannot create non-zero number from 0")) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use parity_scale_codec::Encode; - - #[test] - fn test_new_returns_none_if_zero() { - assert_eq!(None, NonZeroU32::new(0)); - } - - #[test] - fn test_new_returns_some_if_nonzero() { - let n = 10; - let expected = Some(NonZeroU32::new_unchecked(n)); - - let actual = NonZeroU32::new(n); - assert_eq!(expected, actual); - assert_eq!(n, actual.unwrap().get()); - } - - #[test] - fn test_decode_errors_if_zero_value() { - let buf: Vec = 0u32.encode(); - let result = NonZeroU32::decode(&mut &buf[..]); - assert!(result.is_err(), "expected error, got {:?}", result); - } - - #[test] - fn test_decode_succeeds_if_nonzero_value() { - let buf: Vec = 1u32.encode(); - - let result = NonZeroU32::decode(&mut &buf[..]); - assert!(result.is_ok(), "unexpected error, got {:?}", result); - assert_eq!(Ok(NonZeroU32::new_unchecked(1)), result); - } -} diff --git a/external/pallets/author-slot-filter/src/tests.rs b/external/pallets/author-slot-filter/src/tests.rs deleted file mode 100644 index f01599a5e..000000000 --- a/external/pallets/author-slot-filter/src/tests.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Nimbus. - -// Nimbus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Nimbus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Nimbus. If not, see . - -use super::*; -use crate::{mock::*, num::NonZeroU32}; - -use frame_support::{assert_ok, traits::OnRuntimeUpgrade, weights::Weight}; -use sp_runtime::Percent; - -#[test] -fn test_set_eligibility_works() { - new_test_ext().execute_with(|| { - let value = num::NonZeroU32::new_unchecked(34); - - assert_ok!(AuthorSlotFilter::set_eligible(RuntimeOrigin::root(), value.clone())); - assert_eq!(AuthorSlotFilter::eligible_count(), value) - }); -} - -#[allow(deprecated)] -#[test] -fn test_migration_works_for_converting_existing_eligible_ratio_to_eligible_count() { - new_test_ext().execute_with(|| { - let input_eligible_ratio = Percent::from_percent(50); - let total_author_count = mock::Authors::get().len(); - let eligible_author_count = input_eligible_ratio.mul_ceil(total_author_count) as u32; - let expected_eligible_count = NonZeroU32::new_unchecked(eligible_author_count); - let expected_weight = - Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); - - >::put(input_eligible_ratio); - - let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); - assert_eq!(expected_weight, actual_weight); - - let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); - let actual_eligible_count = AuthorSlotFilter::eligible_count(); - assert_eq!(expected_eligible_count, actual_eligible_count); - assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); - }); -} - -#[allow(deprecated)] -#[test] -fn test_migration_works_for_converting_existing_zero_eligible_ratio_to_default_eligible_count() { - new_test_ext().execute_with(|| { - let input_eligible_ratio = Percent::from_percent(0); - let expected_eligible_count = EligibilityValue::default(); - let expected_weight = - Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); - - >::put(input_eligible_ratio); - - let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); - assert_eq!(expected_weight, actual_weight); - - let actual_eligible_ratio_after = AuthorSlotFilter::eligible_ratio(); - let actual_eligible_count = AuthorSlotFilter::eligible_count(); - assert_eq!(expected_eligible_count, actual_eligible_count); - assert_eq!(input_eligible_ratio, actual_eligible_ratio_after); - }); -} - -#[allow(deprecated)] -#[test] -fn test_migration_inserts_default_value_for_missing_eligible_ratio() { - new_test_ext().execute_with(|| { - let default_eligible_ratio = Percent::from_percent(50); - let expected_default_eligible_count = - NonZeroU32::new_unchecked(default_eligible_ratio.mul_ceil(Authors::get().len() as u32)); - let expected_weight = - Weight::from_ref_time(TestDbWeight::get().write + TestDbWeight::get().read); - - let actual_weight = migration::EligibleRatioToEligiblityCount::::on_runtime_upgrade(); - assert_eq!(expected_weight, actual_weight); - - let actual_eligible_count = AuthorSlotFilter::eligible_count(); - assert_eq!(expected_default_eligible_count, actual_eligible_count); - }); -} diff --git a/external/pallets/author-slot-filter/src/weights.rs b/external/pallets/author-slot-filter/src/weights.rs deleted file mode 100644 index 8b7ee79c2..000000000 --- a/external/pallets/author-slot-filter/src/weights.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Autogenerated weights for pallet_author_slot_filter -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-03-07, STEPS: `32`, REPEAT: 64, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/release/moonbeam -// benchmark -// --chain -// dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet -// pallet_author_slot_filter -// --extrinsic -// * -// --steps -// 32 -// --repeat -// 64 -// --template=./benchmarking/frame-weight-template.hbs -// --output -// /tmp/ -// --record-proof - -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for pallet_author_slot_filter. -pub trait WeightInfo { - fn set_eligible() -> Weight; -} - -/// Weights for pallet_author_slot_filter using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn set_eligible() -> Weight { - Weight::from_ref_time(13_250_000_u64).saturating_add(T::DbWeight::get().writes(1_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - fn set_eligible() -> Weight { - Weight::from_ref_time(13_250_000_u64).saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} diff --git a/external/pallets/parachain-staking/Cargo.toml b/external/pallets/parachain-staking/Cargo.toml deleted file mode 100644 index f0777ee6a..000000000 --- a/external/pallets/parachain-staking/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -authors = ["PureStake"] -description = "parachain staking pallet for collator selection and reward distribution" -edition = "2021" -name = "pallet-parachain-staking" -version = "3.0.0" - -[dependencies] -log = "0.4.17" -serde = { version = "1.0.101", optional = true } - -# Substrate -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } - -# Nimbus -nimbus-primitives = { path = "../../nimbus-primitives", default-features = false } - -[dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -similar-asserts = "1.1.0" -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } - -[features] -default = ["std"] -runtime-benchmarks = ["frame-benchmarking"] -std = [ - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "serde", - "sp-runtime/std", - "sp-std/std", -] -try-runtime = ["frame-support/try-runtime"] diff --git a/external/pallets/parachain-staking/README.md b/external/pallets/parachain-staking/README.md deleted file mode 100644 index e169fe702..000000000 --- a/external/pallets/parachain-staking/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# DPoS Pallet for Parachain Staking - -## Formatting Rules - -- dependencies in alphabetical order in the `Cargo.toml` and at the top of each file -- prefer explicit imports to glob import syntax i.e. prefer `use::crate::{Ex1, Ex2, ..};` to `use super::*;` - -## Description - -Implements Delegated Proof of Stake to - -1. select the active set of eligible block producers -2. reward block authors -3. enable delegators and collators to participate in inflationary rewards - -Links: - -- [Rust Documentation](https://purestake.github.io/moonbeam/pallet_parachain_staking/index.html) -- [Unofficial Documentation](https://meta5.world/parachain-staking-docs/) -- [(Outdated) Blog Post with Justification](https://meta5.world/posts/parachain-staking) - -## History - -Since January 2021, Moonbeam's team has maintained this Delegated Proof of Stake (DPoS) pallet designed specifically for parachains. - -Since April 2021, the development of this pallet has been supported by [a Web3 Foundation grant](https://github.com/w3f/Grants-Program/pull/389). The [first milestone](https://github.com/w3f/Grant-Milestone-Delivery/pull/218) was approved in June 2021. diff --git a/external/pallets/parachain-staking/migrations.md b/external/pallets/parachain-staking/migrations.md deleted file mode 100644 index d2277ffcd..000000000 --- a/external/pallets/parachain-staking/migrations.md +++ /dev/null @@ -1,42 +0,0 @@ -# Migration History - -## Calculate outgoing rewards based on pending revoke and decrease changes - -- [Migration PR `#1408`](https://github.com/PureStake/moonbeam/pull/1408) - -## Patch delegations total mismatch - -- [Migration PR `#1291`](https://github.com/PureStake/moonbeam/pull/1291) - -## Split candidate state for PoV optimization - -- [Migration PR `#1117`](https://github.com/PureStake/moonbeam/pull/1117) - -## Increase max delegations per candidate - -- [Migration PR `#1096`](https://github.com/PureStake/moonbeam/pull/1096) -- [Migratio bugfix `#1112`](https://github.com/PureStake/moonbeam/pull/1112) - -## Manual Exits and Patch Lack of Delay for bond\_{more, less} - -- [Migration PR `#810`](https://github.com/PureStake/moonbeam/pull/810) -- [Migration Removal PR `#?`]() - -## Purge Stale Storage - -- [Migration PR `#970`](https://github.com/PureStake/moonbeam/pull/970) - -## Delay nominator exits by changing NominatorState and ExitQueue - -- [Migration PR `#610`](https://github.com/PureStake/moonbeam/pull/610) -- [Migration Removal PR `#662`](https://github.com/PureStake/moonbeam/pull/662) - -## Patch nomination DOS attack vector by changing CollatorState - -- [Migration PR `#505`](https://github.com/PureStake/moonbeam/pull/505) -- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) - -## Patch underflow bug and correct Total storage item - -- [Migration PR `#502`](https://github.com/PureStake/moonbeam/pull/502) -- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) diff --git a/external/pallets/parachain-staking/src/auto_compound.rs b/external/pallets/parachain-staking/src/auto_compound.rs deleted file mode 100644 index f9ee68b54..000000000 --- a/external/pallets/parachain-staking/src/auto_compound.rs +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Auto-compounding functionality for staking rewards -#![allow(clippy::len_without_is_empty)] -use crate::{ - pallet::{ - AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, CandidateInfo, - Config, DelegatorState, Error, Event, Pallet, Total, - }, - types::{Bond, BondAdjust, Delegator}, -}; -use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Saturating, Percent}; -use sp_std::{prelude::*, vec::Vec}; - -/// Represents the auto-compounding amount for a delegation. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] -pub struct AutoCompoundConfig { - pub delegator: AccountId, - pub value: Percent, -} - -/// Represents the auto-compounding [Delegations] for `T: Config` -#[derive(Clone, Eq, PartialEq, RuntimeDebug)] -pub struct AutoCompoundDelegations(Vec>); - -impl AutoCompoundDelegations -where - T: Config, -{ - /// Creates a new instance of [AutoCompoundingDelegations] from a vector of sorted_delegations. - /// This is used for testing purposes only. - #[cfg(test)] - pub fn new(sorted_delegations: Vec>) -> Self { - Self(sorted_delegations) - } - - /// Retrieves an instance of [AutoCompoundingDelegations] storage as [AutoCompoundDelegations]. - pub fn get_storage(candidate: &T::AccountId) -> Self { - Self(>::get(candidate)) - } - - /// Inserts the current state to [AutoCompoundingDelegations] storage. - pub fn set_storage(self, candidate: &T::AccountId) { - >::insert(candidate, self.0) - } - - /// Retrieves the auto-compounding value for a delegation. The `delegations_config` must be a - /// sorted vector for binary_search to work. - pub fn get_for_delegator(&self, delegator: &T::AccountId) -> Option { - match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { - Ok(index) => Some(self.0[index].value), - Err(_) => None, - } - } - - /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted - /// vector for binary_search to work. - pub fn set_for_delegator(&mut self, delegator: T::AccountId, value: Percent) -> bool { - match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { - Ok(index) => { - if self.0[index].value == value { - false - } else { - self.0[index].value = value; - true - } - } - Err(index) => { - self.0.insert(index, AutoCompoundConfig { delegator, value }); - true - } - } - } - - /// Removes the auto-compounding value for a delegation. - /// Returns `true` if the entry was removed, `false` otherwise. The `delegations_config` must be a - /// sorted vector for binary_search to work. - pub fn remove_for_delegator(&mut self, delegator: &T::AccountId) -> bool { - match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { - Ok(index) => { - self.0.remove(index); - true - } - Err(_) => false, - } - } - - /// Returns the length of the inner vector. - pub fn len(&self) -> u32 { - self.0.len() as u32 - } - - /// Returns a reference to the inner vector. - #[cfg(test)] - pub fn inner(&self) -> &Vec> { - &self.0 - } - - /// Converts the [AutoCompoundDelegations] into the inner vector. - #[cfg(test)] - pub fn into_inner(self) -> Vec> { - self.0 - } - - // -- pallet functions -- - - /// Delegates and sets the auto-compounding config. The function skips inserting auto-compound - /// storage and validation, if the auto-compound value is 0%. - pub(crate) fn delegate_with_auto_compound( - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - auto_compound: Percent, - candidate_delegation_count_hint: u32, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - // check that caller can lock the amount before any changes to storage - ensure!( - >::get_delegator_stakable_free_balance(&delegator) >= amount, - Error::::InsufficientBalance - ); - - let mut delegator_state = if let Some(mut state) = >::get(&delegator) { - // delegation after first - ensure!(amount >= T::MinDelegation::get(), Error::::DelegationBelowMin); - ensure!( - delegation_count_hint >= state.delegations.0.len() as u32, - Error::::TooLowDelegationCountToDelegate - ); - ensure!( - (state.delegations.0.len() as u32) < T::MaxDelegationsPerDelegator::get(), - Error::::ExceedMaxDelegationsPerDelegator - ); - ensure!( - state.add_delegation(Bond { owner: candidate.clone(), amount }), - Error::::AlreadyDelegatedCandidate - ); - state - } else { - // first delegation - ensure!(amount >= T::MinDelegatorStk::get(), Error::::DelegatorBondBelowMin); - ensure!(!>::is_candidate(&delegator), Error::::CandidateExists); - Delegator::new(delegator.clone(), candidate.clone(), amount) - }; - let mut candidate_state = - >::get(&candidate).ok_or(Error::::CandidateDNE)?; - ensure!( - candidate_delegation_count_hint >= candidate_state.delegation_count, - Error::::TooLowCandidateDelegationCountToDelegate - ); - - let auto_compounding_state = if !auto_compound.is_zero() { - let auto_compounding_state = Self::get_storage(&candidate); - ensure!( - auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, - >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, - ); - Some(auto_compounding_state) - } else { - None - }; - - // add delegation to candidate - let (delegator_position, less_total_staked) = candidate_state - .add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; - - // lock delegator amount - delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; - - // adjust total locked, - // only is_some if kicked the lowest bottom as a consequence of this new delegation - let net_total_increase = - if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; - let new_total_locked = >::get().saturating_add(net_total_increase); - - // maybe set auto-compound config, state is Some if the percent is non-zero - if let Some(mut state) = auto_compounding_state { - state.set_for_delegator(delegator.clone(), auto_compound); - state.set_storage(&candidate); - } - - >::put(new_total_locked); - >::insert(&candidate, candidate_state); - >::insert(&delegator, delegator_state); - >::deposit_event(Event::Delegation { - delegator, - locked_amount: amount, - candidate, - delegator_position, - auto_compound, - }); - - Ok(().into()) - } - - /// Sets the auto-compounding value for a delegation. The config is removed if value is zero. - pub(crate) fn set_auto_compound( - candidate: T::AccountId, - delegator: T::AccountId, - value: Percent, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - let delegator_state = - >::get(&delegator).ok_or(>::DelegatorDNE)?; - ensure!( - delegator_state.delegations.0.len() <= delegation_count_hint as usize, - >::TooLowDelegationCountToAutoCompound, - ); - ensure!( - delegator_state.delegations.0.iter().any(|b| b.owner == candidate), - >::DelegationDNE, - ); - - let mut auto_compounding_state = Self::get_storage(&candidate); - ensure!( - auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, - >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - ); - let state_updated = if value.is_zero() { - auto_compounding_state.remove_for_delegator(&delegator) - } else { - auto_compounding_state.set_for_delegator(delegator.clone(), value) - }; - if state_updated { - auto_compounding_state.set_storage(&candidate); - } - - >::deposit_event(Event::AutoCompoundSet { candidate, delegator, value }); - - Ok(().into()) - } - - /// Removes the auto-compounding value for a delegation. This should be called when the - /// delegation is revoked to cleanup storage. Storage is only written iff the entry existed. - pub(crate) fn remove_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) { - let mut auto_compounding_state = Self::get_storage(candidate); - if auto_compounding_state.remove_for_delegator(delegator) { - auto_compounding_state.set_storage(candidate); - } - } - - /// Returns the value of auto-compound, if it exists for a given delegation, zero otherwise. - pub(crate) fn auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { - let delegations_config = Self::get_storage(candidate); - delegations_config.get_for_delegator(delegator).unwrap_or_else(Percent::zero) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::Test; - - #[test] - fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { - let mut delegations_config = AutoCompoundDelegations::::new(vec![]); - assert!(delegations_config.set_for_delegator(1, Percent::from_percent(50))); - assert_eq!( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], - delegations_config.into_inner(), - ); - } - - #[test] - fn test_set_for_delegator_updates_config_and_returns_true_if_entry_changed() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }]); - assert!(delegations_config.set_for_delegator(1, Percent::from_percent(50))); - assert_eq!( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], - delegations_config.into_inner(), - ); - } - - #[test] - fn test_set_for_delegator_updates_config_and_returns_false_if_entry_unchanged() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }]); - assert!(!delegations_config.set_for_delegator(1, Percent::from_percent(10))); - assert_eq!( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }], - delegations_config.into_inner(), - ); - } - - #[test] - fn test_remove_for_delegator_returns_false_if_entry_was_missing() { - let mut delegations_config = AutoCompoundDelegations::::new(vec![]); - assert!(!delegations_config.remove_for_delegator(&1),); - } - - #[test] - fn test_remove_delegation_config_returns_true_if_entry_existed() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![AutoCompoundConfig { - delegator: 1, - value: Percent::from_percent(10), - }]); - assert!(delegations_config.remove_for_delegator(&1)); - } -} diff --git a/external/pallets/parachain-staking/src/benchmarks.rs b/external/pallets/parachain-staking/src/benchmarks.rs deleted file mode 100644 index 283f270c2..000000000 --- a/external/pallets/parachain-staking/src/benchmarks.rs +++ /dev/null @@ -1,1483 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -#![cfg(feature = "runtime-benchmarks")] - -//! Benchmarking -use crate::{ - AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, - ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, - Staked, TopDelegations, -}; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; -use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; -use frame_system::RawOrigin; -use sp_runtime::{Perbill, Percent}; -use sp_std::vec::Vec; - -/// Minimum collator candidate stake -fn min_candidate_stk() -> BalanceOf { - <::MinCollatorStk as Get>>::get() -} - -/// Minimum delegator stake -fn min_delegator_stk() -> BalanceOf { - <::MinDelegatorStk as Get>>::get() -} - -/// Create a funded user. -/// Extra + min_candidate_stk is total minted funds -/// Returns tuple (id, balance) -fn create_funded_user( - string: &'static str, - n: u32, - extra: BalanceOf, -) -> (T::AccountId, BalanceOf) { - const SEED: u32 = 0; - let user = account(string, n, SEED); - let min_candidate_stk = min_candidate_stk::(); - let total = min_candidate_stk + extra; - T::Currency::make_free_balance_be(&user, total); - T::Currency::issue(total); - (user, total) -} - -/// Create a funded delegator. -fn create_funded_delegator( - string: &'static str, - n: u32, - extra: BalanceOf, - collator: T::AccountId, - min_bond: bool, - collator_delegator_count: u32, -) -> Result { - let (user, total) = create_funded_user::(string, n, extra); - let bond = if min_bond { min_delegator_stk::() } else { total }; - Pallet::::delegate( - RawOrigin::Signed(user.clone()).into(), - collator, - bond, - collator_delegator_count, - 0u32, // first delegation for all calls - )?; - Ok(user) -} - -/// Create a funded collator. -fn create_funded_collator( - string: &'static str, - n: u32, - extra: BalanceOf, - min_bond: bool, - candidate_count: u32, -) -> Result { - let (user, total) = create_funded_user::(string, n, extra); - let bond = if min_bond { min_candidate_stk::() } else { total }; - Pallet::::join_candidates(RawOrigin::Signed(user.clone()).into(), bond, candidate_count)?; - Ok(user) -} - -// Simulate staking on finalize by manually setting points -fn parachain_staking_on_finalize(author: T::AccountId) { - let now = >::get().current; - let score_plus_20 = >::get(now, &author).saturating_add(20); - >::insert(now, author, score_plus_20); - >::mutate(now, |x| *x = x.saturating_add(20)); -} - -/// Run to end block and author -fn roll_to_and_author(round_delay: u32, author: T::AccountId) { - let total_rounds = round_delay + 1u32; - let round_length: T::BlockNumber = Pallet::::round().length.into(); - let mut now = >::block_number() + 1u32.into(); - let end = Pallet::::round().first + (round_length * total_rounds.into()); - while now < end { - parachain_staking_on_finalize::(author.clone()); - >::on_finalize(>::block_number()); - >::set_block_number( - >::block_number() + 1u32.into(), - ); - >::on_initialize(>::block_number()); - Pallet::::on_initialize(>::block_number()); - now += 1u32.into(); - } -} - -const USER_SEED: u32 = 999666; -struct Seed { - pub inner: u32, -} -impl Seed { - fn new() -> Self { - Seed { inner: USER_SEED } - } - - pub fn take(&mut self) -> u32 { - let v = self.inner; - self.inner += 1; - v - } -} - -benchmarks! { - // MONETARY ORIGIN DISPATCHABLES - set_staking_expectations { - let stake_range: Range> = Range { - min: 100u32.into(), - ideal: 200u32.into(), - max: 300u32.into(), - }; - }: _(RawOrigin::Root, stake_range) - verify { - assert_eq!(Pallet::::inflation_config().expect, stake_range); - } - - set_inflation { - let inflation_range: Range = Range { - min: Perbill::from_perthousand(1), - ideal: Perbill::from_perthousand(2), - max: Perbill::from_perthousand(3), - }; - - }: _(RawOrigin::Root, inflation_range) - verify { - assert_eq!(Pallet::::inflation_config().annual, inflation_range); - } - - set_parachain_bond_account { - let parachain_bond_account: T::AccountId = account("TEST", 0u32, USER_SEED); - }: _(RawOrigin::Root, parachain_bond_account.clone()) - verify { - assert_eq!(Pallet::::parachain_bond_info().account, parachain_bond_account); - } - - set_parachain_bond_reserve_percent { - }: _(RawOrigin::Root, Percent::from_percent(33)) - verify { - assert_eq!(Pallet::::parachain_bond_info().percent, Percent::from_percent(33)); - } - - // ROOT DISPATCHABLES - - set_total_selected { - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; - }: _(RawOrigin::Root, 100u32) - verify { - assert_eq!(Pallet::::total_selected(), 100u32); - } - - set_collator_commission {}: _(RawOrigin::Root, Perbill::from_percent(33)) - verify { - assert_eq!(Pallet::::collator_commission(), Perbill::from_percent(33)); - } - - set_blocks_per_round {}: _(RawOrigin::Root, 1200u32) - verify { - assert_eq!(Pallet::::round().length, 1200u32); - } - - // USER DISPATCHABLES - - join_candidates { - let x in 3..1_000; - // Worst Case Complexity is insertion into an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let (caller, min_candidate_stk) = create_funded_user::("caller", USER_SEED, 0u32.into()); - }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk, candidate_count) - verify { - assert!(Pallet::::is_candidate(&caller)); - } - - // This call schedules the collator's exit and removes them from the candidate pool - // -> it retains the self-bond and delegator bonds - schedule_leave_candidates { - let x in 3..1_000; - // Worst Case Complexity is removal from an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let caller: T::AccountId = create_funded_collator::( - "caller", - USER_SEED, - 0u32.into(), - true, - candidate_count, - )?; - candidate_count += 1u32; - }: _(RawOrigin::Signed(caller.clone()), candidate_count) - verify { - assert!(Pallet::::candidate_info(&caller).unwrap().is_leaving()); - } - - execute_leave_candidates { - // x is total number of delegations for the candidate - let x in 2..(<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get()); - let candidate: T::AccountId = create_funded_collator::( - "unique_caller", - USER_SEED - 100, - 0u32.into(), - true, - 1u32, - )?; - // 2nd delegation required for all delegators to ensure DelegatorState updated not removed - let second_candidate: T::AccountId = create_funded_collator::( - "unique__caller", - USER_SEED - 99, - 0u32.into(), - true, - 2u32, - )?; - let mut delegators: Vec = Vec::new(); - let mut col_del_count = 0u32; - for i in 1..x { - let seed = USER_SEED + i; - let delegator = create_funded_delegator::( - "delegator", - seed, - min_delegator_stk::(), - candidate.clone(), - true, - col_del_count, - )?; - Pallet::::delegate( - RawOrigin::Signed(delegator.clone()).into(), - second_candidate.clone(), - min_delegator_stk::(), - col_del_count, - 1u32, - )?; - Pallet::::schedule_revoke_delegation( - RawOrigin::Signed(delegator.clone()).into(), - candidate.clone() - )?; - delegators.push(delegator); - col_del_count += 1u32; - } - Pallet::::schedule_leave_candidates( - RawOrigin::Signed(candidate.clone()).into(), - 3u32 - )?; - roll_to_and_author::(2, candidate.clone()); - }: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count) - verify { - assert!(Pallet::::candidate_info(&candidate).is_none()); - assert!(Pallet::::candidate_info(&second_candidate).is_some()); - for delegator in delegators { - assert!(Pallet::::is_delegator(&delegator)); - } - } - - cancel_leave_candidates { - let x in 3..1_000; - // Worst Case Complexity is removal from an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let caller: T::AccountId = create_funded_collator::( - "caller", - USER_SEED, - 0u32.into(), - true, - candidate_count, - )?; - candidate_count += 1u32; - Pallet::::schedule_leave_candidates( - RawOrigin::Signed(caller.clone()).into(), - candidate_count - )?; - candidate_count -= 1u32; - }: _(RawOrigin::Signed(caller.clone()), candidate_count) - verify { - assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); - } - - go_offline { - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(!Pallet::::candidate_info(&caller).unwrap().is_active()); - } - - go_online { - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - Pallet::::go_offline(RawOrigin::Signed(caller.clone()).into())?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(Pallet::::candidate_info(&caller).unwrap().is_active()); - } - - candidate_bond_more { - let more = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - more, - true, - 1u32, - )?; - }: _(RawOrigin::Signed(caller.clone()), more) - verify { - let expected_bond = more * 2u32.into(); - assert_eq!( - Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, - expected_bond, - ); - } - - schedule_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk) - verify { - let state = Pallet::::candidate_info(&caller).expect("request bonded less so exists"); - assert_eq!( - state.request, - Some(CandidateBondLessRequest { - amount: min_candidate_stk, - when_executable: 3, - }) - ); - } - - execute_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - Pallet::::schedule_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - min_candidate_stk - )?; - roll_to_and_author::(2, caller.clone()); - }: { - Pallet::::execute_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - caller.clone() - )?; - } verify { - assert_eq!( - Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, - min_candidate_stk, - ); - } - - cancel_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - Pallet::::schedule_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - min_candidate_stk - )?; - }: { - Pallet::::cancel_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - )?; - } verify { - assert!( - Pallet::::candidate_info(&caller).unwrap().request.is_none() - ); - } - - delegate { - let x in 3..<::MaxDelegationsPerDelegator as Get>::get(); - let y in 2..<::MaxTopDelegationsPerCandidate as Get>::get(); - // Worst Case is full of delegations before calling `delegate` - let mut collators: Vec = Vec::new(); - // Initialize MaxDelegationsPerDelegator collator candidates - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - collators.len() as u32 + 1u32, - )?; - collators.push(collator.clone()); - } - let bond = <::MinDelegatorStk as Get>>::get(); - let extra = if (bond * (collators.len() as u32 + 1u32).into()) > min_candidate_stk::() { - (bond * (collators.len() as u32 + 1u32).into()) - min_candidate_stk::() - } else { - 0u32.into() - }; - let (caller, _) = create_funded_user::("caller", USER_SEED, extra); - // Delegation count - let mut del_del_count = 0u32; - // Nominate MaxDelegationsPerDelegators collator candidates - for col in collators.clone() { - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), col, bond, 0u32, del_del_count - )?; - del_del_count += 1u32; - } - // Last collator to be delegated - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - collators.len() as u32 + 1u32, - )?; - // Worst Case Complexity is insertion into an almost full collator - let mut col_del_count = 0u32; - for i in 1..y { - let seed = USER_SEED + i; - let _ = create_funded_delegator::( - "delegator", - seed, - 0u32.into(), - collator.clone(), - true, - col_del_count, - )?; - col_del_count += 1u32; - } - }: _(RawOrigin::Signed(caller.clone()), collator, bond, col_del_count, del_del_count) - verify { - assert!(Pallet::::is_delegator(&caller)); - } - - schedule_leave_delegators { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!( - Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|r| r.delegator == caller && matches!(r.action, DelegationAction::Revoke(_))) - ); - } - - execute_leave_delegators { - let x in 2..<::MaxDelegationsPerDelegator as Get>::get(); - // Worst Case is full of delegations before execute exit - let mut collators: Vec = Vec::new(); - // Initialize MaxDelegationsPerDelegator collator candidates - for i in 1..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - collators.len() as u32 + 1u32 - )?; - collators.push(collator.clone()); - } - let bond = <::MinDelegatorStk as Get>>::get(); - let need = bond * (collators.len() as u32).into(); - let default_minted = min_candidate_stk::(); - let need: BalanceOf = if need > default_minted { - need - default_minted - } else { - 0u32.into() - }; - // Fund the delegator - let (caller, _) = create_funded_user::("caller", USER_SEED, need); - // Delegation count - let mut delegation_count = 0u32; - let author = collators[0].clone(); - // Nominate MaxDelegationsPerDelegators collator candidates - for col in collators { - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), - col, - bond, - 0u32, - delegation_count - )?; - delegation_count += 1u32; - } - Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; - roll_to_and_author::(2, author); - }: _(RawOrigin::Signed(caller.clone()), caller.clone(), delegation_count) - verify { - assert!(Pallet::::delegator_state(&caller).is_none()); - } - - cancel_leave_delegators { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator, - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(Pallet::::delegator_state(&caller).unwrap().is_active()); - } - - schedule_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone()), collator.clone()) - verify { - assert_eq!( - Pallet::::delegation_scheduled_requests(&collator), - vec![ScheduledRequest { - delegator: caller, - when_executable: 3, - action: DelegationAction::Revoke(bond), - }], - ); - } - - delegator_bond_more { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone()), collator, bond) - verify { - let expected_bond = bond * 2u32.into(); - assert_eq!( - Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, - expected_bond, - ); - } - - schedule_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond_less) - verify { - let state = Pallet::::delegator_state(&caller) - .expect("just request bonded less so exists"); - assert_eq!( - Pallet::::delegation_scheduled_requests(&collator), - vec![ScheduledRequest { - delegator: caller, - when_executable: 3, - action: DelegationAction::Decrease(bond_less), - }], - ); - } - - execute_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_revoke_delegation(RawOrigin::Signed( - caller.clone()).into(), - collator.clone() - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::execute_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - caller.clone(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::is_delegator(&caller) - ); - } - - execute_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - Pallet::::schedule_delegator_bond_less( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond_less - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::execute_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - caller.clone(), - collator.clone() - )?; - } verify { - let expected = total - bond_less; - assert_eq!( - Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, - expected, - ); - } - - cancel_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_revoke_delegation( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - }: { - Pallet::::cancel_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|x| x.delegator == caller) - ); - } - - cancel_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - Pallet::::schedule_delegator_bond_less( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond_less - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::cancel_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|x| x.delegator == caller) - ); - } - - // ON_INITIALIZE - - prepare_staking_payouts { - let reward_delay = <::RewardPaymentDelay as Get>::get(); - let round = reward_delay + 2u32; - let payout_round = round - reward_delay; - // may need: - // > - // > - // > - // ensure parachain bond account exists so that deposit_into_existing succeeds - >::insert(payout_round, 100); - >::insert(payout_round, min_candidate_stk::()); - - // set an account in the bond config so that we will measure the payout to it - let account = create_funded_user::( - "parachain_bond", - 0, - min_candidate_stk::(), - ).0; - >::put(ParachainBondConfig { - account, - percent: Percent::from_percent(50), - }); - - }: { Pallet::::prepare_staking_payouts(round); } - verify { - } - - get_rewardable_delegators { - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators - - let high_inflation: Range = Range { - min: Perbill::one(), - ideal: Perbill::one(), - max: Perbill::one(), - }; - Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation)?; - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; - Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; - - let collator = create_funded_collator::( - "collator", - 0, - min_candidate_stk::() * 1_000_000u32.into(), - true, - 1, - )?; - - // create delegators - for i in 0..y { - let seed = USER_SEED + i + 1; - let delegator = create_funded_delegator::( - "delegator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - collator.clone(), - true, - i, - )?; - } - - let mut _results = None; - - }: { _results = Some(Pallet::::get_rewardable_delegators(&collator)); } - verify { - let counted_delegations = _results.expect("get_rewardable_delegators returned some results"); - assert!(counted_delegations.uncounted_stake == 0u32.into()); - assert!(counted_delegations.rewardable_delegations.len() as u32 == y); - let top_delegations = >::get(collator.clone()) - .expect("delegations were set for collator through delegate() calls"); - assert!(top_delegations.delegations.len() as u32 == y); - } - - select_top_candidates { - let x in 0..50; // num collators - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators - - let high_inflation: Range = Range { - min: Perbill::one(), - ideal: Perbill::one(), - max: Perbill::one(), - }; - Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation)?; - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 100u32)?; - Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; - - let mut seed = USER_SEED + 1; - - for _ in 0..x { - let collator = create_funded_collator::( - "collator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - true, - 999999, - )?; - seed += 1; - - // create delegators - for _ in 0..y { - let delegator = create_funded_delegator::( - "delegator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - collator.clone(), - true, - 9999999, - )?; - seed += 1; - } - } - - }: { Pallet::::select_top_candidates(1); } - verify { - } - - pay_one_collator_reward { - // y controls number of delegations, its maximum per collator is the max top delegations - let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); - - // must come after 'let foo in 0..` statements for macro - use crate::{ - DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points, - AwardedPts, - }; - - let before_running_round_index = Pallet::::round().current; - let initial_stake_amount = min_candidate_stk::() * 1_000_000u32.into(); - - let mut total_staked = 0u32.into(); - - // initialize our single collator - let sole_collator = create_funded_collator::( - "collator", - 0, - initial_stake_amount, - true, - 1u32, - )?; - total_staked += initial_stake_amount; - - // generate funded collator accounts - let mut delegators: Vec = Vec::new(); - for i in 0..y { - let seed = USER_SEED + i; - let delegator = create_funded_delegator::( - "delegator", - seed, - initial_stake_amount, - sole_collator.clone(), - true, - delegators.len() as u32, - )?; - delegators.push(delegator); - total_staked += initial_stake_amount; - } - - // rather than roll through rounds in order to initialize the storage we want, we set it - // directly and then call pay_one_collator_reward directly. - - let round_for_payout = 5; - >::insert(round_for_payout, DelayedPayout { - // NOTE: round_issuance is not correct here, but it doesn't seem to cause problems - round_issuance: 1000u32.into(), - total_staking_reward: total_staked, - collator_commission: Perbill::from_rational(1u32, 100u32), - }); - - let mut delegations: Vec>> = Vec::new(); - for delegator in &delegators { - delegations.push(BondWithAutoCompound { - owner: delegator.clone(), - amount: 100u32.into(), - auto_compound: Percent::zero(), - }); - } - - >::insert(round_for_payout, &sole_collator, CollatorSnapshot { - bond: 1_000u32.into(), - delegations, - total: 1_000_000u32.into(), - }); - - >::insert(round_for_payout, 100); - >::insert(round_for_payout, &sole_collator, 20); - - }: { - let round_for_payout = 5; - // TODO: this is an extra read right here (we should whitelist it?) - let payout_info = Pallet::::delayed_payouts(round_for_payout).expect("payout expected"); - let result = Pallet::::pay_one_collator_reward(round_for_payout, payout_info); - // TODO: how to keep this in scope so it can be done in verify block? - assert!(matches!(result.0, RewardPayment::Paid)); - } - verify { - // collator should have been paid - assert!( - T::Currency::free_balance(&sole_collator) > initial_stake_amount, - "collator should have been paid in pay_one_collator_reward" - ); - // nominators should have been paid - for delegator in &delegators { - assert!( - T::Currency::free_balance(delegator) > initial_stake_amount, - "delegator should have been paid in pay_one_collator_reward" - ); - } - } - - base_on_initialize { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let start = >::block_number(); - parachain_staking_on_finalize::(collator); - >::on_finalize(start); - >::set_block_number( - start + 1u32.into() - ); - let end = >::block_number(); - >::on_initialize(end); - }: { Pallet::::on_initialize(end); } - verify { - // Round transitions - assert_eq!(start + 1u32.into(), end); - } - - set_auto_compound { - // x controls number of distinct auto-compounding delegations the prime collator will have - // y controls number of distinct delegations the prime delegator will have - let x in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); - - use crate::auto_compound::AutoCompoundDelegations; - - let min_candidate_stake = min_candidate_stk::(); - let min_delegator_stake = min_delegator_stk::(); - let mut seed = Seed::new(); - - // initialize the prime collator - let prime_candidate = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - 1, - )?; - - // initialize the prime delegator - let prime_delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake * (y+1).into(), - prime_candidate.clone(), - true, - 0, - )?; - - // have x-1 distinct auto-compounding delegators delegate to prime collator - // we directly set the storage, since benchmarks don't work when the same extrinsic is - // called from within the benchmark. - let mut auto_compounding_state = >::get_storage(&prime_candidate); - for i in 1..x { - let delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake, - prime_candidate.clone(), - true, - i, - )?; - auto_compounding_state.set_for_delegator( - delegator, - Percent::from_percent(100), - ); - } - auto_compounding_state.set_storage(&prime_candidate); - - // delegate to y-1 distinct collators from the prime delegator - for i in 1..y { - let collator = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - i+1, - )?; - Pallet::::delegate( - RawOrigin::Signed(prime_delegator.clone()).into(), - collator, - min_delegator_stake, - 0, - i, - )?; - } - }: { - Pallet::::set_auto_compound( - RawOrigin::Signed(prime_delegator.clone()).into(), - prime_candidate.clone(), - Percent::from_percent(50), - x, - y+1, - )?; - } - verify { - let actual_auto_compound = >::get_storage(&prime_candidate) - .get_for_delegator(&prime_delegator); - let expected_auto_compound = Some(Percent::from_percent(50)); - assert_eq!( - expected_auto_compound, - actual_auto_compound, - "delegation must have an auto-compound entry", - ); - } - - delegate_with_auto_compound { - // x controls number of distinct delegations the prime collator will have - // y controls number of distinct auto-compounding delegations the prime collator will have - // z controls number of distinct delegations the prime delegator will have - let x in 0..(<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get()); - let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get(); - let z in 0..<::MaxDelegationsPerDelegator as Get>::get(); - - use crate::auto_compound::AutoCompoundDelegations; - - let min_candidate_stake = min_candidate_stk::(); - let min_delegator_stake = min_delegator_stk::(); - let mut seed = Seed::new(); - - // initialize the prime collator - let prime_candidate = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - 1, - )?; - - // initialize the future delegator - let (prime_delegator, _) = create_funded_user::( - "delegator", - seed.take(), - min_delegator_stake * (z+1).into(), - ); - - // have x-1 distinct delegators delegate to prime collator, of which y are auto-compounding. - // we can directly set the storage here. - let auto_compound_z = x * y / 100; - for i in 1..x { - let delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake, - prime_candidate.clone(), - true, - i, - )?; - if i <= y { - Pallet::::set_auto_compound( - RawOrigin::Signed(delegator.clone()).into(), - prime_candidate.clone(), - Percent::from_percent(100), - i+1, - i, - )?; - } - } - - // delegate to z-1 distinct collators from the prime delegator - for i in 1..z { - let collator = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - i+1, - )?; - Pallet::::delegate( - RawOrigin::Signed(prime_delegator.clone()).into(), - collator, - min_delegator_stake, - 0, - i, - )?; - } - }: { - Pallet::::delegate_with_auto_compound( - RawOrigin::Signed(prime_delegator.clone()).into(), - prime_candidate.clone(), - min_delegator_stake, - Percent::from_percent(50), - x, - y, - z, - )?; - } - verify { - assert!(Pallet::::is_delegator(&prime_delegator)); - let actual_auto_compound = >::get_storage(&prime_candidate) - .get_for_delegator(&prime_delegator); - let expected_auto_compound = Some(Percent::from_percent(50)); - assert_eq!( - expected_auto_compound, - actual_auto_compound, - "delegation must have an auto-compound entry", - ); - } - - mint_collator_reward { - let mut seed = Seed::new(); - let collator = create_funded_collator::( - "collator", - seed.take(), - 0u32.into(), - true, - 1, - )?; - let original_free_balance = T::Currency::free_balance(&collator); - }: { - Pallet::::mint_collator_reward(1u32, collator.clone(), 50u32.into()) - } - verify { - assert_eq!(T::Currency::free_balance(&collator), original_free_balance + 50u32.into()); - } -} - -#[cfg(test)] -mod tests { - use crate::{benchmarks::*, mock::Test}; - use frame_support::assert_ok; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t) - } - - #[test] - fn bench_set_staking_expectations() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_staking_expectations()); - }); - } - - #[test] - fn bench_set_inflation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_inflation()); - }); - } - - #[test] - fn bench_set_parachain_bond_account() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_parachain_bond_account()); - }); - } - - #[test] - fn bench_set_parachain_bond_reserve_percent() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_parachain_bond_reserve_percent()); - }); - } - - #[test] - fn bench_set_total_selected() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_total_selected()); - }); - } - - #[test] - fn bench_set_collator_commission() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_collator_commission()); - }); - } - - #[test] - fn bench_set_blocks_per_round() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_blocks_per_round()); - }); - } - - #[test] - fn bench_join_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_join_candidates()); - }); - } - - #[test] - fn bench_schedule_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_leave_candidates()); - }); - } - - #[test] - fn bench_execute_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_leave_candidates()); - }); - } - - #[test] - fn bench_cancel_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_leave_candidates()); - }); - } - - #[test] - fn bench_go_offline() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_go_offline()); - }); - } - - #[test] - fn bench_go_online() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_go_online()); - }); - } - - #[test] - fn bench_candidate_bond_more() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_candidate_bond_more()); - }); - } - - #[test] - fn bench_schedule_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_candidate_bond_less()); - }); - } - - #[test] - fn bench_execute_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_candidate_bond_less()); - }); - } - - #[test] - fn bench_cancel_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_candidate_bond_less()); - }); - } - - #[test] - fn bench_delegate() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_delegate()); - }); - } - - #[test] - fn bench_schedule_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_leave_delegators()); - }); - } - - #[test] - fn bench_execute_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_leave_delegators()); - }); - } - - #[test] - fn bench_cancel_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_leave_delegators()); - }); - } - - #[test] - fn bench_schedule_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_revoke_delegation()); - }); - } - - #[test] - fn bench_delegator_bond_more() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_delegator_bond_more()); - }); - } - - #[test] - fn bench_schedule_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_delegator_bond_less()); - }); - } - - #[test] - fn bench_execute_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_revoke_delegation()); - }); - } - - #[test] - fn bench_execute_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_delegator_bond_less()); - }); - } - - #[test] - fn bench_cancel_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_revoke_delegation()); - }); - } - - #[test] - fn bench_cancel_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_delegator_bond_less()); - }); - } - - #[test] - fn bench_base_on_initialize() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_base_on_initialize()); - }); - } -} - -impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Test); diff --git a/external/pallets/parachain-staking/src/delegation_requests.rs b/external/pallets/parachain-staking/src/delegation_requests.rs deleted file mode 100644 index ce454a3aa..000000000 --- a/external/pallets/parachain-staking/src/delegation_requests.rs +++ /dev/null @@ -1,647 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Scheduled requests functionality for delegators - -use crate::{ - auto_compound::AutoCompoundDelegations, - pallet::{ - BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, - Event, Pallet, Round, RoundIndex, Total, - }, - Delegator, DelegatorStatus, -}; -use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_runtime::traits::Saturating; -use sp_std::{vec, vec::Vec}; - -/// An action that can be performed upon a delegation -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] -pub enum DelegationAction { - Revoke(Balance), - Decrease(Balance), -} - -impl DelegationAction { - /// Returns the wrapped amount value. - pub fn amount(&self) -> Balance { - match self { - DelegationAction::Revoke(amount) => *amount, - DelegationAction::Decrease(amount) => *amount, - } - } -} - -/// Represents a scheduled request that define a [DelegationAction]. The request is executable -/// iff the provided [RoundIndex] is achieved. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] -pub struct ScheduledRequest { - pub delegator: AccountId, - pub when_executable: RoundIndex, - pub action: DelegationAction, -} - -/// Represents a cancelled scheduled request for emitting an event. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct CancelledScheduledRequest { - pub when_executable: RoundIndex, - pub action: DelegationAction, -} - -impl From> for CancelledScheduledRequest { - fn from(request: ScheduledRequest) -> Self { - CancelledScheduledRequest { - when_executable: request.when_executable, - action: request.action, - } - } -} - -impl Pallet { - /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. - pub(crate) fn delegation_schedule_revoke( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - ensure!( - !scheduled_requests.iter().any(|req| req.delegator == delegator), - >::PendingDelegationRequestAlreadyExists, - ); - - let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; - let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); - scheduled_requests.push(ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Revoke(bonded_amount), - when_executable: when, - }); - state.less_total = state.less_total.saturating_add(bonded_amount); - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::DelegationRevocationScheduled { - round: now, - delegator, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Schedules a [DelegationAction::Decrease] for the delegator, towards a given collator. - pub(crate) fn delegation_schedule_bond_decrease( - collator: T::AccountId, - delegator: T::AccountId, - decrease_amount: BalanceOf, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - ensure!( - !scheduled_requests.iter().any(|req| req.delegator == delegator), - >::PendingDelegationRequestAlreadyExists, - ); - - let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; - ensure!(bonded_amount > decrease_amount, >::DelegatorBondBelowMin); - let new_amount: BalanceOf = bonded_amount - decrease_amount; - ensure!(new_amount >= T::MinDelegation::get(), >::DelegationBelowMin); - - // Net Total is total after pending orders are executed - let net_total = state.total().saturating_sub(state.less_total); - // Net Total is always >= MinDelegatorStk - let max_subtracted_amount = net_total.saturating_sub(T::MinDelegatorStk::get()); - ensure!(decrease_amount <= max_subtracted_amount, >::DelegatorBondBelowMin); - - let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); - scheduled_requests.push(ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Decrease(decrease_amount), - when_executable: when, - }); - state.less_total = state.less_total.saturating_add(decrease_amount); - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::DelegationDecreaseScheduled { - delegator, - candidate: collator, - amount_to_decrease: decrease_amount, - execute_round: when, - }); - Ok(().into()) - } - - /// Cancels the delegator's existing [ScheduledRequest] towards a given collator. - pub(crate) fn delegation_cancel_request( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) - .ok_or(>::PendingDelegationRequestDNE)?; - - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::CancelledDelegationRequest { - delegator, - collator, - cancelled_request: request.into(), - }); - Ok(().into()) - } - - fn cancel_request_with_state( - delegator: &T::AccountId, - state: &mut Delegator>, - scheduled_requests: &mut Vec>>, - ) -> Option>> { - let request_idx = scheduled_requests.iter().position(|req| &req.delegator == delegator)?; - - let request = scheduled_requests.remove(request_idx); - let amount = request.action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - Some(request) - } - - /// Executes the delegator's existing [ScheduledRequest] towards a given collator. - pub(crate) fn delegation_execute_scheduled_request( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - let request_idx = scheduled_requests - .iter() - .position(|req| req.delegator == delegator) - .ok_or(>::PendingDelegationRequestDNE)?; - let request = &scheduled_requests[request_idx]; - - let now = >::get().current; - ensure!(request.when_executable <= now, >::PendingDelegationRequestNotDueYet); - - match request.action { - DelegationAction::Revoke(amount) => { - // revoking last delegation => leaving set of delegators - let leaving = if state.delegations.0.len() == 1usize { - true - } else { - ensure!( - state.total().saturating_sub(T::MinDelegatorStk::get()) >= amount, - >::DelegatorBondBelowMin - ); - false - }; - - // remove from pending requests - let amount = scheduled_requests.remove(request_idx).action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - - // remove delegation from delegator state - state.rm_delegation::(&collator); - - // remove delegation from auto-compounding info - >::remove_auto_compound(&collator, &delegator); - - // remove delegation from collator state delegations - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), amount)?; - Self::deposit_event(Event::DelegationRevoked { - delegator: delegator.clone(), - candidate: collator.clone(), - unstaked_amount: amount, - }); - - >::insert(collator, scheduled_requests); - if leaving { - >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { - delegator, - unstaked_amount: amount, - }); - } else { - >::insert(&delegator, state); - } - Ok(().into()) - } - DelegationAction::Decrease(_) => { - // remove from pending requests - let amount = scheduled_requests.remove(request_idx).action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - - // decrease delegation - for bond in &mut state.delegations.0 { - if bond.owner == collator { - return if bond.amount > amount { - let amount_before: BalanceOf = bond.amount; - bond.amount = bond.amount.saturating_sub(amount); - let mut collator_info = >::get(&collator) - .ok_or(>::CandidateDNE)?; - - state.total_sub_if::(amount, |total| { - let new_total: BalanceOf = total; - ensure!( - new_total >= T::MinDelegation::get(), - >::DelegationBelowMin - ); - ensure!( - new_total >= T::MinDelegatorStk::get(), - >::DelegatorBondBelowMin - ); - - Ok(()) - })?; - - // need to go into decrease_delegation - let in_top = collator_info.decrease_delegation::( - &collator, - delegator.clone(), - amount_before, - amount, - )?; - >::insert(&collator, collator_info); - let new_total_staked = >::get().saturating_sub(amount); - >::put(new_total_staked); - - >::insert( - collator.clone(), - scheduled_requests, - ); - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegationDecreased { - delegator, - candidate: collator.clone(), - amount, - in_top, - }); - Ok(().into()) - } else { - // must rm entire delegation if bond.amount <= less or cancel request - Err(>::DelegationBelowMin.into()) - }; - } - } - Err(>::DelegationDNE.into()) - } - } - } - - /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. - /// The last fulfilled request causes the delegator to leave the set of delegators. - pub(crate) fn delegator_schedule_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut updated_scheduled_requests = vec![]; - let now = >::get().current; - let when = now.saturating_add(T::LeaveDelegatorsDelay::get()); - - // lazy migration for DelegatorStatus::Leaving - #[allow(deprecated)] - if matches!(state.status, DelegatorStatus::Leaving(_)) { - state.status = DelegatorStatus::Active; - >::insert(delegator.clone(), state.clone()); - } - - // it is assumed that a multiple delegations to the same collator does not exist, else this - // will cause a bug - the last duplicate delegation update will be the only one applied. - let mut existing_revoke_count = 0; - for bond in state.delegations.0.clone() { - let collator = bond.owner; - let bonded_amount = bond.amount; - let mut scheduled_requests = >::get(&collator); - - // cancel any existing requests - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); - let request = match request { - Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { - existing_revoke_count += 1; - revoke_req // re-insert the same Revoke request - } - _ => ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Revoke(bonded_amount), - when_executable: when, - }, - }; - - scheduled_requests.push(request); - state.less_total = state.less_total.saturating_add(bonded_amount); - updated_scheduled_requests.push((collator, scheduled_requests)); - } - - if existing_revoke_count == state.delegations.0.len() { - return Err(>::DelegatorAlreadyLeaving.into()); - } - - updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitScheduled { - round: now, - delegator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. - /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be - /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_cancel_scheduled_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut updated_scheduled_requests = vec![]; - - // backwards compatible handling for DelegatorStatus::Leaving - #[allow(deprecated)] - if matches!(state.status, DelegatorStatus::Leaving(_)) { - state.status = DelegatorStatus::Active; - >::insert(delegator.clone(), state.clone()); - Self::deposit_event(Event::DelegatorExitCancelled { delegator }); - return Ok(().into()); - } - - // pre-validate that all delegations have a Revoke request. - for bond in &state.delegations.0 { - let collator = bond.owner.clone(); - let scheduled_requests = >::get(&collator); - scheduled_requests - .iter() - .find(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - .ok_or(>::DelegatorNotLeaving)?; - } - - // cancel all requests - for bond in state.delegations.0.clone() { - let collator = bond.owner.clone(); - let mut scheduled_requests = >::get(&collator); - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); - updated_scheduled_requests.push((collator, scheduled_requests)); - } - - updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitCancelled { delegator }); - - Ok(().into()) - } - - /// Executes every [DelegationAction::Revoke] request for a delegator towards a collator. - /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be - /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_execute_scheduled_revoke_all( - delegator: T::AccountId, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - ensure!( - delegation_count >= (state.delegations.0.len() as u32), - Error::::TooLowDelegationCountToLeaveDelegators - ); - let now = >::get().current; - - // backwards compatible handling for DelegatorStatus::Leaving - #[allow(deprecated)] - if let DelegatorStatus::Leaving(when) = state.status { - ensure!(>::get().current >= when, Error::::DelegatorCannotLeaveYet); - - for bond in state.delegations.0.clone() { - if let Err(error) = Self::delegator_leaves_candidate( - bond.owner.clone(), - delegator.clone(), - bond.amount, - ) { - log::warn!( - "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", - error - ); - } - - Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); - >::remove_auto_compound(&bond.owner, &delegator); - } - >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { delegator, unstaked_amount: state.total }); - return Ok(().into()); - } - - let mut validated_scheduled_requests = vec![]; - // pre-validate that all delegations have a Revoke request that can be executed now. - for bond in &state.delegations.0 { - let scheduled_requests = >::get(&bond.owner); - let request_idx = scheduled_requests - .iter() - .position(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - .ok_or(>::DelegatorNotLeaving)?; - let request = &scheduled_requests[request_idx]; - - ensure!(request.when_executable <= now, >::DelegatorCannotLeaveYet); - - validated_scheduled_requests.push((bond.clone(), scheduled_requests, request_idx)) - } - - let mut updated_scheduled_requests = vec![]; - // we do not update the delegator state, since the it will be completely removed - for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { - let collator = bond.owner; - - if let Err(error) = - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) - { - log::warn!( - "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", - delegator, - error - ); - } - - // remove the scheduled request, since it is fulfilled - scheduled_requests.remove(request_idx).action.amount(); - updated_scheduled_requests.push((collator.clone(), scheduled_requests)); - - // remove the auto-compounding entry for the delegation - >::remove_auto_compound(&collator, &delegator); - } - - // set state.total so that state.adjust_bond_lock will remove lock - let unstaked_amount = state.total(); - state.total_sub::(unstaked_amount)?; - - updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - Self::deposit_event(Event::DelegatorLeft { delegator: delegator.clone(), unstaked_amount }); - >::remove(&delegator); - - Ok(().into()) - } - - /// Removes the delegator's existing [ScheduledRequest] towards a given collator, if exists. - /// The state needs to be persisted by the caller of this function. - pub(crate) fn delegation_remove_request_with_state( - collator: &T::AccountId, - delegator: &T::AccountId, - state: &mut Delegator>, - ) { - let mut scheduled_requests = >::get(collator); - - let maybe_request_idx = - scheduled_requests.iter().position(|req| &req.delegator == delegator); - - if let Some(request_idx) = maybe_request_idx { - let request = scheduled_requests.remove(request_idx); - let amount = request.action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - >::insert(collator, scheduled_requests); - } - } - - /// Returns true if a [ScheduledRequest] exists for a given delegation - pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { - >::get(collator) - .iter() - .any(|req| &req.delegator == delegator) - } - - /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation - pub fn delegation_request_revoke_exists( - collator: &T::AccountId, - delegator: &T::AccountId, - ) -> bool { - >::get(collator).iter().any(|req| { - &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{mock::Test, set::OrderedSet, Bond}; - - #[test] - fn test_cancel_request_with_state_removes_request_for_correct_delegator_and_updates_state() { - let mut state = Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - }; - let mut scheduled_requests = vec![ - ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }, - ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }, - ]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); - - assert_eq!( - removed_request, - Some(ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }) - ); - assert_eq!( - scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] - ); - assert_eq!( - state, - Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 0, - status: crate::DelegatorStatus::Active, - } - ); - } - - #[test] - fn test_cancel_request_with_state_does_nothing_when_request_does_not_exist() { - let mut state = Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - }; - let mut scheduled_requests = vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); - - assert_eq!(removed_request, None,); - assert_eq!( - scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] - ); - assert_eq!( - state, - Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - } - ); - } -} diff --git a/external/pallets/parachain-staking/src/inflation.rs b/external/pallets/parachain-staking/src/inflation.rs deleted file mode 100644 index d2f7522dd..000000000 --- a/external/pallets/parachain-staking/src/inflation.rs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Helper methods for computing issuance based on inflation -use crate::pallet::{BalanceOf, Config, Pallet}; -use frame_support::traits::Currency; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_runtime::{PerThing, Perbill, RuntimeDebug}; -use substrate_fixed::{transcendental::pow as floatpow, types::I64F64}; - -const SECONDS_PER_YEAR: u32 = 31557600; -const SECONDS_PER_BLOCK: u32 = 12; -pub const BLOCKS_PER_YEAR: u32 = SECONDS_PER_YEAR / SECONDS_PER_BLOCK; - -fn rounds_per_year() -> u32 { - let blocks_per_round = >::round().length; - BLOCKS_PER_YEAR / blocks_per_round -} - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive( - Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, -)] -pub struct Range { - pub min: T, - pub ideal: T, - pub max: T, -} - -impl Range { - pub fn is_valid(&self) -> bool { - self.max >= self.ideal && self.ideal >= self.min - } -} - -impl From for Range { - fn from(other: T) -> Range { - Range { min: other, ideal: other, max: other } - } -} -/// Convert an annual inflation to a round inflation -/// round = (1+annual)^(1/rounds_per_year) - 1 -pub fn perbill_annual_to_perbill_round( - annual: Range, - rounds_per_year: u32, -) -> Range { - let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); - let annual_to_round = |annual: Perbill| -> Perbill { - let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); - let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) - .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); - Perbill::from_parts( - ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) - .ceil() - .to_num::(), - ) - }; - Range { - min: annual_to_round(annual.min), - ideal: annual_to_round(annual.ideal), - max: annual_to_round(annual.max), - } -} -/// Convert annual inflation rate range to round inflation range -pub fn annual_to_round(annual: Range) -> Range { - let periods = rounds_per_year::(); - perbill_annual_to_perbill_round(annual, periods) -} - -/// Compute round issuance range from round inflation range and current total issuance -pub fn round_issuance_range(round: Range) -> Range> { - let circulating = T::Currency::total_issuance(); - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } -} - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct InflationInfo { - /// Staking expectations - pub expect: Range, - /// Annual inflation range - pub annual: Range, - /// Round inflation range - pub round: Range, -} - -impl InflationInfo { - pub fn new( - annual: Range, - expect: Range, - ) -> InflationInfo { - InflationInfo { expect, annual, round: annual_to_round::(annual) } - } - /// Set round inflation range according to input annual inflation range - pub fn set_round_from_annual(&mut self, new: Range) { - self.round = annual_to_round::(new); - } - /// Reset round inflation rate based on changes to round length - pub fn reset_round(&mut self, new_length: u32) { - let periods = BLOCKS_PER_YEAR / new_length; - self.round = perbill_annual_to_perbill_round(self.annual, periods); - } - /// Set staking expectations - pub fn set_expectations(&mut self, expect: Range) { - self.expect = expect; - } -} - -#[cfg(test)] -mod tests { - use super::*; - fn mock_annual_to_round(annual: Range, rounds_per_year: u32) -> Range { - perbill_annual_to_perbill_round(annual, rounds_per_year) - } - fn mock_round_issuance_range( - // Total circulating before minting - circulating: u128, - // Round inflation range - round: Range, - ) -> Range { - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } - } - #[test] - fn simple_issuance_conversion() { - // 5% inflation for 10_000_0000 = 500,000 minted over the year - // let's assume there are 10 periods in a year - // => mint 500_000 over 10 periods => 50_000 minted per period - let expected_round_issuance_range: Range = - Range { min: 48_909, ideal: 48_909, max: 48_909 }; - let schedule = Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_issuance_range, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) - ); - } - #[test] - fn range_issuance_conversion() { - // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year - // let's assume there are 10 periods in a year - // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period - let expected_round_issuance_range: Range = - Range { min: 29_603, ideal: 39298, max: 48_909 }; - let schedule = Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_issuance_range, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) - ); - } - #[test] - fn expected_parameterization() { - let expected_round_schedule: Range = Range { min: 45, ideal: 56, max: 56 }; - let schedule = Range { - min: Perbill::from_percent(4), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_schedule, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) - ); - } - #[test] - fn inflation_does_not_panic_at_round_number_limit() { - let schedule = Range { - min: Perbill::from_percent(100), - ideal: Perbill::from_percent(100), - max: Perbill::from_percent(100), - }; - mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u128::MAX, mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1)); - mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1)); - mock_round_issuance_range(u128::MAX, mock_annual_to_round(schedule, 1)); - } -} diff --git a/external/pallets/parachain-staking/src/lib.rs b/external/pallets/parachain-staking/src/lib.rs deleted file mode 100644 index 6da9321ec..000000000 --- a/external/pallets/parachain-staking/src/lib.rs +++ /dev/null @@ -1,1850 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! # Parachain Staking -//! Minimal staking pallet that implements collator selection by total backed stake. -//! The main difference between this pallet and `frame/pallet-staking` is that this pallet -//! uses direct delegation. Delegators choose exactly who they delegate and with what stake. -//! This is different from `frame/pallet-staking` where delegators approval vote and run Phragmen. -//! -//! ### Rules -//! There is a new round every `>::get().length` blocks. -//! -//! At the start of every round, -//! * issuance is calculated for collators (and their delegators) for block authoring -//! `T::RewardPaymentDelay` rounds ago -//! * a new set of collators is chosen from the candidates -//! -//! Immediately following a round change, payments are made once-per-block until all payments have -//! been made. In each such block, one collator is chosen for a rewards payment and is paid along -//! with each of its top `T::MaxTopDelegationsPerCandidate` delegators. -//! -//! To join the set of candidates, call `join_candidates` with `bond >= MinCandidateStk`. -//! To leave the set of candidates, call `schedule_leave_candidates`. If the call succeeds, -//! the collator is removed from the pool of candidates so they cannot be selected for future -//! collator sets, but they are not unbonded until their exit request is executed. Any signed -//! account may trigger the exit `T::LeaveCandidatesDelay` rounds after the round in which the -//! original request was made. -//! -//! To join the set of delegators, call `delegate` and pass in an account that is -//! already a collator candidate and `bond >= MinDelegatorStk`. Each delegator can delegate up to -//! `T::MaxDelegationsPerDelegator` collator candidates by calling `delegate`. -//! -//! To revoke a delegation, call `revoke_delegation` with the collator candidate's account. -//! To leave the set of delegators and revoke all delegations, call `leave_delegators`. - -#![cfg_attr(not(feature = "std"), no_std)] -#![allow(clippy::type_complexity)] - -mod auto_compound; -mod delegation_requests; -pub mod inflation; -pub mod migrations; -pub mod traits; -pub mod types; -pub mod weights; - -#[cfg(any(test, feature = "runtime-benchmarks"))] -mod benchmarks; -#[cfg(test)] -mod mock; -mod set; -#[cfg(test)] -mod tests; - -use frame_support::pallet; -pub use inflation::{InflationInfo, Range}; -use weights::WeightInfo; - -pub use auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}; -pub use delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}; -pub use pallet::*; -pub use traits::*; -pub use types::*; -pub use RoundIndex; - -#[pallet] -pub mod pallet { - use crate::{ - delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, - set::OrderedSet, - traits::*, - types::*, - AutoCompoundConfig, AutoCompoundDelegations, InflationInfo, Range, WeightInfo, - }; - use frame_support::{ - pallet_prelude::*, - traits::{ - tokens::WithdrawReasons, Currency, Get, Imbalance, LockIdentifier, LockableCurrency, - ReservableCurrency, - }, - }; - use frame_system::pallet_prelude::*; - use sp_runtime::{ - traits::{Saturating, Zero}, - Perbill, Percent, - }; - use sp_std::{collections::btree_map::BTreeMap, prelude::*}; - - /// Pallet for parachain staking - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - pub type RoundIndex = u32; - type RewardPoint = u32; - pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; - - pub const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol"; - pub const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel"; - - /// Configuration trait of this pallet. - #[pallet::config] - pub trait Config: frame_system::Config { - /// Overarching event type - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// The currency type - type Currency: Currency - + ReservableCurrency - + LockableCurrency; - /// The origin for monetary governance - type MonetaryGovernanceOrigin: EnsureOrigin; - /// Minimum number of blocks per round - #[pallet::constant] - type MinBlocksPerRound: Get; - /// Number of rounds that candidates remain bonded before exit request is executable - #[pallet::constant] - type LeaveCandidatesDelay: Get; - /// Number of rounds candidate requests to decrease self-bond must wait to be executable - #[pallet::constant] - type CandidateBondLessDelay: Get; - /// Number of rounds that delegators remain bonded before exit request is executable - #[pallet::constant] - type LeaveDelegatorsDelay: Get; - /// Number of rounds that delegations remain bonded before revocation request is executable - #[pallet::constant] - type RevokeDelegationDelay: Get; - /// Number of rounds that delegation less requests must wait before executable - #[pallet::constant] - type DelegationBondLessDelay: Get; - /// Number of rounds after which block authors are rewarded - #[pallet::constant] - type RewardPaymentDelay: Get; - /// Minimum number of selected candidates every round - #[pallet::constant] - type MinSelectedCandidates: Get; - /// Maximum top delegations counted per candidate - #[pallet::constant] - type MaxTopDelegationsPerCandidate: Get; - /// Maximum bottom delegations (not counted) per candidate - #[pallet::constant] - type MaxBottomDelegationsPerCandidate: Get; - /// Maximum delegations per delegator - #[pallet::constant] - type MaxDelegationsPerDelegator: Get; - /// Minimum stake required for any candidate to be in `SelectedCandidates` for the round - #[pallet::constant] - type MinCollatorStk: Get>; - /// Minimum stake required for any account to be a collator candidate - #[pallet::constant] - type MinCandidateStk: Get>; - /// Minimum stake for any registered on-chain account to delegate - #[pallet::constant] - type MinDelegation: Get>; - /// Minimum stake for any registered on-chain account to be a delegator - #[pallet::constant] - type MinDelegatorStk: Get>; - /// Get the current block author - type BlockAuthor: Get; - /// Handler to notify the runtime when a collator is paid. - /// If you don't need it, you can specify the type `()`. - type OnCollatorPayout: OnCollatorPayout>; - /// Handler to distribute a collator's reward. - /// To use the default implementation of minting rewards, specify the type `()`. - type PayoutCollatorReward: PayoutCollatorReward; - /// Handler to notify the runtime when a new round begin. - /// If you don't need it, you can specify the type `()`. - type OnNewRound: OnNewRound; - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - } - - #[pallet::error] - pub enum Error { - DelegatorDNE, - DelegatorDNEinTopNorBottom, - DelegatorDNEInDelegatorSet, - CandidateDNE, - DelegationDNE, - DelegatorExists, - CandidateExists, - CandidateBondBelowMin, - InsufficientBalance, - DelegatorBondBelowMin, - DelegationBelowMin, - AlreadyOffline, - AlreadyActive, - DelegatorAlreadyLeaving, - DelegatorNotLeaving, - DelegatorCannotLeaveYet, - CannotDelegateIfLeaving, - CandidateAlreadyLeaving, - CandidateNotLeaving, - CandidateCannotLeaveYet, - CannotGoOnlineIfLeaving, - ExceedMaxDelegationsPerDelegator, - AlreadyDelegatedCandidate, - InvalidSchedule, - CannotSetBelowMin, - RoundLengthMustBeGreaterThanTotalSelectedCollators, - NoWritingSameValue, - TooLowCandidateCountWeightHintJoinCandidates, - TooLowCandidateCountWeightHintCancelLeaveCandidates, - TooLowCandidateCountToLeaveCandidates, - TooLowDelegationCountToDelegate, - TooLowCandidateDelegationCountToDelegate, - TooLowCandidateDelegationCountToLeaveCandidates, - TooLowDelegationCountToLeaveDelegators, - PendingCandidateRequestsDNE, - PendingCandidateRequestAlreadyExists, - PendingCandidateRequestNotDueYet, - PendingDelegationRequestDNE, - PendingDelegationRequestAlreadyExists, - PendingDelegationRequestNotDueYet, - CannotDelegateLessThanOrEqualToLowestBottomWhenFull, - PendingDelegationRevoke, - TooLowDelegationCountToAutoCompound, - TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - TooLowCandidateAutoCompoundingDelegationCountToDelegate, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// Started new round. - NewRound { - starting_block: T::BlockNumber, - round: RoundIndex, - selected_collators_number: u32, - total_balance: BalanceOf, - }, - /// Account joined the set of collator candidates. - JoinedCollatorCandidates { - account: T::AccountId, - amount_locked: BalanceOf, - new_total_amt_locked: BalanceOf, - }, - /// Candidate selected for collators. Total Exposed Amount includes all delegations. - CollatorChosen { - round: RoundIndex, - collator_account: T::AccountId, - total_exposed_amount: BalanceOf, - }, - /// Candidate requested to decrease a self bond. - CandidateBondLessRequested { - candidate: T::AccountId, - amount_to_decrease: BalanceOf, - execute_round: RoundIndex, - }, - /// Candidate has increased a self bond. - CandidateBondedMore { - candidate: T::AccountId, - amount: BalanceOf, - new_total_bond: BalanceOf, - }, - /// Candidate has decreased a self bond. - CandidateBondedLess { - candidate: T::AccountId, - amount: BalanceOf, - new_bond: BalanceOf, - }, - /// Candidate temporarily leave the set of collator candidates without unbonding. - CandidateWentOffline { candidate: T::AccountId }, - /// Candidate rejoins the set of collator candidates. - CandidateBackOnline { candidate: T::AccountId }, - /// Candidate has requested to leave the set of candidates. - CandidateScheduledExit { - exit_allowed_round: RoundIndex, - candidate: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Cancelled request to leave the set of candidates. - CancelledCandidateExit { candidate: T::AccountId }, - /// Cancelled request to decrease candidate's bond. - CancelledCandidateBondLess { - candidate: T::AccountId, - amount: BalanceOf, - execute_round: RoundIndex, - }, - /// Candidate has left the set of candidates. - CandidateLeft { - ex_candidate: T::AccountId, - unlocked_amount: BalanceOf, - new_total_amt_locked: BalanceOf, - }, - /// Delegator requested to decrease a bond for the collator candidate. - DelegationDecreaseScheduled { - delegator: T::AccountId, - candidate: T::AccountId, - amount_to_decrease: BalanceOf, - execute_round: RoundIndex, - }, - // Delegation increased. - DelegationIncreased { - delegator: T::AccountId, - candidate: T::AccountId, - amount: BalanceOf, - in_top: bool, - }, - // Delegation decreased. - DelegationDecreased { - delegator: T::AccountId, - candidate: T::AccountId, - amount: BalanceOf, - in_top: bool, - }, - /// Delegator requested to leave the set of delegators. - DelegatorExitScheduled { - round: RoundIndex, - delegator: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Delegator requested to revoke delegation. - DelegationRevocationScheduled { - round: RoundIndex, - delegator: T::AccountId, - candidate: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Delegator has left the set of delegators. - DelegatorLeft { delegator: T::AccountId, unstaked_amount: BalanceOf }, - /// Delegation revoked. - DelegationRevoked { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Delegation kicked. - DelegationKicked { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Cancelled a pending request to exit the set of delegators. - DelegatorExitCancelled { delegator: T::AccountId }, - /// Cancelled request to change an existing delegation. - CancelledDelegationRequest { - delegator: T::AccountId, - cancelled_request: CancelledScheduledRequest>, - collator: T::AccountId, - }, - /// New delegation (increase of the existing one). - Delegation { - delegator: T::AccountId, - locked_amount: BalanceOf, - candidate: T::AccountId, - delegator_position: DelegatorAdded>, - auto_compound: Percent, - }, - /// Delegation from candidate state has been remove. - DelegatorLeftCandidate { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - total_candidate_staked: BalanceOf, - }, - /// Paid the account (delegator or collator) the balance as liquid rewards. - Rewarded { account: T::AccountId, rewards: BalanceOf }, - /// Transferred to account which holds funds reserved for parachain bond. - ReservedForParachainBond { account: T::AccountId, value: BalanceOf }, - /// Account (re)set for parachain bond treasury. - ParachainBondAccountSet { old: T::AccountId, new: T::AccountId }, - /// Percent of inflation reserved for parachain bond (re)set. - ParachainBondReservePercentSet { old: Percent, new: Percent }, - /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) - InflationSet { - annual_min: Perbill, - annual_ideal: Perbill, - annual_max: Perbill, - round_min: Perbill, - round_ideal: Perbill, - round_max: Perbill, - }, - /// Staking expectations set. - StakeExpectationsSet { - expect_min: BalanceOf, - expect_ideal: BalanceOf, - expect_max: BalanceOf, - }, - /// Set total selected candidates to this value. - TotalSelectedSet { old: u32, new: u32 }, - /// Set collator commission to this value. - CollatorCommissionSet { old: Perbill, new: Perbill }, - /// Set blocks per round - BlocksPerRoundSet { - current_round: RoundIndex, - first_block: T::BlockNumber, - old: u32, - new: u32, - new_per_round_inflation_min: Perbill, - new_per_round_inflation_ideal: Perbill, - new_per_round_inflation_max: Perbill, - }, - /// Auto-compounding reward percent was set for a delegation. - AutoCompoundSet { candidate: T::AccountId, delegator: T::AccountId, value: Percent }, - /// Compounded a portion of rewards towards the delegation. - Compounded { candidate: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(n: T::BlockNumber) -> Weight { - let mut weight = T::WeightInfo::base_on_initialize(); - - let mut round = >::get(); - if round.should_update(n) { - // mutate round - round.update(n); - // notify that new round begin - weight = weight.saturating_add(T::OnNewRound::on_new_round(round.current)); - // pay all stakers for T::RewardPaymentDelay rounds ago - weight = weight.saturating_add(Self::prepare_staking_payouts(round.current)); - // select top collator candidates for next round - let (extra_weight, collator_count, _delegation_count, total_staked) = - Self::select_top_candidates(round.current); - weight = weight.saturating_add(extra_weight); - // start next round - >::put(round); - // snapshot total stake - >::insert(round.current, >::get()); - Self::deposit_event(Event::NewRound { - starting_block: round.first, - round: round.current, - selected_collators_number: collator_count, - total_balance: total_staked, - }); - // account for Round and Staked writes - weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 2)); - } else { - weight = weight.saturating_add(Self::handle_delayed_payouts(round.current)); - } - - // add on_finalize weight - // read: Author, Points, AwardedPts - // write: Points, AwardedPts - weight = weight.saturating_add(T::DbWeight::get().reads_writes(3, 2)); - weight - } - fn on_finalize(_n: T::BlockNumber) { - Self::award_points_to_block_author(); - } - } - - #[pallet::storage] - #[pallet::getter(fn collator_commission)] - /// Commission percent taken off of rewards for all collators - type CollatorCommission = StorageValue<_, Perbill, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn total_selected)] - /// The total candidates selected every round - pub(crate) type TotalSelected = StorageValue<_, u32, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn parachain_bond_info)] - /// Parachain bond config info { account, percent_of_inflation } - pub(crate) type ParachainBondInfo = - StorageValue<_, ParachainBondConfig, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn round)] - /// Current round index and next round scheduled transition - pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn delegator_state)] - /// Get delegator state associated with an account if account is delegating else None - pub(crate) type DelegatorState = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegator>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn candidate_info)] - /// Get collator candidate info associated with an account if account is candidate else None - pub(crate) type CandidateInfo = - StorageMap<_, Twox64Concat, T::AccountId, CandidateMetadata>, OptionQuery>; - - /// Stores outstanding delegation requests per collator. - #[pallet::storage] - #[pallet::getter(fn delegation_scheduled_requests)] - pub(crate) type DelegationScheduledRequests = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec>>, - ValueQuery, - >; - - /// Stores auto-compounding configuration per collator. - #[pallet::storage] - #[pallet::getter(fn auto_compounding_delegations)] - pub(crate) type AutoCompoundingDelegations = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec>, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn top_delegations)] - /// Top delegations for collator candidate - pub(crate) type TopDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn bottom_delegations)] - /// Bottom delegations for collator candidate - pub(crate) type BottomDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn selected_candidates)] - /// The collator candidates selected for the current round - type SelectedCandidates = StorageValue<_, Vec, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn total)] - /// Total capital locked by this staking pallet - pub(crate) type Total = StorageValue<_, BalanceOf, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn candidate_pool)] - /// The pool of collator candidates, each with their total backing stake - pub(crate) type CandidatePool = - StorageValue<_, OrderedSet>>, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn at_stake)] - /// Snapshot of collator delegation stake at the start of the round - pub type AtStake = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - CollatorSnapshot>, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn delayed_payouts)] - /// Delayed payouts - pub type DelayedPayouts = - StorageMap<_, Twox64Concat, RoundIndex, DelayedPayout>, OptionQuery>; - - #[pallet::storage] - #[pallet::getter(fn staked)] - /// Total counted stake for selected candidates in the round - pub type Staked = StorageMap<_, Twox64Concat, RoundIndex, BalanceOf, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn inflation_config)] - /// Inflation configuration - pub type InflationConfig = StorageValue<_, InflationInfo>, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn points)] - /// Total points awarded to collators for block production in the round - pub type Points = StorageMap<_, Twox64Concat, RoundIndex, RewardPoint, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn awarded_pts)] - /// Points for each collator per round - pub type AwardedPts = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - RewardPoint, - ValueQuery, - >; - - #[pallet::genesis_config] - pub struct GenesisConfig { - /// Initialize balance and register all as collators: `(collator AccountId, balance Amount)` - pub candidates: Vec<(T::AccountId, BalanceOf)>, - /// Initialize balance and make delegations: - /// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding Percent)` - pub delegations: Vec<(T::AccountId, T::AccountId, BalanceOf, Percent)>, - /// Inflation configuration - pub inflation_config: InflationInfo>, - /// Default fixed percent a collator takes off the top of due rewards - pub collator_commission: Perbill, - /// Default percent of inflation set aside for parachain bond every round - pub parachain_bond_reserve_percent: Percent, - /// Default number of blocks in a round - pub blocks_per_round: u32, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - candidates: vec![], - delegations: vec![], - inflation_config: Default::default(), - collator_commission: Default::default(), - parachain_bond_reserve_percent: Default::default(), - blocks_per_round: 1u32, - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - assert!(self.blocks_per_round > 0, "Blocks per round must be > 0"); - >::put(self.inflation_config.clone()); - let mut candidate_count = 0u32; - // Initialize the candidates - for &(ref candidate, balance) in &self.candidates { - assert!( - >::get_collator_stakable_free_balance(candidate) >= balance, - "Account does not have enough balance to bond as a candidate." - ); - if let Err(error) = >::join_candidates( - T::RuntimeOrigin::from(Some(candidate.clone()).into()), - balance, - candidate_count, - ) { - log::warn!("Join candidates failed in genesis with error {:?}", error); - } else { - candidate_count = candidate_count.saturating_add(1u32); - } - } - - let mut col_delegator_count: BTreeMap = BTreeMap::new(); - let mut col_auto_compound_delegator_count: BTreeMap = - BTreeMap::new(); - let mut del_delegation_count: BTreeMap = BTreeMap::new(); - // Initialize the delegations - for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { - assert!( - >::get_delegator_stakable_free_balance(delegator) >= balance, - "Account does not have enough balance to place delegation." - ); - let cd_count = - if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; - let dd_count = - if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; - let cd_auto_compound_count = - col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); - if let Err(error) = >::delegate_with_auto_compound( - T::RuntimeOrigin::from(Some(delegator.clone()).into()), - target.clone(), - balance, - auto_compound, - cd_count, - cd_auto_compound_count, - dd_count, - ) { - log::warn!("Delegate failed in genesis with error {:?}", error); - } else { - if let Some(x) = col_delegator_count.get_mut(target) { - *x = x.saturating_add(1u32); - } else { - col_delegator_count.insert(target.clone(), 1u32); - }; - if let Some(x) = del_delegation_count.get_mut(delegator) { - *x = x.saturating_add(1u32); - } else { - del_delegation_count.insert(delegator.clone(), 1u32); - }; - if !auto_compound.is_zero() { - col_auto_compound_delegator_count - .entry(target.clone()) - .and_modify(|x| *x = x.saturating_add(1)) - .or_insert(1); - } - } - } - // Set collator commission to default config - >::put(self.collator_commission); - // Set parachain bond config to default config - >::put(ParachainBondConfig { - // must be set soon; if not => due inflation will be sent to collators/delegators - account: T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - percent: self.parachain_bond_reserve_percent, - }); - // Set total selected candidates to minimum config - >::put(T::MinSelectedCandidates::get()); - // Choose top TotalSelected collator candidates - let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); - // Start Round 1 at Block 0 - let round: RoundInfo = - RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); - >::put(round); - // Snapshot total stake - >::insert(1u32, >::get()); - >::deposit_event(Event::NewRound { - starting_block: T::BlockNumber::zero(), - round: 1u32, - selected_collators_number: v_count, - total_balance: total_staked, - }); - } - } - - #[pallet::call] - impl Pallet { - #[pallet::weight(::WeightInfo::set_staking_expectations())] - /// Set the expectations for total staked. These expectations determine the issuance for - /// the round according to logic in `fn compute_issuance` - pub fn set_staking_expectations( - origin: OriginFor, - expectations: Range>, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - ensure!(expectations.is_valid(), Error::::InvalidSchedule); - let mut config = >::get(); - ensure!(config.expect != expectations, Error::::NoWritingSameValue); - config.set_expectations(expectations); - Self::deposit_event(Event::StakeExpectationsSet { - expect_min: config.expect.min, - expect_ideal: config.expect.ideal, - expect_max: config.expect.max, - }); - >::put(config); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_inflation())] - /// Set the annual inflation rate to derive per-round inflation - pub fn set_inflation( - origin: OriginFor, - schedule: Range, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - ensure!(schedule.is_valid(), Error::::InvalidSchedule); - let mut config = >::get(); - ensure!(config.annual != schedule, Error::::NoWritingSameValue); - config.annual = schedule; - config.set_round_from_annual::(schedule); - Self::deposit_event(Event::InflationSet { - annual_min: config.annual.min, - annual_ideal: config.annual.ideal, - annual_max: config.annual.max, - round_min: config.round.min, - round_ideal: config.round.ideal, - round_max: config.round.max, - }); - >::put(config); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_parachain_bond_account())] - /// Set the account that will hold funds set aside for parachain bond - pub fn set_parachain_bond_account( - origin: OriginFor, - new: T::AccountId, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - let ParachainBondConfig { account: old, percent } = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(ParachainBondConfig { account: new.clone(), percent }); - Self::deposit_event(Event::ParachainBondAccountSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] - /// Set the percent of inflation set aside for parachain bond - pub fn set_parachain_bond_reserve_percent( - origin: OriginFor, - new: Percent, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - let ParachainBondConfig { account, percent: old } = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(ParachainBondConfig { account, percent: new }); - Self::deposit_event(Event::ParachainBondReservePercentSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_total_selected())] - /// Set the total number of collator candidates selected per round - /// - changes are not applied until the start of the next round - pub fn set_total_selected(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - ensure!(new >= T::MinSelectedCandidates::get(), Error::::CannotSetBelowMin); - let old = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new <= >::get().length, - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - >::put(new); - Self::deposit_event(Event::TotalSelectedSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_collator_commission())] - /// Set the commission for all collators - pub fn set_collator_commission( - origin: OriginFor, - new: Perbill, - ) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - let old = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(new); - Self::deposit_event(Event::CollatorCommissionSet { old, new }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::set_blocks_per_round())] - /// Set blocks per round - /// - if called with `new` less than length of current round, will transition immediately - /// in the next block - /// - also updates per-round inflation config - pub fn set_blocks_per_round(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); - let mut round = >::get(); - let (now, first, old) = (round.current, round.first, round.length); - ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new >= >::get(), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - round.length = new; - // update per-round inflation given new rounds per year - let mut inflation_config = >::get(); - inflation_config.reset_round(new); - >::put(round); - Self::deposit_event(Event::BlocksPerRoundSet { - current_round: now, - first_block: first, - old, - new, - new_per_round_inflation_min: inflation_config.round.min, - new_per_round_inflation_ideal: inflation_config.round.ideal, - new_per_round_inflation_max: inflation_config.round.max, - }); - >::put(inflation_config); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::join_candidates(*candidate_count))] - /// Join the set of collator candidates - pub fn join_candidates( - origin: OriginFor, - bond: BalanceOf, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - ensure!(!Self::is_candidate(&acc), Error::::CandidateExists); - ensure!(!Self::is_delegator(&acc), Error::::DelegatorExists); - ensure!(bond >= T::MinCandidateStk::get(), Error::::CandidateBondBelowMin); - let mut candidates = >::get(); - let old_count = candidates.0.len() as u32; - ensure!( - candidate_count >= old_count, - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - ensure!( - candidates.insert(Bond { owner: acc.clone(), amount: bond }), - Error::::CandidateExists - ); - ensure!( - Self::get_collator_stakable_free_balance(&acc) >= bond, - Error::::InsufficientBalance, - ); - T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); - let candidate = CandidateMetadata::new(bond); - >::insert(&acc, candidate); - let empty_delegations: Delegations> = Default::default(); - // insert empty top delegations - >::insert(&acc, empty_delegations.clone()); - // insert empty bottom delegations - >::insert(&acc, empty_delegations); - >::put(candidates); - let new_total = >::get().saturating_add(bond); - >::put(new_total); - Self::deposit_event(Event::JoinedCollatorCandidates { - account: acc, - amount_locked: bond, - new_total_amt_locked: new_total, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] - /// Request to leave the set of candidates. If successful, the account is immediately - /// removed from the candidate pool to prevent selection as a collator. - pub fn schedule_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let (now, when) = state.schedule_leave::()?; - let mut candidates = >::get(); - ensure!( - candidate_count >= candidates.0.len() as u32, - Error::::TooLowCandidateCountToLeaveCandidates - ); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); - } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateScheduledExit { - exit_allowed_round: now, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) - } - - #[pallet::weight( - ::WeightInfo::execute_leave_candidates(*candidate_delegation_count) - )] - /// Execute leave candidates request - pub fn execute_leave_candidates( - origin: OriginFor, - candidate: T::AccountId, - candidate_delegation_count: u32, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - ensure!( - state.delegation_count <= candidate_delegation_count, - Error::::TooLowCandidateDelegationCountToLeaveCandidates - ); - state.can_leave::()?; - let return_stake = |bond: Bond>| -> DispatchResult { - // remove delegation from delegator state - let mut delegator = DelegatorState::::get(&bond.owner).expect( - "Collator state and delegator state are consistent. - Collator state has a record of this delegation. Therefore, - Delegator state also has a record. qed.", - ); - - if let Some(remaining) = delegator.rm_delegation::(&candidate) { - Self::delegation_remove_request_with_state( - &candidate, - &bond.owner, - &mut delegator, - ); - >::remove_auto_compound(&candidate, &bond.owner); - - if remaining.is_zero() { - // we do not remove the scheduled delegation requests from other collators - // since it is assumed that they were removed incrementally before only the - // last delegation was left. - >::remove(&bond.owner); - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); - } else { - >::insert(&bond.owner, delegator); - } - } else { - // TODO: review. we assume here that this delegator has no remaining staked - // balance, so we ensure the lock is cleared - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); - } - Ok(()) - }; - // total backing stake is at least the candidate self bond - let mut total_backing = state.bond; - // return all top delegations - let top_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in top_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(top_delegations.total); - // return all bottom delegations - let bottom_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in bottom_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(bottom_delegations.total); - // return stake to collator - T::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - let new_total_staked = >::get().saturating_sub(total_backing); - >::put(new_total_staked); - Self::deposit_event(Event::CandidateLeft { - ex_candidate: candidate, - unlocked_amount: total_backing, - new_total_amt_locked: new_total_staked, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] - /// Cancel open request to leave candidates - /// - only callable by collator account - /// - result upon successful call is the candidate is active in the candidate pool - pub fn cancel_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(state.is_leaving(), Error::::CandidateNotLeaving); - state.go_online(); - let mut candidates = >::get(); - ensure!( - candidates.0.len() as u32 <= candidate_count, - Error::::TooLowCandidateCountWeightHintCancelLeaveCandidates - ); - ensure!( - candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), - Error::::AlreadyActive - ); - >::put(candidates); - >::insert(&collator, state); - Self::deposit_event(Event::CancelledCandidateExit { candidate: collator }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::go_offline())] - /// Temporarily leave the set of collator candidates without unbonding - pub fn go_offline(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(state.is_active(), Error::::AlreadyOffline); - state.go_offline(); - let mut candidates = >::get(); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); - } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateWentOffline { candidate: collator }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::go_online())] - /// Rejoin the set of collator candidates if previously had called `go_offline` - pub fn go_online(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(!state.is_active(), Error::::AlreadyActive); - ensure!(!state.is_leaving(), Error::::CannotGoOnlineIfLeaving); - state.go_online(); - let mut candidates = >::get(); - ensure!( - candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), - Error::::AlreadyActive - ); - >::put(candidates); - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBackOnline { candidate: collator }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::candidate_bond_more())] - /// Increase collator candidate self bond by `more` - pub fn candidate_bond_more( - origin: OriginFor, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - state.bond_more::(collator.clone(), more)?; - let (is_active, total_counted) = (state.is_active(), state.total_counted); - >::insert(&collator, state); - if is_active { - Self::update_active(collator, total_counted); - } - Ok(().into()) - } - #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] - /// Request by collator candidate to decrease self bond by `less` - pub fn schedule_candidate_bond_less( - origin: OriginFor, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let when = state.schedule_bond_less::(less)?; - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBondLessRequested { - candidate: collator, - amount_to_decrease: less, - execute_round: when, - }); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::execute_candidate_bond_less())] - /// Execute pending request to adjust the collator candidate self bond - pub fn execute_candidate_bond_less( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; // we may want to reward this if caller != candidate - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.execute_bond_less::(candidate.clone())?; - >::insert(&candidate, state); - Ok(().into()) - } - #[pallet::weight(::WeightInfo::cancel_candidate_bond_less())] - /// Cancel pending request to adjust the collator candidate self bond - pub fn cancel_candidate_bond_less(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - state.cancel_bond_less::(collator.clone())?; - >::insert(&collator, state); - Ok(().into()) - } - #[pallet::weight( - ::WeightInfo::delegate( - *candidate_delegation_count, - *delegation_count - ) - )] - /// If caller is not a delegator and not a collator, then join the set of delegators - /// If caller is a delegator, then makes delegation to change their delegation state - pub fn delegate( - origin: OriginFor, - candidate: T::AccountId, - amount: BalanceOf, - candidate_delegation_count: u32, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::delegate_with_auto_compound( - candidate, - delegator, - amount, - Percent::zero(), - candidate_delegation_count, - 0, - delegation_count, - ) - } - - /// If caller is not a delegator and not a collator, then join the set of delegators - /// If caller is a delegator, then makes delegation to change their delegation state - /// Sets the auto-compound config for the delegation - #[pallet::weight( - ::WeightInfo::delegate_with_auto_compound( - *candidate_delegation_count, - *candidate_auto_compounding_delegation_count, - *delegation_count, - ) - )] - pub fn delegate_with_auto_compound( - origin: OriginFor, - candidate: T::AccountId, - amount: BalanceOf, - auto_compound: Percent, - candidate_delegation_count: u32, - candidate_auto_compounding_delegation_count: u32, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::delegate_with_auto_compound( - candidate, - delegator, - amount, - auto_compound, - candidate_delegation_count, - candidate_auto_compounding_delegation_count, - delegation_count, - ) - } - - /// DEPRECATED use batch util with schedule_revoke_delegation for all delegations - /// Request to leave the set of delegators. If successful, the caller is scheduled to be - /// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations. - /// Success forbids future delegation requests until the request is invoked or cancelled. - #[pallet::weight(::WeightInfo::schedule_leave_delegators())] - pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegator_schedule_revoke_all(delegator) - } - - /// DEPRECATED use batch util with execute_delegation_request for all delegations - /// Execute the right to exit the set of delegators and revoke all ongoing delegations. - #[pallet::weight(::WeightInfo::execute_leave_delegators(*delegation_count))] - pub fn execute_leave_delegators( - origin: OriginFor, - delegator: T::AccountId, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count) - } - - /// DEPRECATED use batch util with cancel_delegation_request for all delegations - /// Cancel a pending request to exit the set of delegators. Success clears the pending exit - /// request (thereby resetting the delay upon another `leave_delegators` call). - #[pallet::weight(::WeightInfo::cancel_leave_delegators())] - pub fn cancel_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegator_cancel_scheduled_revoke_all(delegator) - } - - #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] - /// Request to revoke an existing delegation. If successful, the delegation is scheduled - /// to be allowed to be revoked via the `execute_delegation_request` extrinsic. - /// The delegation receives no rewards for the rounds while a revoke is pending. - /// A revoke may not be performed if any other scheduled request is pending. - pub fn schedule_revoke_delegation( - origin: OriginFor, - collator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_schedule_revoke(collator, delegator) - } - - #[pallet::weight(::WeightInfo::delegator_bond_more())] - /// Bond more for delegators wrt a specific collator candidate. - pub fn delegator_bond_more( - origin: OriginFor, - candidate: T::AccountId, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - let in_top = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - more, - )?; - Pallet::::deposit_event(Event::DelegationIncreased { - delegator, - candidate, - amount: more, - in_top, - }); - - Ok(().into()) - } - - #[pallet::weight(::WeightInfo::schedule_delegator_bond_less())] - /// Request bond less for delegators wrt a specific collator candidate. The delegation's - /// rewards for rounds while the request is pending use the reduced bonded amount. - /// A bond less may not be performed if any other scheduled request is pending. - pub fn schedule_delegator_bond_less( - origin: OriginFor, - candidate: T::AccountId, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_schedule_bond_decrease(candidate, delegator, less) - } - - #[pallet::weight(::WeightInfo::execute_delegator_bond_less())] - /// Execute pending request to change an existing delegation - pub fn execute_delegation_request( - origin: OriginFor, - delegator: T::AccountId, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; // we may want to reward caller if caller != delegator - Self::delegation_execute_scheduled_request(candidate, delegator) - } - - #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] - /// Cancel request to change an existing delegation. - pub fn cancel_delegation_request( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_cancel_request(candidate, delegator) - } - - /// Sets the auto-compounding reward percentage for a delegation. - #[pallet::weight(::WeightInfo::set_auto_compound( - *candidate_auto_compounding_delegation_count_hint, - *delegation_count_hint, - ))] - pub fn set_auto_compound( - origin: OriginFor, - candidate: T::AccountId, - value: Percent, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::set_auto_compound( - candidate, - delegator, - value, - candidate_auto_compounding_delegation_count_hint, - delegation_count_hint, - ) - } - - /// Hotfix to remove existing empty entries for candidates that have left. - #[pallet::weight( - T::DbWeight::get().reads_writes(2 * candidates.len() as u64, candidates.len() as u64) - )] - pub fn hotfix_remove_delegation_requests_exited_candidates( - origin: OriginFor, - candidates: Vec, - ) -> DispatchResult { - ensure_signed(origin)?; - ensure!(candidates.len() < 100, >::InsufficientBalance); - for candidate in &candidates { - ensure!( - >::get(candidate).is_none(), - >::CandidateNotLeaving - ); - ensure!( - >::get(candidate).is_empty(), - >::CandidateNotLeaving - ); - } - - for candidate in candidates { - >::remove(candidate); - } - - Ok(()) - } - } - - /// Represents a payout made via `pay_one_collator_reward`. - pub(crate) enum RewardPayment { - /// A collator was paid - Paid, - /// A collator was skipped for payment. This can happen if they haven't been awarded any - /// points, that is, they did not produce any blocks. - Skipped, - /// All collator payments have been processed. - Finished, - } - - impl Pallet { - pub fn is_delegator(acc: &T::AccountId) -> bool { - >::get(acc).is_some() - } - pub fn is_candidate(acc: &T::AccountId) -> bool { - >::get(acc).is_some() - } - pub fn is_selected_candidate(acc: &T::AccountId) -> bool { - >::get().binary_search(acc).is_ok() - } - /// Returns an account's free balance which is not locked in delegation staking - pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { - let mut balance = T::Currency::free_balance(acc); - if let Some(state) = >::get(acc) { - balance = balance.saturating_sub(state.total()); - } - balance - } - /// Returns an account's free balance which is not locked in collator staking - pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { - let mut balance = T::Currency::free_balance(acc); - if let Some(info) = >::get(acc) { - balance = balance.saturating_sub(info.bond); - } - balance - } - /// Returns a delegations auto-compound value. - pub fn delegation_auto_compound( - candidate: &T::AccountId, - delegator: &T::AccountId, - ) -> Percent { - >::auto_compound(candidate, delegator) - } - /// Caller must ensure candidate is active before calling - pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { - let mut candidates = >::get(); - candidates.remove(&Bond::from_owner(candidate.clone())); - candidates.insert(Bond { owner: candidate, amount: total }); - >::put(candidates); - } - /// Compute round issuance based on total staked for the given round - fn compute_issuance(staked: BalanceOf) -> BalanceOf { - let config = >::get(); - let round_issuance = crate::inflation::round_issuance_range::(config.round); - // TODO: consider interpolation instead of bounded range - if staked < config.expect.min { - round_issuance.min - } else if staked > config.expect.max { - round_issuance.max - } else { - round_issuance.ideal - } - } - /// Remove delegation from candidate state - /// Amount input should be retrieved from delegator and it informs the storage lookups - pub(crate) fn delegator_leaves_candidate( - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - ) -> DispatchResult { - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.rm_delegation_if_exists::(&candidate, delegator.clone(), amount)?; - let new_total_locked = >::get().saturating_sub(amount); - >::put(new_total_locked); - let new_total = state.total_counted; - >::insert(&candidate, state); - Self::deposit_event(Event::DelegatorLeftCandidate { - delegator, - candidate, - unstaked_amount: amount, - total_candidate_staked: new_total, - }); - Ok(()) - } - pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { - // payout is now - delay rounds ago => now - delay > 0 else return early - let delay = T::RewardPaymentDelay::get(); - if now <= delay { - return Weight::zero(); - } - let round_to_payout = now.saturating_sub(delay); - let total_points = >::get(round_to_payout); - if total_points.is_zero() { - return Weight::zero(); - } - let total_staked = >::take(round_to_payout); - let total_issuance = Self::compute_issuance(total_staked); - let mut left_issuance = total_issuance; - // reserve portion of issuance for parachain bond account - let bond_config = >::get(); - let parachain_bond_reserve = bond_config.percent * total_issuance; - if let Ok(imb) = - T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) - { - // update round issuance iff transfer succeeds - left_issuance = left_issuance.saturating_sub(imb.peek()); - Self::deposit_event(Event::ReservedForParachainBond { - account: bond_config.account, - value: imb.peek(), - }); - } - - let payout = DelayedPayout { - round_issuance: total_issuance, - total_staking_reward: left_issuance, - collator_commission: >::get(), - }; - - >::insert(round_to_payout, payout); - T::WeightInfo::prepare_staking_payouts() - } - - /// Wrapper around pay_one_collator_reward which handles the following logic: - /// * whether or not a payout needs to be made - /// * cleaning up when payouts are done - /// * returns the weight consumed by pay_one_collator_reward if applicable - fn handle_delayed_payouts(now: RoundIndex) -> Weight { - let delay = T::RewardPaymentDelay::get(); - - // don't underflow uint - if now < delay { - return Weight::from_ref_time(0u64); - } - - let paid_for_round = now.saturating_sub(delay); - - if let Some(payout_info) = >::get(paid_for_round) { - let result = Self::pay_one_collator_reward(paid_for_round, payout_info); - - // clean up storage items that we no longer need - if matches!(result.0, RewardPayment::Finished) { - >::remove(paid_for_round); - >::remove(paid_for_round); - } - result.1 // weight consumed by pay_one_collator_reward - } else { - Weight::from_ref_time(0u64) - } - } - - /// Payout a single collator from the given round. - /// - /// Returns an optional tuple of (Collator's AccountId, total paid) - /// or None if there were no more payouts to be made for the round. - pub(crate) fn pay_one_collator_reward( - paid_for_round: RoundIndex, - payout_info: DelayedPayout>, - ) -> (RewardPayment, Weight) { - // 'early_weight' tracks weight used for reads/writes done early in this fn before its - // early-exit codepaths. - let mut early_weight = Weight::zero(); - - // TODO: it would probably be optimal to roll Points into the DelayedPayouts storage - // item so that we do fewer reads each block - let total_points = >::get(paid_for_round); - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 0)); - - if total_points.is_zero() { - // TODO: this case is obnoxious... it's a value query, so it could mean one of two - // different logic errors: - // 1. we removed it before we should have - // 2. we called pay_one_collator_reward when we were actually done with deferred - // payouts - log::warn!("pay_one_collator_reward called with no > for the round!"); - return (RewardPayment::Finished, early_weight); - } - - let collator_fee = payout_info.collator_commission; - let collator_issuance = collator_fee * payout_info.round_issuance; - - if let Some((collator, state)) = - >::iter_prefix(paid_for_round).drain().next() - { - // read and kill AtStake - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - - // Take the awarded points for the collator - let pts = >::take(paid_for_round, &collator); - // read and kill AwardedPts - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - if pts == 0 { - return (RewardPayment::Skipped, early_weight); - } - - // 'extra_weight' tracks weight returned from fns that we delegate to which can't be - // known ahead of time. - let mut extra_weight = Weight::zero(); - let pct_due = Perbill::from_rational(pts, total_points); - let total_paid = pct_due * payout_info.total_staking_reward; - let mut amt_due = total_paid; - - let num_delegators = state.delegations.len(); - if state.delegations.is_empty() { - // solo collator with no delegators - extra_weight = extra_weight - .saturating_add(T::PayoutCollatorReward::payout_collator_reward( - paid_for_round, - collator.clone(), - amt_due, - )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator, - amt_due, - )); - } else { - // pay collator first; commission + due_portion - let collator_pct = Perbill::from_rational(state.bond, state.total); - let commission = pct_due * collator_issuance; - amt_due = amt_due.saturating_sub(commission); - let collator_reward = (collator_pct * amt_due).saturating_add(commission); - extra_weight = extra_weight - .saturating_add(T::PayoutCollatorReward::payout_collator_reward( - paid_for_round, - collator.clone(), - collator_reward, - )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator.clone(), - collator_reward, - )); - - // pay delegators due portion - for BondWithAutoCompound { owner, amount, auto_compound } in state.delegations { - let percent = Perbill::from_rational(amount, state.total); - let due = percent * amt_due; - if !due.is_zero() { - extra_weight = extra_weight.saturating_add(Self::mint_and_compound( - due, - auto_compound, - collator.clone(), - owner.clone(), - )); - } - } - } - - ( - RewardPayment::Paid, - T::WeightInfo::pay_one_collator_reward(num_delegators as u32) - .saturating_add(extra_weight), - ) - } else { - // Note that we don't clean up storage here; it is cleaned up in - // handle_delayed_payouts() - (RewardPayment::Finished, Weight::from_ref_time(0u64)) - } - } - - /// Compute the top `TotalSelected` candidates in the CandidatePool and return - /// a vec of their AccountIds (in the order of selection) - pub fn compute_top_candidates() -> Vec { - let mut candidates = >::get().0; - // order candidates by stake (least to greatest so requires `rev()`) - candidates.sort_by(|a, b| a.amount.cmp(&b.amount)); - let top_n = >::get() as usize; - // choose the top TotalSelected qualified candidates, ordered by stake - let mut collators = candidates - .into_iter() - .rev() - .take(top_n) - .filter(|x| x.amount >= T::MinCollatorStk::get()) - .map(|x| x.owner) - .collect::>(); - collators.sort(); - collators - } - /// Best as in most cumulatively supported in terms of stake - /// Returns [collator_count, delegation_count, total staked] - pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { - let (mut collator_count, mut delegation_count, mut total) = - (0u32, 0u32, BalanceOf::::zero()); - // choose the top TotalSelected qualified candidates, ordered by stake - let collators = Self::compute_top_candidates(); - if collators.is_empty() { - // SELECTION FAILED TO SELECT >=1 COLLATOR => select collators from previous round - let last_round = now.saturating_sub(1u32); - let mut total_per_candidate: BTreeMap> = BTreeMap::new(); - // set this round AtStake to last round AtStake - for (account, snapshot) in >::iter_prefix(last_round) { - collator_count = collator_count.saturating_add(1u32); - delegation_count = - delegation_count.saturating_add(snapshot.delegations.len() as u32); - total = total.saturating_add(snapshot.total); - total_per_candidate.insert(account.clone(), snapshot.total); - >::insert(now, account, snapshot); - } - // `SelectedCandidates` remains unchanged from last round - // emit CollatorChosen event for tools that use this event - for candidate in >::get() { - let snapshot_total = total_per_candidate - .get(&candidate) - .expect("all selected candidates have snapshots"); - Self::deposit_event(Event::CollatorChosen { - round: now, - collator_account: candidate, - total_exposed_amount: *snapshot_total, - }) - } - let weight = T::WeightInfo::select_top_candidates(0, 0); - return (weight, collator_count, delegation_count, total); - } - - // snapshot exposure for round for weighting reward distribution - for account in collators.iter() { - let state = >::get(account) - .expect("all members of CandidateQ must be candidates"); - - collator_count = collator_count.saturating_add(1u32); - delegation_count = delegation_count.saturating_add(state.delegation_count); - total = total.saturating_add(state.total_counted); - let CountedDelegations { uncounted_stake, rewardable_delegations } = - Self::get_rewardable_delegators(account); - let total_counted = state.total_counted.saturating_sub(uncounted_stake); - - let auto_compounding_delegations = >::get(account) - .into_iter() - .map(|x| (x.delegator, x.value)) - .collect::>(); - let rewardable_delegations = rewardable_delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner.clone(), - amount: d.amount, - auto_compound: auto_compounding_delegations - .get(&d.owner) - .cloned() - .unwrap_or(Percent::zero()), - }) - .collect(); - - let snapshot = CollatorSnapshot { - bond: state.bond, - delegations: rewardable_delegations, - total: total_counted, - }; - >::insert(now, account, snapshot); - Self::deposit_event(Event::CollatorChosen { - round: now, - collator_account: account.clone(), - total_exposed_amount: state.total_counted, - }); - } - // insert canonical collator set - >::put(collators); - - let avg_delegator_count = delegation_count.checked_div(collator_count).unwrap_or(0); - let weight = T::WeightInfo::select_top_candidates(collator_count, avg_delegator_count); - (weight, collator_count, delegation_count, total) - } - - /// Apply the delegator intent for revoke and decrease in order to build the - /// effective list of delegators with their intended bond amount. - /// - /// This will: - /// - if [DelegationChange::Revoke] is outstanding, set the bond amount to 0. - /// - if [DelegationChange::Decrease] is outstanding, subtract the bond by specified amount. - /// - else, do nothing - /// - /// The intended bond amounts will be used while calculating rewards. - pub(crate) fn get_rewardable_delegators(collator: &T::AccountId) -> CountedDelegations { - let requests = >::get(collator) - .into_iter() - .map(|x| (x.delegator, x.action)) - .collect::>(); - let mut uncounted_stake = BalanceOf::::zero(); - let rewardable_delegations = >::get(collator) - .expect("all members of CandidateQ must be candidates") - .delegations - .into_iter() - .map(|mut bond| { - bond.amount = match requests.get(&bond.owner) { - None => bond.amount, - Some(DelegationAction::Revoke(_)) => { - uncounted_stake = uncounted_stake.saturating_add(bond.amount); - BalanceOf::::zero() - } - Some(DelegationAction::Decrease(amount)) => { - uncounted_stake = uncounted_stake.saturating_add(*amount); - bond.amount.saturating_sub(*amount) - } - }; - - bond - }) - .collect(); - CountedDelegations { uncounted_stake, rewardable_delegations } - } - - /// This function exists as a helper to delegator_bond_more & auto_compound functionality. - /// Any changes to this function must align with both user-initiated bond increases and - /// auto-compounding bond increases. - /// Any feature-specific preconditions should be validated before this function is invoked. - /// Any feature-specific events must be emitted after this function is invoked. - pub fn delegation_bond_more_without_event( - delegator: T::AccountId, - candidate: T::AccountId, - more: BalanceOf, - ) -> Result { - ensure!( - !Self::delegation_request_revoke_exists(&candidate, &delegator), - Error::::PendingDelegationRevoke - ); - let mut state = >::get(&delegator).ok_or(Error::::DelegatorDNE)?; - state.increase_delegation::(candidate, more) - } - - /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. - pub fn mint(amt: BalanceOf, to: T::AccountId) { - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { - Self::deposit_event(Event::Rewarded { - account: to.clone(), - rewards: amount_transferred.peek(), - }); - } - } - - /// Mint a specified reward amount to the collator's account. Emits the [Rewarded] event. - pub fn mint_collator_reward( - _paid_for_round: RoundIndex, - collator_id: T::AccountId, - amt: BalanceOf, - ) -> Weight { - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&collator_id, amt) { - Self::deposit_event(Event::Rewarded { - account: collator_id.clone(), - rewards: amount_transferred.peek(), - }); - } - T::WeightInfo::mint_collator_reward() - } - - /// Mint and compound delegation rewards. The function mints the amount towards the - /// delegator and tries to compound a specified percent of it back towards the delegation. - /// If a scheduled delegation revoke exists, then the amount is only minted, and nothing is - /// compounded. Emits the [Compounded] event. - pub fn mint_and_compound( - amt: BalanceOf, - compound_percent: Percent, - candidate: T::AccountId, - delegator: T::AccountId, - ) -> Weight { - let mut weight = T::WeightInfo::mint_collator_reward(); - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&delegator, amt) { - Self::deposit_event(Event::Rewarded { - account: delegator.clone(), - rewards: amount_transferred.peek(), - }); - - let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); - if compound_amount.is_zero() { - return weight; - } - - if let Err(err) = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - compound_amount, - ) { - log::debug!( - "skipped compounding staking reward towards candidate '{:?}' for \ - delegator '{:?}': {:?}", - candidate, - delegator, - err - ); - return weight; - }; - weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); - - Pallet::::deposit_event(Event::Compounded { - delegator, - candidate, - amount: compound_amount, - }); - }; - - weight - } - } - - /// Add reward points to block authors: - /// * 20 points to the block producer for producing a block in the chain - impl Pallet { - fn award_points_to_block_author() { - let author = T::BlockAuthor::get(); - let now = >::get().current; - let score_plus_20 = >::get(now, &author).saturating_add(20); - >::insert(now, author, score_plus_20); - >::mutate(now, |x| *x = x.saturating_add(20)); - } - } - - impl nimbus_primitives::CanAuthor for Pallet { - fn can_author(account: &T::AccountId, _slot: &u32) -> bool { - Self::is_selected_candidate(account) - } - } - - impl Get> for Pallet { - fn get() -> Vec { - Self::selected_candidates() - } - } -} diff --git a/external/pallets/parachain-staking/src/migrations.rs b/external/pallets/parachain-staking/src/migrations.rs deleted file mode 100644 index 7fbc98064..000000000 --- a/external/pallets/parachain-staking/src/migrations.rs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! # Migrations - -#![allow(unused)] -#![allow(clippy::type_complexity)] - -#[allow(deprecated)] -use crate::types::deprecated::{ - CollatorSnapshot as OldCollatorSnapshot, DelegationChange, Delegator as OldDelegator, -}; -use crate::{ - delegation_requests::{DelegationAction, ScheduledRequest}, - pallet::{DelegationScheduledRequests, DelegatorState, Total}, - types::{CollatorSnapshot, Delegator}, - AtStake, BalanceOf, Bond, BondWithAutoCompound, BottomDelegations, CandidateInfo, - CandidateMetadata, CapacityStatus, CollatorCandidate, Config, DelayedPayouts, Delegations, - Event, Pallet, Points, Round, RoundIndex, Staked, TopDelegations, -}; -use frame_support::Twox64Concat; -use parity_scale_codec::{Decode, Encode}; -extern crate alloc; -#[cfg(feature = "try-runtime")] -use alloc::{format, string::ToString}; -use frame_support::{ - migration::storage_key_iter, - pallet_prelude::PhantomData, - storage, - traits::{Get, OnRuntimeUpgrade, ReservableCurrency}, - weights::Weight, -}; -#[cfg(feature = "try-runtime")] -use scale_info::prelude::string::String; -use sp_runtime::{ - traits::{Saturating, Zero}, - Percent, -}; -use sp_std::{convert::TryInto, vec, vec::Vec}; - -/// Migrate `AtStake` storage item to include auto-compound value for unpaid rounds. -pub struct MigrateAtStakeAutoCompound(PhantomData); -impl MigrateAtStakeAutoCompound { - /// Get keys for the `AtStake` storage for the rounds up to `RewardPaymentDelay` rounds ago. - /// We migrate only the last unpaid rounds due to the presence of stale entries in `AtStake` - /// which significantly increase the PoV size. - fn unpaid_rounds_keys() -> impl Iterator)> { - let current_round = >::get().current; - let max_unpaid_round = current_round.saturating_sub(T::RewardPaymentDelay::get()); - (max_unpaid_round..=current_round).into_iter().flat_map(|round| { - >::iter_key_prefix(round).map(move |candidate| { - let key = >::hashed_key_for(round, candidate.clone()); - (round, candidate, key) - }) - }) - } -} -impl OnRuntimeUpgrade for MigrateAtStakeAutoCompound { - #[allow(deprecated)] - fn on_runtime_upgrade() -> Weight { - log::info!( - target: "MigrateAtStakeAutoCompound", - "running migration to add auto-compound values" - ); - let mut reads = 0u64; - let mut writes = 0u64; - for (round, candidate, key) in Self::unpaid_rounds_keys() { - let old_state: OldCollatorSnapshot> = - storage::unhashed::get(&key).expect("unable to decode value"); - reads = reads.saturating_add(1); - writes = writes.saturating_add(1); - log::info!( - target: "MigrateAtStakeAutoCompound", - "migration from old format round {:?}, candidate {:?}", round, candidate - ); - let new_state = CollatorSnapshot { - bond: old_state.bond, - delegations: old_state - .delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner, - amount: d.amount, - auto_compound: Percent::zero(), - }) - .collect(), - total: old_state.total, - }; - storage::unhashed::put(&key, &new_state); - } - - T::DbWeight::get().reads_writes(reads, writes) - } - - #[allow(deprecated)] - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { - let mut num_to_update = 0u32; - let mut rounds_candidates: Vec<(RoundIndex, T::AccountId)> = vec![]; - use sp_std::collections::btree_map::BTreeMap; - let mut state_map: BTreeMap = BTreeMap::new(); - - for (round, candidate, key) in Self::unpaid_rounds_keys() { - let state: OldCollatorSnapshot> = - storage::unhashed::get(&key).expect("unable to decode value"); - - num_to_update = num_to_update.saturating_add(1); - rounds_candidates.push((round, candidate.clone())); - let mut delegation_str = vec![]; - for d in state.delegations { - delegation_str - .push(format!("owner={:?}_amount={:?}_autoCompound=0%", d.owner, d.amount)); - } - state_map.insert( - (*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string(), - format!( - "bond={:?}_total={:?}_delegations={:?}", - state.bond, state.total, delegation_str - ), - ); - } - - rounds_candidates.sort(); - Ok((state_map, rounds_candidates, num_to_update).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), &'static str> { - use sp_std::collections::btree_map::BTreeMap; - - let (state_map, rounds_candidates_received, num_updated_received): ( - BTreeMap, - Vec<(RoundIndex, T::AccountId)>, - u32, - ) = Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed"); - - let mut num_updated = 0u32; - let mut rounds_candidates = vec![]; - for (round, candidate, _) in Self::unpaid_rounds_keys() { - let state = >::get(round, &candidate); - num_updated = num_updated.saturating_add(1); - rounds_candidates.push((round, candidate.clone())); - let mut delegation_str = vec![]; - for d in state.delegations { - delegation_str.push(format!( - "owner={:?}_amount={:?}_autoCompound={:?}", - d.owner, d.amount, d.auto_compound - )); - } - assert_eq!( - Some(&format!( - "bond={:?}_total={:?}_delegations={:?}", - state.bond, state.total, delegation_str - )), - state_map - .get(&((*format!("round_{:?}_candidate_{:?}", round, candidate)).to_string())), - "incorrect delegations migration for round_{:?}_candidate_{:?}", - round, - candidate, - ); - } - - rounds_candidates.sort(); - assert_eq!(rounds_candidates, rounds_candidates_received); - assert_eq!(num_updated, num_updated_received); - Ok(()) - } -} diff --git a/external/pallets/parachain-staking/src/mock.rs b/external/pallets/parachain-staking/src/mock.rs deleted file mode 100644 index c8bf3ba3a..000000000 --- a/external/pallets/parachain-staking/src/mock.rs +++ /dev/null @@ -1,970 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Test utilities -use crate as pallet_parachain_staking; -use crate::{ - pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, - COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, -}; -use frame_support::{ - construct_runtime, parameter_types, - traits::{Everything, GenesisBuild, LockIdentifier, OnFinalize, OnInitialize}, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_core::H256; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - Perbill, Percent, -}; - -pub type AccountId = u64; -pub type Balance = u128; -pub type BlockNumber = u32; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -// Configure a mock runtime to test the pallet. -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Config, Event}, - BlockAuthor: block_author::{Pallet, Storage}, - } -); - -parameter_types! { - pub const BlockHashCount: u32 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const SS58Prefix: u8 = 42; -} -impl frame_system::Config for Test { - type BaseCallFilter = Everything; - type DbWeight = RocksDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = sp_runtime::generic::Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u128 = 1; -} -impl pallet_balances::Config for Test { - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type MaxLocks = (); - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} -impl block_author::Config for Test {} -const GENESIS_BLOCKS_PER_ROUND: u32 = 5; -const GENESIS_COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20); -const GENESIS_PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30); -parameter_types! { - pub const MinBlocksPerRound: u32 = 3; - pub const LeaveCandidatesDelay: u32 = 2; - pub const CandidateBondLessDelay: u32 = 2; - pub const LeaveDelegatorsDelay: u32 = 2; - pub const RevokeDelegationDelay: u32 = 2; - pub const DelegationBondLessDelay: u32 = 2; - pub const RewardPaymentDelay: u32 = 2; - pub const MinSelectedCandidates: u32 = 5; - pub const MaxTopDelegationsPerCandidate: u32 = 4; - pub const MaxBottomDelegationsPerCandidate: u32 = 4; - pub const MaxDelegationsPerDelegator: u32 = 4; - pub const MinCollatorStk: u128 = 10; - pub const MinDelegatorStk: u128 = 5; - pub const MinDelegation: u128 = 3; -} -impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; - type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; - type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; - type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MinCollatorStk = MinCollatorStk; - type MinCandidateStk = MinCollatorStk; - type MinDelegatorStk = MinDelegatorStk; - type MinDelegation = MinDelegation; - type BlockAuthor = BlockAuthor; - type OnCollatorPayout = (); - type PayoutCollatorReward = (); - type OnNewRound = (); - type WeightInfo = (); -} - -pub(crate) struct ExtBuilder { - // endowed accounts with balances - balances: Vec<(AccountId, Balance)>, - // [collator, amount] - collators: Vec<(AccountId, Balance)>, - // [delegator, collator, delegation_amount, auto_compound_percent] - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - // inflation config - inflation: InflationInfo, -} - -impl Default for ExtBuilder { - fn default() -> ExtBuilder { - ExtBuilder { - balances: vec![], - delegations: vec![], - collators: vec![], - inflation: InflationInfo { - expect: Range { min: 700, ideal: 700, max: 700 }, - // not used - annual: Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50), - }, - // unrealistically high parameterization, only for testing - round: Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }, - }, - } - } -} - -impl ExtBuilder { - pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { - self.balances = balances; - self - } - - pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { - self.collators = collators; - self - } - - pub(crate) fn with_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance)>, - ) -> Self { - self.delegations = - delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); - self - } - - pub(crate) fn with_auto_compounding_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - ) -> Self { - self.delegations = delegations; - self - } - - #[allow(dead_code)] - pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { - self.inflation = inflation; - self - } - - pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { balances: self.balances } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - pallet_parachain_staking::GenesisConfig:: { - candidates: self.collators, - delegations: self.delegations, - inflation_config: self.inflation, - collator_commission: GENESIS_COLLATOR_COMMISSION, - parachain_bond_reserve_percent: GENESIS_PARACHAIN_BOND_RESERVE_PERCENT, - blocks_per_round: GENESIS_BLOCKS_PER_ROUND, - } - .assimilate_storage(&mut t) - .expect("Parachain Staking's storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } -} - -/// Rolls forward one block. Returns the new block number. -fn roll_one_block() -> BlockNumber { - Balances::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - System::reset_events(); - System::on_initialize(System::block_number()); - Balances::on_initialize(System::block_number()); - ParachainStaking::on_initialize(System::block_number()); - System::block_number() -} - -/// Rolls to the desired block. Returns the number of blocks played. -pub(crate) fn roll_to(n: BlockNumber) -> u32 { - let mut num_blocks = 0; - let mut block = System::block_number(); - while block < n { - block = roll_one_block(); - num_blocks += 1; - } - num_blocks -} - -/// Rolls desired number of blocks. Returns the final block. -pub(crate) fn roll_blocks(num_blocks: u32) -> BlockNumber { - let mut block = System::block_number(); - for _ in 0..num_blocks { - block = roll_one_block(); - } - block -} - -/// Rolls block-by-block to the beginning of the specified round. -/// This will complete the block in which the round change occurs. -/// Returns the number of blocks played. -pub(crate) fn roll_to_round_begin(round: BlockNumber) -> BlockNumber { - let block = (round - 1) * GENESIS_BLOCKS_PER_ROUND; - roll_to(block) -} - -/// Rolls block-by-block to the end of the specified round. -/// The block following will be the one in which the specified round change occurs. -pub(crate) fn roll_to_round_end(round: BlockNumber) -> BlockNumber { - let block = round * GENESIS_BLOCKS_PER_ROUND - 1; - roll_to(block) -} - -pub(crate) fn events() -> Vec> { - System::events() - .into_iter() - .map(|r| r.event) - .filter_map( - |e| { - if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None } - }, - ) - .collect::>() -} - -/// Asserts that some events were never emitted. -/// -/// # Example -/// -/// ``` -/// assert_no_events!(); -/// ``` -#[macro_export] -macro_rules! assert_no_events { - () => { - similar_asserts::assert_eq!(Vec::>::new(), $crate::mock::events()) - }; -} - -/// Asserts that emitted events match exactly the given input. -/// -/// # Example -/// -/// ``` -/// assert_events_eq!( -/// Foo { x: 1, y: 2 }, -/// Bar { value: "test" }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_eq { - ($event:expr) => { - similar_asserts::assert_eq!(vec![$event], $crate::mock::events()); - }; - ($($events:expr,)+) => { - similar_asserts::assert_eq!(vec![$($events,)+], $crate::mock::events()); - }; -} - -/// Asserts that some emitted events match the given input. -/// -/// # Example -/// -/// ``` -/// assert_events_emitted!( -/// Foo { x: 1, y: 2 }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_emitted { - ($event:expr) => { - [$event].into_iter().for_each(|e| assert!( - $crate::mock::events().into_iter().find(|x| x == &e).is_some(), - "Event {:?} was not found in events: \n{:#?}", - e, - $crate::mock::events() - )); - }; - ($($events:expr,)+) => { - [$($events,)+].into_iter().for_each(|e| assert!( - $crate::mock::events().into_iter().find(|x| x == &e).is_some(), - "Event {:?} was not found in events: \n{:#?}", - e, - $crate::mock::events() - )); - }; -} - -/// Asserts that some events were never emitted. -/// -/// # Example -/// -/// ``` -/// assert_events_not_emitted!( -/// Foo { x: 1, y: 2 }, -/// Bar { value: "test" }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_not_emitted { - ($event:expr) => { - [$event].into_iter().for_each(|e| assert!( - $crate::mock::events().into_iter().find(|x| x != &e).is_some(), - "Event {:?} was unexpectedly found in events: \n{:#?}", - e, - $crate::mock::events() - )); - }; - ($($events:expr,)+) => { - [$($events,)+].into_iter().for_each(|e| assert!( - $crate::mock::events().into_iter().find(|x| x != &e).is_some(), - "Event {:?} was unexpectedly found in events: \n{:#?}", - e, - $crate::mock::events() - )); - }; -} - -/// Asserts that the emitted events are exactly equal to the input patterns. -/// -/// # Example -/// -/// ``` -/// assert_events_eq_match!( -/// Foo { x: 1, .. }, -/// Bar { .. }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_eq_match { - ($index:expr;) => { - assert_eq!( - $index, - $crate::mock::events().len(), - "Found {} extra event(s): \n{:#?}", - $crate::mock::events().len()-$index, - $crate::mock::events() - ); - }; - ($index:expr; $event:pat_param, $($events:pat_param,)*) => { - assert!( - matches!( - $crate::mock::events().get($index), - Some($event), - ), - "Event {:#?} was not found at index {}: \n{:#?}", - stringify!($event), - $index, - $crate::mock::events() - ); - assert_events_eq_match!($index+1; $($events,)*); - }; - ($event:pat_param) => { - assert_events_eq_match!(0; $event,); - }; - ($($events:pat_param,)+) => { - assert_events_eq_match!(0; $($events,)+); - }; -} - -/// Asserts that some emitted events match the input patterns. -/// -/// # Example -/// -/// ``` -/// assert_events_emitted_match!( -/// Foo { x: 1, .. }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_emitted_match { - ($event:pat_param) => { - assert!( - $crate::mock::events().into_iter().any(|x| matches!(x, $event)), - "Event {:?} was not found in events: \n{:#?}", - stringify!($event), - $crate::mock::events() - ); - }; - ($event:pat_param, $($events:pat_param,)+) => { - assert_events_emitted_match!($event); - $( - assert_events_emitted_match!($events); - )+ - }; -} - -/// Asserts that the input patterns match none of the emitted events. -/// -/// # Example -/// -/// ``` -/// assert_events_not_emitted_match!( -/// Foo { x: 1, .. }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_not_emitted_match { - ($event:pat_param) => { - assert!( - $crate::mock::events().into_iter().any(|x| !matches!(x, $event)), - "Event {:?} was unexpectedly found in events: \n{:#?}", - stringify!($event), - $crate::mock::events() - ); - }; - ($event:pat_param, $($events:pat_param,)+) => { - assert_events_not_emitted_match!($event); - $( - assert_events_not_emitted_match!($events); - )+ - }; -} - -// Same storage changes as ParachainStaking::on_finalize -pub(crate) fn set_author(round: BlockNumber, acc: u64, pts: u32) { - >::mutate(round, |p| *p += pts); - >::mutate(round, acc, |p| *p += pts); -} - -/// fn to query the lock amount -pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option { - for lock in Balances::locks(&account_id) { - if lock.id == id { - return Some(lock.amount); - } - } - None -} - -#[test] -fn geneses() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 500); - assert_eq!(query_lock_amount(1, COLLATOR_LOCK_ID), Some(500)); - assert!(ParachainStaking::is_candidate(&1)); - assert_eq!(query_lock_amount(2, COLLATOR_LOCK_ID), Some(200)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&2), 100); - assert!(ParachainStaking::is_candidate(&2)); - // delegators - for x in 3..7 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 0); - assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(100)); - } - // uninvolved - for x in 7..10 { - assert!(!ParachainStaking::is_delegator(&x)); - } - // no delegator staking locks - assert_eq!(query_lock_amount(7, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 100); - assert_eq!(query_lock_amount(8, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&8), 9); - assert_eq!(query_lock_amount(9, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&9), 4); - // no collator staking locks - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&7), 100); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&8), 9); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&9), 4); - }); - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - for x in 1..5 { - assert!(ParachainStaking::is_candidate(&x)); - assert_eq!(query_lock_amount(x, COLLATOR_LOCK_ID), Some(20)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&x), 80); - } - assert!(ParachainStaking::is_candidate(&5)); - assert_eq!(query_lock_amount(5, COLLATOR_LOCK_ID), Some(10)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&5), 90); - // delegators - for x in 6..11 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(10)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 90); - } - }); -} - -#[frame_support::pallet] -pub mod block_author { - use super::*; - use frame_support::{pallet_prelude::*, traits::Get}; - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::storage] - #[pallet::getter(fn block_author)] - pub(super) type BlockAuthor = StorageValue<_, AccountId, ValueQuery>; - - impl Get for Pallet { - fn get() -> AccountId { - >::get() - } - } -} - -#[test] -fn roll_to_round_begin_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_begin(1); - assert_eq!(System::block_number(), 1); // no-op, we're already on this round - assert_eq!(num_blocks, 0); - - let num_blocks = roll_to_round_begin(2); - assert_eq!(System::block_number(), 5); - assert_eq!(num_blocks, 4); - - let num_blocks = roll_to_round_begin(3); - assert_eq!(System::block_number(), 10); - assert_eq!(num_blocks, 5); - }); -} - -#[test] -fn roll_to_round_end_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_end(1); - assert_eq!(System::block_number(), 4); - assert_eq!(num_blocks, 3); - - let num_blocks = roll_to_round_end(2); - assert_eq!(System::block_number(), 9); - assert_eq!(num_blocks, 5); - - let num_blocks = roll_to_round_end(3); - assert_eq!(System::block_number(), 14); - assert_eq!(num_blocks, 5); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_extra() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 200 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_wrong_order() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }, - ); - }); -} - -#[test] -fn test_assert_events_eq_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_eq!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - }); -} - -#[test] -fn test_assert_events_eq_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!(ParachainStakingEvent::DelegatorExitScheduled { - round: 2, - delegator: 3, - scheduled_exit: 4, - }); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }); - }); -} - -#[test] -fn test_assert_events_emitted_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - }); -} - -#[test] -fn test_assert_events_emitted_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_extra() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ParachainStakingEvent::Rewarded { .. }, - ParachainStakingEvent::Rewarded { .. }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_wrong_order() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::Rewarded { .. }, - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ParachainStakingEvent::Rewarded { rewards: 50, .. }, - ); - }); -} - -#[test] -fn test_assert_events_eq_match_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_eq_match!(ParachainStakingEvent::Rewarded { account: 1, .. }); - }); -} - -#[test] -fn test_assert_events_eq_match_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { round: 2, collator_account: 1, .. }, - ParachainStakingEvent::NewRound { starting_block: 10, .. }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_match_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!(ParachainStakingEvent::DelegatorExitScheduled { - round: 2, - .. - }); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_match_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 50, .. }); - }); -} - -#[test] -fn test_assert_events_emitted_match_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 100, .. }); - }); -} - -#[test] -fn test_assert_events_emitted_match_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!( - ParachainStakingEvent::CollatorChosen { total_exposed_amount: 10, .. }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -fn inject_test_events() { - [ - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ] - .into_iter() - .for_each(System::deposit_event); -} diff --git a/external/pallets/parachain-staking/src/set.rs b/external/pallets/parachain-staking/src/set.rs deleted file mode 100644 index d4775eba8..000000000 --- a/external/pallets/parachain-staking/src/set.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -/* TODO: use orml_utilities::OrderedSet without leaking substrate v2.0 dependencies*/ -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; - -/// An ordered set backed by `Vec` -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Default, Clone, TypeInfo)] -pub struct OrderedSet(pub Vec); - -impl OrderedSet { - /// Create a new empty set - pub fn new() -> Self { - Self(Vec::new()) - } - - /// Create a set from a `Vec`. - /// `v` will be sorted and dedup first. - pub fn from(mut v: Vec) -> Self { - v.sort(); - v.dedup(); - Self::from_sorted_set(v) - } - - /// Create a set from a `Vec`. - /// Assume `v` is sorted and contain unique elements. - pub fn from_sorted_set(v: Vec) -> Self { - Self(v) - } - - /// Insert an element. - /// Return true if insertion happened. - pub fn insert(&mut self, value: T) -> bool { - match self.0.binary_search(&value) { - Ok(_) => false, - Err(loc) => { - self.0.insert(loc, value); - true - } - } - } - - /// Remove an element. - /// Return true if removal happened. - pub fn remove(&mut self, value: &T) -> bool { - match self.0.binary_search(value) { - Ok(loc) => { - self.0.remove(loc); - true - } - Err(_) => false, - } - } - - /// Return if the set contains `value` - pub fn contains(&self, value: &T) -> bool { - self.0.binary_search(value).is_ok() - } - - /// Clear the set - pub fn clear(&mut self) { - self.0.clear(); - } -} - -impl From> for OrderedSet { - fn from(v: Vec) -> Self { - Self::from(v) - } -} diff --git a/external/pallets/parachain-staking/src/tests.rs b/external/pallets/parachain-staking/src/tests.rs deleted file mode 100644 index acd93210c..000000000 --- a/external/pallets/parachain-staking/src/tests.rs +++ /dev/null @@ -1,6909 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! # Staking Pallet Unit Tests -//! The unit tests are organized by the call they test. The order matches the order -//! of the calls in the `lib.rs`. -//! 1. Root -//! 2. Monetary Governance -//! 3. Public (Collator, Nominator) -//! 4. Miscellaneous Property-Based Tests - -use crate::{ - assert_events_emitted, assert_events_emitted_match, assert_events_eq, assert_no_events, - auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}, - delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, - mock::{ - roll_blocks, roll_to, roll_to_round_begin, roll_to_round_end, set_author, Balances, - BlockNumber, ExtBuilder, ParachainStaking, RuntimeOrigin, Test, - }, - AtStake, Bond, CollatorStatus, DelegationScheduledRequests, DelegatorAdded, DelegatorState, - DelegatorStatus, Error, Event, Range, DELEGATOR_LOCK_ID, -}; -use frame_support::{assert_noop, assert_ok}; -use sp_runtime::{traits::Zero, DispatchError, ModuleError, Perbill, Percent}; - -// ~~ ROOT ~~ - -#[test] -fn invalid_root_origin_fails() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::signed(45), 6u32), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_collator_commission( - RuntimeOrigin::signed(45), - Perbill::from_percent(5) - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::signed(45), 3u32), - sp_runtime::DispatchError::BadOrigin - ); - }); -} - -// SET TOTAL SELECTED - -#[test] -fn set_total_selected_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - // before we can bump total_selected we must bump the blocks per round - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - roll_blocks(1); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); - assert_events_eq!(Event::TotalSelectedSet { old: 5u32, new: 6u32 }); - }); -} - -#[test] -fn set_total_selected_fails_if_above_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); // test relies on this - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); -} - -#[test] -fn set_total_selected_passes_if_equal_to_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 10u32)); - }); -} - -#[test] -fn set_total_selected_passes_if_below_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); - }); -} - -#[test] -fn set_blocks_per_round_fails_if_below_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 20u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 15u32)); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 14u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); -} - -#[test] -fn set_blocks_per_round_passes_if_equal_to_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 9u32)); - }); -} - -#[test] -fn set_blocks_per_round_passes_if_above_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); // test relies on this - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - }); -} - -#[test] -fn set_total_selected_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - // round length must be >= total_selected, so update that first - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - - assert_eq!(ParachainStaking::total_selected(), 5u32); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); - assert_eq!(ParachainStaking::total_selected(), 6u32); - }); -} - -#[test] -fn cannot_set_total_selected_to_current_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 5u32), - Error::::NoWritingSameValue - ); - }); -} - -#[test] -fn cannot_set_total_selected_below_module_min() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 4u32), - Error::::CannotSetBelowMin - ); - }); -} - -// SET COLLATOR COMMISSION - -#[test] -fn set_collator_commission_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(5) - )); - assert_events_eq!(Event::CollatorCommissionSet { - old: Perbill::from_percent(20), - new: Perbill::from_percent(5), - }); - }); -} - -#[test] -fn set_collator_commission_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(20)); - assert_ok!(ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(5) - )); - assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(5)); - }); -} - -#[test] -fn cannot_set_collator_commission_to_current_collator_commission() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(20) - ), - Error::::NoWritingSameValue - ); - }); -} - -// SET BLOCKS PER ROUND - -#[test] -fn set_blocks_per_round_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - assert_events_eq!(Event::BlocksPerRoundSet { - current_round: 1, - first_block: 0, - old: 5, - new: 6, - new_per_round_inflation_min: Perbill::from_parts(926), - new_per_round_inflation_ideal: Perbill::from_parts(926), - new_per_round_inflation_max: Perbill::from_parts(926), - }); - }); -} - -#[test] -fn set_blocks_per_round_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - assert_eq!(ParachainStaking::round().length, 6); - }); -} - -#[test] -fn cannot_set_blocks_per_round_below_module_min() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 2u32), - Error::::CannotSetBelowMin - ); - }); -} - -#[test] -fn cannot_set_blocks_per_round_to_current_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32), - Error::::NoWritingSameValue - ); - }); -} - -#[test] -fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // we can't lower the blocks per round because it must be above the number of collators, - // and we can't lower the number of collators because it must be above - // MinSelectedCandidates. so we first raise blocks per round, then lower it. - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - - roll_to(10); - assert_events_emitted!(Event::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 20 - },); - roll_to(17); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32)); - roll_to(18); - assert_events_emitted!(Event::NewRound { - starting_block: 18, - round: 3, - selected_collators_number: 1, - total_balance: 20 - }); - }); -} - -// ~~ MONETARY GOVERNANCE ~~ - -#[test] -fn invalid_monetary_origin_fails() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::signed(45), - Range { min: 3u32.into(), ideal: 4u32.into(), max: 5u32.into() } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_parachain_bond_account(RuntimeOrigin::signed(45), 11), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::signed(45), - Percent::from_percent(2) - ), - sp_runtime::DispatchError::BadOrigin - ); - }); -} - -// SET STAKING EXPECTATIONS - -#[test] -fn set_staking_event_emits_event_correctly() { - ExtBuilder::default().build().execute_with(|| { - // valid call succeeds - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - )); - assert_events_eq!(Event::StakeExpectationsSet { - expect_min: 3u128, - expect_ideal: 4u128, - expect_max: 5u128, - }); - }); -} - -#[test] -fn set_staking_updates_storage_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { min: 700, ideal: 700, max: 700 } - ); - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - )); - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { min: 3u128, ideal: 4u128, max: 5u128 } - ); - }); -} - -#[test] -fn cannot_set_invalid_staking_expectations() { - ExtBuilder::default().build().execute_with(|| { - // invalid call fails - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 5u128, ideal: 4u128, max: 3u128 } - ), - Error::::InvalidSchedule - ); - }); -} - -#[test] -fn cannot_set_same_staking_expectations() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - )); - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - ), - Error::::NoWritingSameValue - ); - }); -} - -// SET INFLATION - -#[test] -fn set_inflation_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = - (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - )); - assert_events_eq!(Event::InflationSet { - annual_min: min, - annual_ideal: ideal, - annual_max: max, - round_min: Perbill::from_parts(57), - round_ideal: Perbill::from_parts(75), - round_max: Perbill::from_parts(93), - }); - }); -} - -#[test] -fn set_inflation_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = - (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_eq!( - ParachainStaking::inflation_config().annual, - Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50) - } - ); - assert_eq!( - ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5) - } - ); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); - assert_eq!(ParachainStaking::inflation_config().annual, Range { min, ideal, max }); - assert_eq!( - ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_parts(57), - ideal: Perbill::from_parts(75), - max: Perbill::from_parts(93) - } - ); - }); -} - -#[test] -fn cannot_set_invalid_inflation() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(3) - } - ), - Error::::InvalidSchedule - ); - }); -} - -#[test] -fn cannot_set_same_inflation() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = - (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); - assert_noop!( - ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), - Error::::NoWritingSameValue - ); - }); -} - -// SET PARACHAIN BOND ACCOUNT - -#[test] -fn set_parachain_bond_account_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); - assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); - }); -} - -#[test] -fn set_parachain_bond_account_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::parachain_bond_info().account, 0); - assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); - assert_eq!(ParachainStaking::parachain_bond_info().account, 11); - }); -} - -// SET PARACHAIN BOND RESERVE PERCENT - -#[test] -fn set_parachain_bond_reserve_percent_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_events_eq!(Event::ParachainBondReservePercentSet { - old: Percent::from_percent(30), - new: Percent::from_percent(50), - }); - }); -} - -#[test] -fn set_parachain_bond_reserve_percent_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(30)); - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(50)); - }); -} - -#[test] -fn cannot_set_same_parachain_bond_reserve_percent() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(30) - ), - Error::::NoWritingSameValue - ); - }); -} - -// ~~ PUBLIC ~~ - -// JOIN CANDIDATES - -#[test] -fn join_candidates_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - assert_events_eq!(Event::JoinedCollatorCandidates { - account: 1, - amount_locked: 10u128, - new_total_amt_locked: 10u128, - }); - }); -} - -#[test] -fn join_candidates_reserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); -} - -#[test] -fn join_candidates_increases_total_staked() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::total(), 0); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - assert_eq!(ParachainStaking::total(), 10); - }); -} - -#[test] -fn join_candidates_creates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert!(ParachainStaking::candidate_info(1).is_none()); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - let candidate_state = ParachainStaking::candidate_info(1).expect("just joined => exists"); - assert_eq!(candidate_state.bond, 10u128); - }); -} - -#[test] -fn join_candidates_adds_to_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - let candidate_pool = ParachainStaking::candidate_pool(); - assert_eq!(candidate_pool.0[0].owner, 1); - assert_eq!(candidate_pool.0[0].amount, 10); - }); -} - -#[test] -fn cannot_join_candidates_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_candidates(vec![(1, 500)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), - Error::::CandidateExists - ); - }); -} - -#[test] -fn cannot_join_candidates_if_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 50), (2, 20)]) - .with_candidates(vec![(1, 50)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(2), 10u128, 1u32), - Error::::DelegatorExists - ); - }); -} - -#[test] -fn cannot_join_candidates_without_min_bond() { - ExtBuilder::default().with_balances(vec![(1, 1000)]).build().execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 9u128, 100u32), - Error::::CandidateBondBelowMin - ); - }); -} - -#[test] -fn cannot_join_candidates_with_more_than_available_balance() { - ExtBuilder::default().with_balances(vec![(1, 500)]).build().execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 501u128, 100u32), - DispatchError::Module(ModuleError { - index: 2, - error: [8, 0, 0, 0], - message: Some("InsufficientBalance") - }) - ); - }); -} - -#[test] -fn insufficient_join_candidates_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - for i in 0..5 { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 20, i), - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - } - }); -} - -#[test] -fn sufficient_join_candidates_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - let mut count = 5u32; - for i in 6..10 { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(i), 20, count)); - count += 1u32; - } - }); -} - -// SCHEDULE LEAVE CANDIDATES - -#[test] -fn leave_candidates_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 1, - candidate: 1, - scheduled_exit: 3 - }); - }); -} - -#[test] -fn leave_candidates_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); -} - -#[test] -fn cannot_leave_candidates_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_leave_candidates_if_already_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateAlreadyLeaving - ); - }); -} - -#[test] -fn insufficient_leave_candidates_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - for i in 1..6 { - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 4u32), - Error::::TooLowCandidateCountToLeaveCandidates - ); - } - }); -} - -#[test] -fn sufficient_leave_candidates_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - let mut count = 5u32; - for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - count - )); - count -= 1u32; - } - }); -} - -// EXECUTE LEAVE CANDIDATES - -#[test] -fn execute_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_events_emitted!(Event::CandidateLeft { - ex_candidate: 1, - unlocked_amount: 10, - new_total_amt_locked: 0 - }); - }); -} - -#[test] -fn execute_leave_candidates_callable_by_any_signed() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); - }); -} - -#[test] -fn execute_leave_candidates_requires_correct_weight_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 10), (3, 10), (4, 10)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 10), (4, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - for i in 0..3 { - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, i), - Error::::TooLowCandidateDelegationCountToLeaveCandidates - ); - } - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 3)); - }); -} - -#[test] -fn execute_leave_candidates_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); -} - -#[test] -fn execute_leave_candidates_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 10); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::total(), 0); - }); -} - -#[test] -fn execute_leave_candidates_removes_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert!(ParachainStaking::candidate_info(1).is_none()); - }); -} - -#[test] -fn execute_leave_candidates_removes_pending_delegation_requests() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 15)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); - assert!(ParachainStaking::candidate_info(1).is_none()); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation request not removed" - ); - assert!( - !>::contains_key(1), - "the key was not removed from storage" - ); - }); -} - -#[test] -fn cannot_execute_leave_candidates_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(9); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); - }); -} - -// CANCEL LEAVE CANDIDATES - -#[test] -fn cancel_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); - }); -} - -#[test] -fn cancel_leave_candidates_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - let candidate = - ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); - assert!(candidate.is_active()); - }); -} - -#[test] -fn cancel_leave_candidates_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); - }); -} - -// GO OFFLINE - -#[test] -fn go_offline_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); - }); -} - -#[test] -fn go_offline_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); -} - -#[test] -fn go_offline_updates_candidate_state_to_idle() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("is candidate, just offline"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - }); -} - -#[test] -fn cannot_go_offline_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_go_offline_if_already_offline() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(1)), - Error::::AlreadyOffline - ); - }); -} - -// GO ONLINE - -#[test] -fn go_online_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - roll_blocks(1); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); - }); -} - -#[test] -fn go_online_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); -} - -#[test] -fn go_online_storage_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("offline still exists"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - }); -} - -#[test] -fn cannot_go_online_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_go_online_if_already_online() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::AlreadyActive - ); - }); -} - -#[test] -fn cannot_go_online_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::CannotGoOnlineIfLeaving - ); - }); -} - -// CANDIDATE BOND MORE - -#[test] -fn candidate_bond_more_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_events_eq!(Event::CandidateBondedMore { - candidate: 1, - amount: 30, - new_total_bond: 50 - }); - }); -} - -#[test] -fn candidate_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); -} - -#[test] -fn candidate_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - total += 30; - assert_eq!(ParachainStaking::total(), total); - }); -} - -#[test] -fn candidate_bond_more_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 50); - }); -} - -#[test] -fn candidate_bond_more_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); - }); -} - -// SCHEDULE CANDIDATE BOND LESS - -#[test] -fn schedule_candidate_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_events_eq!(Event::CandidateBondLessRequested { - candidate: 1, - amount_to_decrease: 10, - execute_round: 3, - }); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_request_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), - Error::::PendingCandidateRequestAlreadyExists - ); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(6), 50), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), - Error::::CandidateBondBelowMin - ); - }); -} - -#[test] -fn can_schedule_candidate_bond_less_if_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_exited_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), - Error::::CandidateDNE - ); - }); -} - -// 2. EXECUTE BOND LESS REQUEST - -#[test] -fn execute_candidate_bond_less_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 50)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 30 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_events_eq!(Event::CandidateBondedLess { - candidate: 1, - amount: 30, - new_bond: 20 - }); - }); -} - -#[test] -fn execute_candidate_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); -} - -#[test] -fn execute_candidate_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - total -= 10; - assert_eq!(ParachainStaking::total(), total); - }); -} - -#[test] -fn execute_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - }); -} - -#[test] -fn execute_candidate_bond_less_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); -} - -// CANCEL CANDIDATE BOND LESS REQUEST - -#[test] -fn cancel_candidate_bond_less_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert_events_emitted!(Event::CancelledCandidateBondLess { - candidate: 1, - amount: 10, - execute_round: 3, - }); - }); -} - -#[test] -fn cancel_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); - }); -} - -#[test] -fn only_candidate_can_cancel_candidate_bond_less_request() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_noop!( - ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), - Error::::CandidateDNE - ); - }); -} - -// DELEGATE - -#[test] -fn delegate_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }); - }); -} - -#[test] -fn delegate_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); -} - -#[test] -fn delegate_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_none()); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); - assert_eq!(delegator_state.total(), 10); - assert_eq!(delegator_state.delegations.0[0].owner, 1); - assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); -} - -#[test] -fn delegate_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); - assert!(top_delegations.delegations.is_empty()); - assert!(top_delegations.total.is_zero()); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); - assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); - assert_eq!(top_delegations.delegations[0].owner, 2); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - }); -} - -#[test] -fn can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); - }); -} - -#[test] -fn can_delegate_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 4, 10, 0, 2)); - }); -} - -#[test] -fn cannot_delegate_if_full_and_new_delegation_less_than_or_equal_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 10, 8, 0), - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - }); -} - -#[test] -fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 11), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 11, 8, 0)); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); - }); -} - -#[test] -fn can_still_delegate_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 3, 10, 0, 1),); - }); -} - -#[test] -fn cannot_delegate_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0), - Error::::CandidateExists - ); - }); -} - -#[test] -fn cannot_delegate_if_already_delegated() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 1), - Error::::AlreadyDelegatedCandidate - ); - }); -} - -#[test] -fn cannot_delegate_more_than_max_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 6, 10, 0, 4), - Error::::ExceedMaxDelegationsPerDelegator, - ); - }); -} - -#[test] -fn sufficient_delegate_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for (count, i) in (7..11).enumerate() { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count as u32, - 0u32 - )); - } - for (count, i) in (3..11).enumerate() { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 2, - 10, - count as u32, - 1u32 - )); - } - }); -} - -#[test] -fn insufficient_delegate_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - let mut count = 3u32; - for i in 7..11 { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32), - Error::::TooLowCandidateDelegationCountToDelegate - ); - } - // to set up for next error test - count = 4u32; - for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); - count += 1u32; - } - count = 0u32; - for i in 3..11 { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 0u32), - Error::::TooLowDelegationCountToDelegate - ); - count += 1u32; - } - }); -} - -// SCHEDULE LEAVE DELEGATORS - -#[test] -fn schedule_leave_delegators_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); - }); -} - -#[test] -fn cannot_schedule_leave_delegators_if_already_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorAlreadyLeaving - ); - }); -} - -#[test] -fn cannot_schedule_leave_delegators_if_not_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorDNE - ); - }); -} - -// EXECUTE LEAVE DELEGATORS - -#[test] -fn execute_leave_delegators_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - }); -} - -#[test] -fn execute_leave_delegators_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 00); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - assert_eq!(crate::mock::query_lock_amount(2, DELEGATOR_LOCK_ID), None); - }); -} - -#[test] -fn execute_leave_delegators_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_eq!(ParachainStaking::total(), 30); - }); -} - -#[test] -fn execute_leave_delegators_removes_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_some()); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert!(ParachainStaking::delegator_state(2).is_none()); - }); -} - -#[test] -fn execute_leave_delegators_removes_pending_delegation_requests() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 15)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert!(ParachainStaking::delegator_state(2).is_none()); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation request not removed" - ) - }); -} - -#[test] -fn execute_leave_delegators_removes_delegations_from_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(2, 20), (3, 20), (4, 20), (5, 20)]) - .with_delegations(vec![(1, 2, 10), (1, 3, 10), (1, 4, 10), (1, 5, 10)]) - .build() - .execute_with(|| { - for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); - assert_eq!(top_delegations.delegations[0].owner, 1); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - } - assert_eq!(ParachainStaking::delegator_state(1).unwrap().delegations.0.len(), 4usize); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(1))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(1), 1, 10)); - for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); - assert_eq!(candidate_state.total_counted, 20); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); - assert!(top_delegations.delegations.is_empty()); - } - }); -} - -#[test] -fn cannot_execute_leave_delegators_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorCannotLeaveYet - ); - // can execute after delay - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - }); -} - -#[test] -fn cannot_execute_leave_delegators_if_single_delegation_revoke_manually_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); - roll_to(10); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2), - Error::::DelegatorNotLeaving - ); - // can execute after manually scheduling revoke, and the round delay after which - // all revokes can be executed - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - roll_to(20); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); - }); -} - -#[test] -fn insufficient_execute_leave_delegators_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for i in 3..7 { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); - } - roll_to(10); - for i in 3..7 { - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 0), - Error::::TooLowDelegationCountToLeaveDelegators - ); - } - }); -} - -#[test] -fn sufficient_execute_leave_delegators_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for i in 3..7 { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); - } - roll_to(10); - for i in 3..7 { - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(i), - i, - 1 - )); - } - }); -} - -// CANCEL LEAVE DELEGATORS - -#[test] -fn cancel_leave_delegators_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_emitted!(Event::DelegatorExitCancelled { delegator: 2 }); - }); -} - -#[test] -fn cancel_leave_delegators_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - let delegator = - ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); - assert!(delegator.is_active()); - }); -} - -#[test] -fn cannot_cancel_leave_delegators_if_single_delegation_revoke_manually_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); - roll_to(10); - assert_noop!( - ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorNotLeaving - ); - // can execute after manually scheduling revoke, without waiting for round delay after - // which all revokes can be executed - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - }); -} - -// SCHEDULE REVOKE DELEGATION - -#[test] -fn revoke_delegation_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - roll_to_round_begin(3); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_eq!( - Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }, - Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, - ); - }); -} - -#[test] -fn can_revoke_delegation_if_revoking_another_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - // this is an exit implicitly because last delegation revoked - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - }); -} - -#[test] -fn delegator_not_allowed_revoke_if_already_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), - >::PendingDelegationRequestAlreadyExists, - ); - }); -} - -#[test] -fn cannot_revoke_delegation_if_not_delegator() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1), - Error::::DelegatorDNE - ); - }); -} - -#[test] -fn cannot_revoke_delegation_that_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), - Error::::DelegationDNE - ); - }); -} - -#[test] -// See `cannot_execute_revoke_delegation_below_min_delegator_stake` for where the "must be above -// MinDelegatorStk" rule is now enforced. -fn can_schedule_revoke_delegation_below_min_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 8), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - }); -} - -// DELEGATOR BOND MORE - -#[test] -fn delegator_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); -} - -#[test] -fn delegator_bond_more_increases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::total(), 45); - }); -} - -#[test] -fn delegator_bond_more_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 15); - }); -} - -#[test] -fn delegator_bond_more_updates_candidate_state_top_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 15); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 15); - }); -} - -#[test] -fn delegator_bond_more_updates_candidate_state_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 20), (4, 1, 20), (5, 1, 20), (6, 1, 20)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, - 10 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_events_eq!(Event::DelegationIncreased { - delegator: 2, - candidate: 1, - amount: 5, - in_top: false - }); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, - 15 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); - }); -} - -#[test] -fn delegator_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::total(), 45); - }); -} - -#[test] -fn can_delegator_bond_more_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - }); -} - -#[test] -fn delegator_bond_more_disallowed_when_revoke_scheduled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_noop!( - ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5), - >::PendingDelegationRevoke - ); - }); -} - -#[test] -fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5, - )); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - }); -} - -// DELEGATOR BOND LESS - -#[test] -fn delegator_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - delegator: 2, - candidate: 1, - amount_to_decrease: 5, - execute_round: 3, - }); - }); -} - -#[test] -fn delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - }); -} - -#[test] -fn delegator_not_allowed_bond_less_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), - >::PendingDelegationRequestAlreadyExists, - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), - Error::::PendingDelegationRequestAlreadyExists - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_not_delegator() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5), - Error::::DelegatorDNE - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_candidate_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), - Error::::DelegationDNE - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_delegation_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), - Error::::DelegationDNE - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_below_min_collator_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 6), - Error::::DelegatorBondBelowMin - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_more_than_total_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 11), - Error::::DelegatorBondBelowMin - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_below_min_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 8), - Error::::DelegationBelowMin - ); - }); -} - -// EXECUTE PENDING DELEGATION REQUEST - -// 1. REVOKE DELEGATION - -#[test] -fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { - // last delegation is revocation - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - }); -} - -#[test] -fn cannot_execute_revoke_delegation_below_min_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 8), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_noop!( - ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorBondBelowMin - ); - // but delegator can cancel the request and request to leave instead: - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(20); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); - }); -} - -#[test] -fn revoke_delegation_executes_exit_if_last_delegation() { - // last delegation is revocation - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - }); -} - -#[test] -fn execute_revoke_delegation_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - }); -} - -#[test] -fn execute_revoke_delegation_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - }); -} - -#[test] -fn execute_revoke_delegation_adds_revocation_to_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2) - ); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert!( - ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2) - ); - }); -} - -#[test] -fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execution() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2) - ); - }); -} - -#[test] -fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation_leave() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation was not removed" - ); - }); -} - -#[test] -fn execute_revoke_delegation_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 30); - }); -} - -#[test] -fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_some()); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - // this will be confusing for people - // if status is leaving, then execute_delegation_request works if last delegation - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::delegator_state(2).is_none()); - }); -} - -#[test] -fn execute_revoke_delegation_removes_delegation_from_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_info(1).expect("exists").delegation_count, 1u32); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - ParachainStaking::candidate_info(1).expect("exists").delegation_count.is_zero() - ); - }); -} - -#[test] -fn can_execute_revoke_delegation_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - // can execute delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); -} - -#[test] -fn can_execute_leave_candidates_if_revoking_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - // revocation executes during execute leave candidates (callable by anyone) - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); - assert!(!ParachainStaking::is_delegator(&2)); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::free_balance(&2), 10); - }); -} - -#[test] -fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 3, 10)); - roll_to(100); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::is_delegator(&2)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - }); -} - -#[test] -fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), - Error::::PendingDelegationRequestAlreadyExists - ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 3, - 2 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); - assert_events_eq!( - Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30, - }, - Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, - Event::DelegationDecreased { delegator: 2, candidate: 3, amount: 2, in_top: true }, - ); - assert!(ParachainStaking::is_delegator(&2)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 22); - }); -} - -// 2. EXECUTE BOND LESS - -#[test] -fn execute_delegator_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); - }); -} - -#[test] -fn execute_delegator_bond_less_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 35); - }); -} - -#[test] -fn execute_delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 5); - }); -} - -#[test] -fn execute_delegator_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 5); - }); -} - -#[test] -fn execute_delegator_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 35); - }); -} - -#[test] -fn execute_delegator_bond_less_updates_just_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) - .build() - .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let pre_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 2 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let post_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - let mut not_equal = false; - for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_bottom_delegations.delegations - { - if &owner == post_owner && &amount != post_amount { - not_equal = true; - break; - } - } - } - assert!(not_equal); - let mut equal = true; - for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_top_delegations.delegations - { - if &owner == post_owner && &amount != post_amount { - equal = false; - break; - } - } - } - assert!(equal); - assert_eq!( - pre_call_candidate_info.total_counted, - post_call_candidate_info.total_counted - ); - }); -} - -#[test] -fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) - .build() - .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let pre_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 4 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let post_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - let mut equal = true; - for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_bottom_delegations.delegations - { - if &owner == post_owner && &amount != post_amount { - equal = false; - break; - } - } - } - assert!(equal); - let mut not_equal = false; - for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_top_delegations.delegations - { - if &owner == post_owner && &amount != post_amount { - not_equal = true; - break; - } - } - } - assert!(not_equal); - assert_eq!( - pre_call_candidate_info.total_counted - 4, - post_call_candidate_info.total_counted - ); - }); -} - -#[test] -fn can_execute_delegator_bond_less_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - // can execute bond more delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); -} - -// CANCEL PENDING DELEGATION REQUEST -// 1. CANCEL REVOKE DELEGATION - -#[test] -fn cancel_revoke_delegation_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert_events_emitted!(Event::CancelledDelegationRequest { - delegator: 2, - collator: 1, - cancelled_request: CancelledScheduledRequest { - when_executable: 3, - action: DelegationAction::Revoke(10), - }, - }); - }); -} - -#[test] -fn cancel_revoke_delegation_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(10), - }], - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10 - ); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2) - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); -} - -// 2. CANCEL DELEGATOR BOND LESS - -#[test] -fn cancel_delegator_bond_less_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert_events_emitted!(Event::CancelledDelegationRequest { - delegator: 2, - collator: 1, - cancelled_request: CancelledScheduledRequest { - when_executable: 3, - action: DelegationAction::Decrease(5), - }, - }); - }); -} - -#[test] -fn cancel_delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 5 - ); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2) - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); -} - -// ~~ PROPERTY-BASED TESTS ~~ - -#[test] -fn delegator_schedule_revocation_total() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10 - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 5, 10, 0, 2)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 4)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 20, - ); - roll_to(20); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10, - ); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 4 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); -} - -#[ignore] -#[test] -fn parachain_bond_inflation_reserve_matches_config() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - (11, 1), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(Balances::free_balance(&11), 1); - // set parachain bond account so DefaultParachainBondReservePercent = 30% of inflation - // is allocated to this account hereafter - assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); - assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, - ); - assert_eq!(Balances::free_balance(&11), 1); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - // distribute total issuance to collator 1 and its delegators 6, 7, 19 - assert_eq!(Balances::free_balance(&11), 16); - // ~ set block author as 1 for all blocks this round - set_author(3, 1, 100); - set_author(4, 1, 100); - set_author(5, 1, 100); - // 1. ensure delegators are paid for 2 rounds after they leave - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), - Error::::DelegatorDNE - ); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 15 }, - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 5, - total_balance: 140, - }, - Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 20 }, - Event::Rewarded { account: 6, rewards: 5 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - // fast forward to block in which delegator 6 exit executes - roll_to_round_begin(5); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 16 }, - Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 5, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 21 }, - Event::Rewarded { account: 6, rewards: 5 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - roll_to_round_begin(6); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 16 }, - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 6, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 140, - }, - Event::DelegatorLeftCandidate { - delegator: 6, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 40, - }, - Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 22 }, - Event::Rewarded { account: 6, rewards: 6 }, - Event::Rewarded { account: 7, rewards: 6 }, - Event::Rewarded { account: 10, rewards: 6 }, - ); - roll_to_round_begin(7); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 17 }, - Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 26 }, - Event::Rewarded { account: 7, rewards: 7 }, - Event::Rewarded { account: 10, rewards: 7 }, - ); - assert_eq!(Balances::free_balance(&11), 65); - roll_blocks(1); - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_events_eq!(Event::ParachainBondReservePercentSet { - old: Percent::from_percent(30), - new: Percent::from_percent(50), - }); - // 6 won't be paid for this round because they left already - set_author(6, 1, 100); - roll_to_round_begin(8); - // keep paying 6 - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 30 }, - Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 8, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 21 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 95); - set_author(7, 1, 100); - roll_to_round_begin(9); - // no more paying 6 - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 32 }, - Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 9, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 22 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 127); - set_author(8, 1, 100); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); - assert_events_eq!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - roll_to_round_begin(10); - // new delegation is not rewarded yet - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 33 }, - Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 10, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 23 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 160); - set_author(9, 1, 100); - set_author(10, 1, 100); - roll_to_round_begin(11); - // new delegation is still not rewarded yet - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 35 }, - Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 11, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 24 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 195); - roll_to_round_begin(12); - // new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2) - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 37 }, - Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 12, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 24 }, - Event::Rewarded { account: 7, rewards: 4 }, - Event::Rewarded { account: 10, rewards: 4 }, - Event::Rewarded { account: 8, rewards: 4 }, - ); - assert_eq!(Balances::free_balance(&11), 232); - }); -} - -#[test] -fn paid_collator_commission_matches_config() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(4), 20u128, 100u32)); - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 1, - total_balance: 40, - }, - Event::JoinedCollatorCandidates { - account: 4, - amount_locked: 20, - new_total_amt_locked: 60, - }, - ); - - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 4, 10, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); - assert_events_eq!( - Event::Delegation { - delegator: 5, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }, - ); - - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 3, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 80, - }, - ); - // only reward author with id 4 - set_author(3, 4, 100); - roll_to_round_begin(5); - // 20% of 10 is commission + due_portion (0) = 2 + 4 = 6 - // all delegator payouts are 10-2 = 8 * stake_pct - assert_events_eq!( - Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 2, - total_balance: 80, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 4, rewards: 18 }, - Event::Rewarded { account: 5, rewards: 6 }, - Event::Rewarded { account: 6, rewards: 6 }, - ); - }); -} - -#[test] -fn collator_exit_executes_after_delay() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - roll_to(11); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 3, - candidate: 2, - scheduled_exit: 5, - }); - let info = ParachainStaking::candidate_info(&2).unwrap(); - assert_eq!(info.status, CollatorStatus::Leaving(5)); - roll_to(21); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); - // we must exclude leaving collators from rewards while - // holding them retroactively accountable for previous faults - // (within the last T::SlashingWindow blocks) - assert_events_eq!(Event::CandidateLeft { - ex_candidate: 2, - unlocked_amount: 400, - new_total_amt_locked: 700, - },); - }); -} - -#[test] -fn collator_selection_chooses_top_candidates() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 33), - (8, 33), - (9, 33), - ]) - .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(6), 6)); - // should choose top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, - Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 60 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 400, - }, - Event::CandidateScheduledExit { - exit_allowed_round: 2, - candidate: 6, - scheduled_exit: 4 - }, - ); - roll_to_round_begin(4); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(6), 6, 0)); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 69u128, 100u32)); - assert_events_eq!( - Event::CandidateLeft { - ex_candidate: 6, - unlocked_amount: 50, - new_total_amt_locked: 400, - }, - Event::JoinedCollatorCandidates { - account: 6, - amount_locked: 69u128, - new_total_amt_locked: 469u128, - }, - ); - roll_to_round_begin(6); - // should choose top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, - Event::CollatorChosen { round: 6, collator_account: 6, total_exposed_amount: 69 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 409, - }, - ); - }); -} - -#[test] -fn payout_distribution_to_solo_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 1000), (2, 1000), (3, 1000), (4, 1000), (7, 33), (8, 33), (9, 33)]) - .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // should choose top TotalCandidatesSelected (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 340, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 340, - }, - ); - // pay total issuance to 1 at 2nd block - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 205 }); - // ~ set block author as 1 for 3 blocks this round - set_author(4, 1, 60); - // ~ set block author as 2 for 2 blocks this round - set_author(4, 2, 40); - roll_to_round_begin(6); - // pay 60% total issuance to 1 and 40% total issuance to 2 - assert_events_eq!( - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 340, - }, - ); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 129 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 86 },); - // ~ each collator produces 1 block this round - set_author(6, 1, 20); - set_author(6, 2, 20); - set_author(6, 3, 20); - set_author(6, 4, 20); - roll_to_round_begin(8); - // pay 20% issuance for all collators - assert_events_eq!( - Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 340, - }, - ); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 3, rewards: 56 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 4, rewards: 56 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 56 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 56 }); - // check that distributing rewards clears awarded pts - assert!(ParachainStaking::awarded_pts(1, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(4, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(4, 2).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 2).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 3).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 4).is_zero()); - }); -} - -#[test] -fn multiple_delegations() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 2, 10, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 3, 10, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); - assert_events_eq!( - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 2, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 3, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - ); - roll_to_round_begin(6); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 2, 80, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 2, 10, 10, 10)); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 5)); - assert_events_eq!( - Event::Delegation { - delegator: 7, - locked_amount: 80, - candidate: 2, - delegator_position: DelegatorAdded::AddedToTop { new_total: 130 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 10, - locked_amount: 10, - candidate: 2, - delegator_position: DelegatorAdded::AddedToBottom, - auto_compound: Percent::zero(), - }, - Event::CandidateScheduledExit { - exit_allowed_round: 6, - candidate: 2, - scheduled_exit: 8 - }, - ); - roll_to_round_begin(7); - assert_events_eq!( - Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 30 }, - Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 30 }, - Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, - ); - // verify that delegations are removed after collator leaves, not before - assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 2usize); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 40); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 4usize); - assert_eq!(Balances::locks(&6)[0].amount, 40); - assert_eq!(Balances::locks(&7)[0].amount, 90); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 60); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 10); - roll_to_round_begin(8); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 5)); - assert_events_eq!(Event::CandidateLeft { - ex_candidate: 2, - unlocked_amount: 140, - new_total_amt_locked: 120, - }); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 10); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 30); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 1usize); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 3usize); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 70); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 90); - }); -} - -#[test] -// The test verifies that the pending revoke request is removed by 2's exit so there is no dangling -// revoke request after 2 exits -fn execute_leave_candidate_removes_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (3, 2, 10), (4, 1, 10), (4, 2, 10)]) - .build() - .execute_with(|| { - // Verifies the revocation request is initially empty - assert!( - !ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3) - ); - - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); - // Verifies the revocation request is present - assert!( - ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3) - ); - - roll_to(16); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); - // Verifies the revocation request is again empty - assert!( - !ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3) - ); - }); -} - -#[test] -fn payouts_follow_delegation_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 130, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - // distribute total issuance to collator 1 and its delegators 6, 7, 19 - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 23 }, - Event::Rewarded { account: 6, rewards: 7 }, - Event::Rewarded { account: 7, rewards: 7 }, - Event::Rewarded { account: 10, rewards: 7 }, - ); - // ~ set block author as 1 for all blocks this round - set_author(3, 1, 100); - set_author(4, 1, 100); - set_author(5, 1, 100); - set_author(6, 1, 100); - - roll_blocks(1); - // 1. ensure delegators are paid for 2 rounds after they leave - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), - Error::::DelegatorDNE - ); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 4, - delegator: 6, - scheduled_exit: 6, - }); - // fast forward to block in which delegator 6 exit executes - roll_to_round_begin(5); - assert_events_eq!( - Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 24 }, - Event::Rewarded { account: 6, rewards: 8 }, - Event::Rewarded { account: 7, rewards: 8 }, - Event::Rewarded { account: 10, rewards: 8 }, - ); - // keep paying 6 (note: inflation is in terms of total issuance so that's why 1 is 21) - roll_to_round_begin(6); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); - assert_events_eq!( - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 130, - }, - Event::DelegatorLeftCandidate { - delegator: 6, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 40, - }, - Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 26 }, - Event::Rewarded { account: 6, rewards: 8 }, - Event::Rewarded { account: 7, rewards: 8 }, - Event::Rewarded { account: 10, rewards: 8 }, - ); - // 6 won't be paid for this round because they left already - set_author(7, 1, 100); - roll_to_round_begin(7); - // keep paying 6 - assert_events_eq!( - Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 31 }, - Event::Rewarded { account: 7, rewards: 10 }, - Event::Rewarded { account: 10, rewards: 10 }, - ); - roll_to_round_begin(8); - assert_events_eq!( - Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 33 }, - Event::Rewarded { account: 7, rewards: 11 }, - Event::Rewarded { account: 10, rewards: 11 }, - ); - set_author(8, 1, 100); - roll_to_round_begin(9); - // no more paying 6 - assert_events_eq!( - Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 34 }, - Event::Rewarded { account: 7, rewards: 11 }, - Event::Rewarded { account: 10, rewards: 11 }, - ); - roll_blocks(1); - set_author(9, 1, 100); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); - assert_events_eq!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - - roll_to_round_begin(10); - // new delegation is not rewarded yet - assert_events_eq!( - Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 36 }, - Event::Rewarded { account: 7, rewards: 12 }, - Event::Rewarded { account: 10, rewards: 12 }, - ); - set_author(10, 1, 100); - roll_to_round_begin(11); - // new delegation not rewarded yet - assert_events_eq!( - Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 38 }, - Event::Rewarded { account: 7, rewards: 12 }, - Event::Rewarded { account: 10, rewards: 12 }, - ); - roll_to_round_begin(12); - // new delegation is rewarded for first time - // 2 rounds after joining (`RewardPaymentDelay` = 2) - assert_events_eq!( - Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 34 }, - Event::Rewarded { account: 7, rewards: 11 }, - Event::Rewarded { account: 10, rewards: 11 }, - Event::Rewarded { account: 8, rewards: 11 }, - ); - }); -} - -#[test] -fn bottom_delegations_are_empty_when_top_delegations_not_full() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 10), (4, 10), (5, 10)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // no top delegators => no bottom delegators - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert!(top_delegations.delegations.is_empty()); - assert!(bottom_delegations.delegations.is_empty()); - // 1 delegator => 1 top delegator, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 1usize); - assert!(bottom_delegations.delegations.is_empty()); - // 2 delegators => 2 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(3), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 2usize); - assert!(bottom_delegations.delegations.is_empty()); - // 3 delegators => 3 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(4), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 3usize); - assert!(bottom_delegations.delegations.is_empty()); - // 4 delegators => 4 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 4usize); - assert!(bottom_delegations.delegations.is_empty()); - }); -} - -#[test] -fn candidate_pool_updates_when_total_counted_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (3, 1, 11), - (4, 1, 12), - (5, 1, 13), - (6, 1, 14), - (7, 1, 15), - (8, 1, 16), - (9, 1, 17), - (10, 1, 18), - ]) - .build() - .execute_with(|| { - fn is_candidate_pool_bond(account: u64, bond: u128) { - let pool = ParachainStaking::candidate_pool(); - for candidate in pool.0 { - if candidate.owner == account { - assert_eq!( - candidate.amount, bond, - "Candidate Bond {:?} is Not Equal to Expected: {:?}", - candidate.amount, bond - ); - } - } - } - // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) - is_candidate_pool_bond(1, 86); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); - // 3: 11 -> 19 => 3 is in top, bumps out 7 - // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) - is_candidate_pool_bond(1, 90); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); - // 4: 12 -> 20 => 4 is in top, bumps out 8 - // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) - is_candidate_pool_bond(1, 94); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(10), - 1, - 3 - )); - roll_to(30); - // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(10), - 10, - 1 - )); - // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) - is_candidate_pool_bond(1, 92); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(9), - 1, - 4 - )); - roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(9), - 9, - 1 - )); - // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) - is_candidate_pool_bond(1, 90); - }); -} - -#[test] -fn only_top_collators_are_counted() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (3, 1, 11), - (4, 1, 12), - (5, 1, 13), - (6, 1, 14), - (7, 1, 15), - (8, 1, 16), - (9, 1, 17), - (10, 1, 18), - ]) - .build() - .execute_with(|| { - // sanity check that 3-10 are delegators immediately - for i in 3..11 { - assert!(ParachainStaking::is_delegator(&i)); - } - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 86); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 90); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 4, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 94); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(5), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 5, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 98); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 6, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 102); - }); -} - -#[test] -fn delegation_events_convey_correct_position() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 11), (4, 1, 12), (5, 1, 13), (6, 1, 14)]) - .build() - .execute_with(|| { - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 11 + 12 + 13 + 14 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 70); - // Top delegations are full, new highest delegation is made - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 1, 15, 10, 10)); - assert_events_emitted!(Event::Delegation { - delegator: 7, - locked_amount: 15, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 74 }, - auto_compound: Percent::zero(), - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 74); - // New delegation is added to the bottom - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); - assert_events_emitted!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToBottom, - auto_compound: Percent::zero(), - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 74); - // 8 increases delegation to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(8), 1, 3)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 8, - candidate: 1, - amount: 3, - in_top: true, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 75); - // 3 increases delegation but stays in bottom - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 1)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 1, - in_top: false, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 75); - // 6 decreases delegation but stays in top - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 2 - )); - assert_events_emitted!(Event::DelegationDecreaseScheduled { - delegator: 6, - candidate: 1, - amount_to_decrease: 2, - execute_round: 3, - }); - roll_to(30); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 2, - in_top: true, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ - assert_eq!(collator1_state.total_counted, 73); - // 6 decreases delegation and is bumped to bottom - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 1 - )); - assert_events_emitted!(Event::DelegationDecreaseScheduled { - delegator: 6, - candidate: 1, - amount_to_decrease: 1, - execute_round: 9, - }); - roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 1, - in_top: false, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 73); - }); -} - -#[test] -fn no_rewards_paid_until_after_reward_payment_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // payouts for round 1 - set_author(1, 1, 1); - set_author(1, 2, 1); - set_author(1, 2, 1); - set_author(1, 3, 1); - set_author(1, 3, 1); - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 3, - total_balance: 60, - }, - ); - - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 3, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 3, - total_balance: 60, - }, - ); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 3, rewards: 1 }); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 }); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 }); - - // there should be no more payments in this round... - let num_blocks_rolled = roll_to_round_end(3); - assert_no_events!(); - assert_eq!(num_blocks_rolled, 1); - }); -} - -#[test] -fn deferred_payment_storage_items_are_cleaned_up() { - use crate::*; - - // this test sets up two collators, gives them points in round one, and focuses on the - // storage over the next several blocks to show that it is properly cleaned up - - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - set_author(1, 1, 1); - set_author(1, 2, 1); - - // reflects genesis? - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - roll_to_round_begin(2); - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - // we should have AtStake snapshots as soon as we start a round... - assert!(>::contains_key(2, 1)); - assert!(>::contains_key(2, 2)); - // ...and it should persist until the round is fully paid out - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - assert!( - !>::contains_key(1), - "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" - ); - assert!( - >::contains_key(1), - "Points should be populated during current round" - ); - assert!( - >::contains_key(1), - "Staked should be populated when round changes" - ); - - assert!( - !>::contains_key(2), - "Points should not be populated until author noted" - ); - assert!( - >::contains_key(2), - "Staked should be populated when round changes" - ); - - // first payout occurs in round 3 - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 },); - - // payouts should exist for past rounds that haven't been paid out yet.. - assert!(>::contains_key(3, 1)); - assert!(>::contains_key(3, 2)); - assert!(>::contains_key(2, 1)); - assert!(>::contains_key(2, 2)); - - assert!( - >::contains_key(1), - "DelayedPayouts should be populated after RewardPaymentDelay" - ); - assert!(>::contains_key(1)); - assert!( - !>::contains_key(1), - "Staked should be cleaned up after round change" - ); - - assert!(!>::contains_key(2)); - assert!(!>::contains_key(2), "We never rewarded points for round 2"); - assert!(>::contains_key(2)); - - assert!(!>::contains_key(3)); - assert!(!>::contains_key(3), "We never awarded points for round 3"); - assert!(>::contains_key(3)); - - // collator 1 has been paid in this last block and associated storage cleaned up - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 1)); - - // but collator 2 hasn't been paid - assert!(>::contains_key(1, 2)); - assert!(>::contains_key(1, 2)); - - // second payout occurs in next block - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 },); - - roll_to_round_begin(4); - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - // collators have both been paid and storage fully cleaned up for round 1 - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); // points should be cleaned up - assert!(!>::contains_key(1)); - - roll_to_round_end(4); - - // no more events expected - assert_no_events!(); - }); -} - -#[test] -fn deferred_payment_and_at_stake_storage_items_cleaned_up_for_candidates_not_producing_blocks() { - use crate::*; - - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) - .build() - .execute_with(|| { - // candidate 3 will not produce blocks - set_author(1, 1, 1); - set_author(1, 2, 1); - - // reflects genesis? - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - roll_to_round_begin(2); - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - assert!(>::contains_key(1, 3)); - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(>::contains_key(1)); - assert!(>::contains_key(1)); - roll_to_round_begin(3); - assert!(>::contains_key(1)); - - // all storage items must be cleaned up - roll_to_round_begin(4); - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); - }); -} - -#[test] -fn deferred_payment_steady_state_event_flow() { - use frame_support::traits::{Currency, ExistenceRequirement, WithdrawReasons}; - - // this test "flows" through a number of rounds, asserting that certain things do/don't happen - // once the staking pallet is in a "steady state" (specifically, once we are past the first few - // rounds to clear RewardPaymentDelay) - - ExtBuilder::default() - .with_balances(vec![ - // collators - (1, 200), - (2, 200), - (3, 200), - (4, 200), - // delegators - (11, 200), - (22, 200), - (33, 200), - (44, 200), - // burn account, see `reset_issuance()` - (111, 1000), - ]) - .with_candidates(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) - .with_delegations(vec![ - // delegator 11 delegates 100 to 1 and 2 - (11, 1, 100), - (11, 2, 100), - // delegator 22 delegates 100 to 2 and 3 - (22, 2, 100), - (22, 3, 100), - // delegator 33 delegates 100 to 3 and 4 - (33, 3, 100), - (33, 4, 100), - // delegator 44 delegates 100 to 4 and 1 - (44, 4, 100), - (44, 1, 100), - ]) - .build() - .execute_with(|| { - // convenience to set the round points consistently - let set_round_points = |round: BlockNumber| { - set_author(round as BlockNumber, 1, 1); - set_author(round as BlockNumber, 2, 1); - set_author(round as BlockNumber, 3, 1); - set_author(round as BlockNumber, 4, 1); - }; - - // grab initial issuance -- we will reset it before round issuance is calculated so that - // it is consistent every round - let initial_issuance = Balances::total_issuance(); - let reset_issuance = || { - let new_issuance = Balances::total_issuance(); - let diff = new_issuance - initial_issuance; - let burned = Balances::burn(diff); - Balances::settle( - &111, - burned, - WithdrawReasons::FEE, - ExistenceRequirement::AllowDeath, - ) - .expect("Account can absorb burn"); - }; - - // fn to roll through the first RewardPaymentDelay rounds. returns new round index - let roll_through_initial_rounds = |mut round: BlockNumber| -> BlockNumber { - while round < crate::mock::RewardPaymentDelay::get() + 1 { - set_round_points(round); - - roll_to_round_end(round); - round += 1; - } - - reset_issuance(); - - round - }; - - // roll through a "steady state" round and make all of our assertions - // returns new round index - let roll_through_steady_state_round = |round: BlockNumber| -> BlockNumber { - let num_rounds_rolled = roll_to_round_begin(round); - assert!(num_rounds_rolled <= 1, "expected to be at round begin already"); - - assert_events_eq!( - Event::CollatorChosen { - round: round as u32, - collator_account: 1, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 2, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 3, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 4, - total_exposed_amount: 400, - }, - Event::NewRound { - starting_block: (round - 1) * 5, - round: round as u32, - selected_collators_number: 4, - total_balance: 1600, - }, - ); - - set_round_points(round); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 3, rewards: 19 }, - Event::Rewarded { account: 22, rewards: 6 }, - Event::Rewarded { account: 33, rewards: 6 }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 4, rewards: 19 }, - Event::Rewarded { account: 33, rewards: 6 }, - Event::Rewarded { account: 44, rewards: 6 }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 19 }, - Event::Rewarded { account: 11, rewards: 6 }, - Event::Rewarded { account: 44, rewards: 6 }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 2, rewards: 19 }, - Event::Rewarded { account: 11, rewards: 6 }, - Event::Rewarded { account: 22, rewards: 6 }, - ); - - roll_blocks(1); - // Since we defer first deferred staking payout, this test have the maximum amout of - // supported collators. This eman that the next round is trigerred one block after - // the last reward. - //assert_no_events!(); - - let num_rounds_rolled = roll_to_round_end(round); - assert_eq!(num_rounds_rolled, 0, "expected to be at round end already"); - - reset_issuance(); - - round + 1 - }; - - let mut round = 1; - round = roll_through_initial_rounds(round); // we should be at RewardPaymentDelay - for _ in 1..2 { - round = roll_through_steady_state_round(round); - } - }); -} - -#[test] -fn delegation_kicked_from_bottom_removes_pending_request() { - ExtBuilder::default() - .with_balances(vec![ - (1, 30), - (2, 29), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 30), - ]) - .with_candidates(vec![(1, 30), (11, 30)]) - .with_delegations(vec![ - (2, 1, 19), - (2, 11, 10), // second delegation so not left after first is kicked - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - (7, 1, 20), - (8, 1, 20), - (9, 1, 20), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - // 10 delegates to full 1 => kicks lowest delegation (2, 19) - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); - // check the event - assert_events_emitted!(Event::DelegationKicked { - delegator: 2, - candidate: 1, - unstaked_amount: 19, - }); - // ensure request DNE - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2) - ); - }); -} - -#[test] -fn no_selected_candidates_defaults_to_last_round_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) - .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) - .build() - .execute_with(|| { - roll_to_round_begin(1); - // schedule to leave - for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - 5 - )); - } - let old_round = ParachainStaking::round().current; - let old_selected_candidates = ParachainStaking::selected_candidates(); - let mut old_at_stake_snapshots = Vec::new(); - for account in old_selected_candidates.clone() { - old_at_stake_snapshots.push(>::get(old_round, account)); - } - roll_to_round_begin(3); - // execute leave - for i in 1..6 { - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(i), - i, - 0, - )); - } - // next round - roll_to_round_begin(4); - let new_round = ParachainStaking::round().current; - // check AtStake matches previous - let new_selected_candidates = ParachainStaking::selected_candidates(); - assert_eq!(old_selected_candidates, new_selected_candidates); - for (index, account) in new_selected_candidates.into_iter().enumerate() { - assert_eq!(old_at_stake_snapshots[index], >::get(new_round, account)); - } - }); -} - -#[test] -fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() -{ - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - execute_round: 3, - delegator: 2, - candidate: 1, - amount_to_decrease: 10, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 3 }, - Event::Rewarded { account: 2, rewards: 2 }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - execute_round: 3, - delegator: 2, - candidate: 1, - amount_to_decrease: 10, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 40, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 3 }, - Event::Rewarded { account: 2, rewards: 2 }, - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2),)); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - }); -} - -#[test] -fn test_delegation_request_exists_returns_false_when_nothing_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_request_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_exists_returns_true_when_decrease_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert!(ParachainStaking::delegation_request_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_exists_returns_true_when_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], - ); - assert!(ParachainStaking::delegation_request_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_revoke_exists_returns_false_when_nothing_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], - ); - assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3, 4] // 4 does not exist, but is OK for idempotency - )); - - assert!(!>::contains_key(2)); - assert!(!>::contains_key(3)); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2] - )); - - assert!(!>::contains_key(2)); - assert!(>::contains_key(3)); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - vec![ScheduledRequest { - delegator: 10, - when_executable: 1, - action: DelegationAction::Revoke(10), - }], - ); - - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3] - ), - >::CandidateNotLeaving, - ); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 1, - Vec::>::new(), - ); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![1] - ), - >::CandidateNotLeaving, - ); - }); -} - -#[test] -fn locking_zero_amount_is_ignored() { - use frame_support::traits::{LockableCurrency, WithdrawReasons}; - - // this test demonstrates the behavior of pallet Balance's `LockableCurrency` implementation of - // `set_locks()` when an amount of 0 is provided: it is a no-op - - ExtBuilder::default().with_balances(vec![(1, 100)]).build().execute_with(|| { - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), None); - - Balances::set_lock(DELEGATOR_LOCK_ID, &1, 1, WithdrawReasons::all()); - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); - - Balances::set_lock(DELEGATOR_LOCK_ID, &1, 0, WithdrawReasons::all()); - // Note that we tried to call `set_lock(0)` and it ignored it, we still have our lock - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); - }); -} - -#[test] -fn revoke_last_removes_lock() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100)]) - .with_candidates(vec![(1, 25), (2, 25)]) - .with_delegations(vec![(3, 1, 30), (3, 2, 25)]) - .build() - .execute_with(|| { - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(55)); - - // schedule and remove one... - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 1)); - roll_to_round_begin(3); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 1 - )); - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(25)); - - // schedule and remove the other... - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); - roll_to_round_begin(5); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 2 - )); - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert!( - >::get(1) - .iter() - .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_))) - ); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); - - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_can_cancel_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitCancelled { delegator: 2 }); - - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_can_execute_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - - let state = >::get(2); - assert!(state.is_none()); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_cannot_execute_leave_delegators_early_no_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorCannotLeaveYet - ); - }); -} - -#[test] -fn test_set_auto_compound_fails_if_invalid_delegation_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; // is however, 1 - - assert_noop!( - ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowDelegationCountToAutoCompound, - ); - }); -} - -#[test] -fn test_set_auto_compound_fails_if_invalid_candidate_auto_compounding_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new(vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(10), - }]) - .set_storage(&1); - let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 - let delegation_hint = 1; - - assert_noop!( - ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - ); - }); -} - -#[test] -fn test_set_auto_compound_inserts_if_not_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], - ParachainStaking::auto_compounding_delegations(&1), - ); - }); -} - -#[test] -fn test_set_auto_compound_updates_if_existing() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new(vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(10), - }]) - .set_storage(&1); - - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], - ParachainStaking::auto_compounding_delegations(&1), - ); - }); -} - -#[test] -fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new(vec![AutoCompoundConfig { - delegator: 2, - value: Percent::from_percent(10), - }]) - .set_storage(&1); - - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::zero(), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::zero(), - }); - assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); - }); -} - -#[test] -fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delegation_revoke() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), - "delegation auto-compound config was erroneously removed" - ); - }); -} - -#[test] -fn test_execute_leave_delegators_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); -} - -#[allow(deprecated)] -#[test] -fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); -} - -#[test] -fn test_execute_leave_candidates_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 2)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1,)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), - "delegation auto-compound config was erroneously removed" - ); - }); -} - -#[test] -fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![ - (1, 30), - (2, 29), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 30), - ]) - .with_candidates(vec![(1, 30), (11, 30)]) - .with_delegations(vec![ - (2, 11, 10), // extra delegation to avoid leaving the delegator set - (2, 1, 19), - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - (7, 1, 20), - (8, 1, 20), - (9, 1, 20), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - - // kicks lowest delegation (2, 19) - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); -} - -#[test] -fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 200), (3, 200)]) - .with_candidates(vec![(1, 100)]) - .with_delegations(vec![(2, 1, 200), (3, 1, 200)]) - .build() - .execute_with(|| { - (2..=5).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(3), - 1, - Percent::from_percent(50), - 1, - 1, - )); - roll_to_round_begin(3); - - // schedule revoke for delegator 2; no rewards should be compounded - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to_round_begin(4); - - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 500 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 500, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 9 }, - // no compound since revoke request exists - Event::Rewarded { account: 2, rewards: 8 }, - // 50% - Event::Rewarded { account: 3, rewards: 8 }, - Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, - ); - }); -} - -#[test] -fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 200), (3, 200), (4, 200), (5, 200)]) - .with_candidates(vec![(1, 100)]) - .with_delegations(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) - .build() - .execute_with(|| { - (2..=6).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(0), - 0, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(3), - 1, - Percent::from_percent(50), - 1, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(4), - 1, - Percent::from_percent(100), - 2, - 1, - )); - roll_to_round_begin(4); - - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 900 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 900, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 13 }, - // 0% - Event::Rewarded { account: 2, rewards: 8 }, - // 50% - Event::Rewarded { account: 3, rewards: 8 }, - Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, - // 100% - Event::Rewarded { account: 4, rewards: 8 }, - Event::Compounded { candidate: 1, delegator: 4, amount: 8 }, - // no-config - Event::Rewarded { account: 5, rewards: 8 }, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_fails_if_invalid_delegation_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 3, 10)]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 0; - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; // is however, 1 - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowDelegationCountToDelegate, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_fails_if_invalid_candidate_delegation_count_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(3, 1, 10)]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 0; // is however, 1 - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateDelegationCountToDelegate, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_delegations_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(10))]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 1; - let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 - let delegation_hint = 0; - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_sets_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0, - )); - assert_events_emitted!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], - ParachainStaking::auto_compounding_delegations(&1), - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::zero(), - 0, - 0, - 0, - )); - assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }); - }); -} - -#[test] -fn test_delegate_with_auto_compound_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0, - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); -} - -#[test] -fn test_delegate_with_auto_compound_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_none()); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - )); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); - assert_eq!(delegator_state.total(), 10); - assert_eq!(delegator_state.delegations.0[0].owner, 1); - assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); -} - -#[test] -fn test_delegate_with_auto_compound_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); - assert!(top_delegations.delegations.is_empty()); - assert!(top_delegations.total.is_zero()); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - )); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); - assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); - assert_eq!(top_delegations.delegations[0].owner, 2); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 20, - Percent::from_percent(50), - 0, - 0, - 0 - )); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_delegate_to_other_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 4, - 10, - Percent::from_percent(50), - 0, - 0, - 2 - )); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_if_less_than_or_equal_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(11), - 1, - 10, - Percent::from_percent(50), - 8, - 0, - 0 - ), - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 11), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(11), - 1, - 11, - Percent::from_percent(50), - 8, - 0, - 0 - )); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_still_delegate_to_other_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 3, - 10, - Percent::from_percent(50), - 0, - 0, - 1 - ),); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - ), - Error::::CandidateExists - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_if_already_delegated() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 1, - 1 - ), - Error::::AlreadyDelegatedCandidate - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_more_than_max_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 6, - 10, - Percent::from_percent(50), - 0, - 0, - 4 - ), - Error::::ExceedMaxDelegationsPerDelegator, - ); - }); -} - -#[test] -fn test_delegate_skips_auto_compound_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(50))]) - .build() - .execute_with(|| { - // We already have an auto-compounding delegation from 3 -> 1, so the hint validation - // would cause a failure if the auto-compounding isn't skipped properly. - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 0,)); - assert_eq!(1, ParachainStaking::auto_compounding_delegations(&1).len(),); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - }); -} - -#[test] -fn test_on_initialize_weights() { - use crate::{ - mock::System, - weights::{SubstrateWeight as PalletWeights, WeightInfo}, - *, - }; - use frame_support::{pallet_prelude::*, weights::constants::RocksDbWeight}; - - // generate balance, candidate, and delegation vecs to "fill" out delegations - let mut balances = Vec::new(); - let mut candidates = Vec::new(); - let mut delegations = Vec::new(); - - for collator in 1..30 { - balances.push((collator, 100)); - candidates.push((collator, 10)); - let starting_delegator = collator * 1000; - for delegator in starting_delegator..starting_delegator + 300 { - balances.push((delegator, 100)); - delegations.push((delegator, collator, 10)); - } - } - - ExtBuilder::default() - .with_balances(balances) - .with_candidates(candidates) - .with_delegations(delegations) - .build() - .execute_with(|| { - let weight = ParachainStaking::on_initialize(1); - - // TODO: build this with proper db reads/writes - assert_eq!(Weight::from_ref_time(285_890_000), weight); - - // roll to the end of the round, then run on_init again, we should see round change... - roll_to_round_end(3); - set_author(2, 1, 100); // must set some points for prepare_staking_payouts - let block = System::block_number() + 1; - let weight = ParachainStaking::on_initialize(block); - - // the total on_init weight during our round change. this number is taken from running - // the fn with a given weights.rs benchmark, so will need to be updated as benchmarks - // change. - // - // following this assertion, we add individual weights together to show that we can - // derive this number independently. - let expected_on_init = 2_537_230_483; - assert_eq!(Weight::from_ref_time(expected_on_init), weight); - - // assemble weight manually to ensure it is well understood - let mut expected_weight = 0u64; - expected_weight += PalletWeights::::base_on_initialize().ref_time(); - expected_weight += PalletWeights::::prepare_staking_payouts().ref_time(); - - // TODO: this should be the same as >. I believe this relates to - // genesis building - let num_avg_delegations = 8; - expected_weight += PalletWeights::::select_top_candidates( - >::get(), - num_avg_delegations, - ) - .ref_time(); - // Round and Staked writes, done in on-round-change code block inside on_initialize() - expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); - // more reads/writes manually accounted for for on_finalize - expected_weight += RocksDbWeight::get().reads_writes(3, 2).ref_time(); - - assert_eq!(Weight::from_ref_time(expected_weight), weight); - assert_eq!(expected_on_init, expected_weight); // magic number == independent accounting - }); -} diff --git a/external/pallets/parachain-staking/src/traits.rs b/external/pallets/parachain-staking/src/traits.rs deleted file mode 100644 index b343ef3dc..000000000 --- a/external/pallets/parachain-staking/src/traits.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! traits for parachain-staking - -use frame_support::pallet_prelude::Weight; - -pub trait OnCollatorPayout { - fn on_collator_payout( - for_round: crate::RoundIndex, - collator_id: AccountId, - amount: Balance, - ) -> Weight; -} -impl OnCollatorPayout for () { - fn on_collator_payout( - _for_round: crate::RoundIndex, - _collator_id: AccountId, - _amount: Balance, - ) -> Weight { - Weight::zero() - } -} - -pub trait OnNewRound { - fn on_new_round(round_index: crate::RoundIndex) -> Weight; -} -impl OnNewRound for () { - fn on_new_round(_round_index: crate::RoundIndex) -> Weight { - Weight::zero() - } -} - -/// Defines the behavior to payout the collator's reward. -pub trait PayoutCollatorReward { - fn payout_collator_reward( - round_index: crate::RoundIndex, - collator_id: Runtime::AccountId, - amount: crate::BalanceOf, - ) -> Weight; -} - -/// Defines the default behavior for paying out the collator's reward. The amount is directly -/// deposited into the collator's account. -impl PayoutCollatorReward for () { - fn payout_collator_reward( - for_round: crate::RoundIndex, - collator_id: Runtime::AccountId, - amount: crate::BalanceOf, - ) -> Weight { - crate::Pallet::::mint_collator_reward(for_round, collator_id, amount) - } -} diff --git a/external/pallets/parachain-staking/src/types.rs b/external/pallets/parachain-staking/src/types.rs deleted file mode 100644 index 17dfbabb4..000000000 --- a/external/pallets/parachain-staking/src/types.rs +++ /dev/null @@ -1,1630 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Types for parachain-staking - -use crate::{ - auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, - CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, - Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, -}; -use frame_support::{ - pallet_prelude::*, - traits::{tokens::WithdrawReasons, LockableCurrency}, -}; -use parity_scale_codec::{Decode, Encode}; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Saturating, Zero}, - Perbill, Percent, RuntimeDebug, -}; -use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; - -pub struct CountedDelegations { - pub uncounted_stake: BalanceOf, - pub rewardable_delegations: Vec>>, -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct Bond { - pub owner: AccountId, - pub amount: Balance, -} - -impl Default for Bond { - fn default() -> Bond { - Bond { - owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - amount: B::default(), - } - } -} - -impl Bond { - pub fn from_owner(owner: A) -> Self { - Bond { owner, amount: B::default() } - } -} - -impl Eq for Bond {} - -impl Ord for Bond { - fn cmp(&self, other: &Self) -> Ordering { - self.owner.cmp(&other.owner) - } -} - -impl PartialOrd for Bond { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for Bond { - fn eq(&self, other: &Self) -> bool { - self.owner == other.owner - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// The activity status of the collator -pub enum CollatorStatus { - /// Committed to be online and producing valid blocks (not equivocating) - Active, - /// Temporarily inactive and excused for inactivity - Idle, - /// Bonded until the inner round - Leaving(RoundIndex), -} - -impl Default for CollatorStatus { - fn default() -> CollatorStatus { - CollatorStatus::Active - } -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct BondWithAutoCompound { - pub owner: AccountId, - pub amount: Balance, - pub auto_compound: Percent, -} - -impl Default for BondWithAutoCompound { - fn default() -> BondWithAutoCompound { - BondWithAutoCompound { - owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - amount: B::default(), - auto_compound: Percent::zero(), - } - } -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// Snapshot of collator state at the start of the round for which they are selected -pub struct CollatorSnapshot { - /// The total value locked by the collator. - pub bond: Balance, - - /// The rewardable delegations. This list is a subset of total delegators, where certain - /// delegators are adjusted based on their scheduled - /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. - pub delegations: Vec>, - - /// The total counted value locked for the collator, including the self bond + total staked by - /// top delegators. - pub total: Balance, -} - -impl PartialEq for CollatorSnapshot { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.bond == other.bond && self.total == other.total; - if !must_be_true { - return false; - } - for ( - BondWithAutoCompound { owner: o1, amount: a1, auto_compound: c1 }, - BondWithAutoCompound { owner: o2, amount: a2, auto_compound: c2 }, - ) in self.delegations.iter().zip(other.delegations.iter()) - { - if o1 != o2 || a1 != a2 || c1 != c2 { - return false; - } - } - true - } -} - -impl Default for CollatorSnapshot { - fn default() -> CollatorSnapshot { - CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } - } -} - -#[derive(Default, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Info needed to make delayed payments to stakers after round end -pub struct DelayedPayout { - /// Total round reward (result of compute_issuance() at round end) - pub round_issuance: Balance, - /// The total inflation paid this round to stakers (e.g. less parachain bond fund) - pub total_staking_reward: Balance, - /// Snapshot of collator commission rate at the end of the round - pub collator_commission: Perbill, -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// DEPRECATED -/// Collator state with commission fee, bonded stake, and delegations -pub struct Collator2 { - /// The account of this collator - pub id: AccountId, - /// This collator's self stake. - pub bond: Balance, - /// Set of all nominator AccountIds (to prevent >1 nomination per AccountId) - pub nominators: OrderedSet, - /// Top T::MaxDelegatorsPerCollator::get() nominators, ordered greatest to least - pub top_nominators: Vec>, - /// Bottom nominators (unbounded), ordered least to greatest - pub bottom_nominators: Vec>, - /// Sum of top delegations + self.bond - pub total_counted: Balance, - /// Sum of all delegations + self.bond = (total_counted + uncounted) - pub total_backing: Balance, - /// Current status of the collator - pub state: CollatorStatus, -} - -impl From> for CollatorCandidate { - fn from(other: Collator2) -> CollatorCandidate { - CollatorCandidate { - id: other.id, - bond: other.bond, - delegators: other.nominators, - top_delegations: other.top_nominators, - bottom_delegations: other.bottom_nominators, - total_counted: other.total_counted, - total_backing: other.total_backing, - request: None, - state: other.state, - } - } -} - -#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Request scheduled to change the collator candidate self-bond -pub struct CandidateBondLessRequest { - pub amount: Balance, - pub when_executable: RoundIndex, -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// DEPRECATED, replaced by `CandidateMetadata` and two storage instances of `Delegations` -/// Collator candidate state with self bond + delegations -pub struct CollatorCandidate { - /// The account of this collator - pub id: AccountId, - /// This collator's self stake. - pub bond: Balance, - /// Set of all delegator AccountIds (to prevent >1 delegation per AccountId) - pub delegators: OrderedSet, - /// Top T::MaxDelegatorsPerCollator::get() delegations, ordered greatest to least - pub top_delegations: Vec>, - /// Bottom delegations (unbounded), ordered least to greatest - pub bottom_delegations: Vec>, - /// Sum of top delegations + self.bond - pub total_counted: Balance, - /// Sum of all delegations + self.bond = (total_counted + uncounted) - pub total_backing: Balance, - /// Maximum 1 pending request to decrease candidate self bond at any given time - pub request: Option>, - /// Current status of the collator - pub state: CollatorStatus, -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Type for top and bottom delegation storage item -pub struct Delegations { - pub delegations: Vec>, - pub total: Balance, -} - -impl Default for Delegations { - fn default() -> Delegations { - Delegations { delegations: Vec::new(), total: B::default() } - } -} - -impl - Delegations -{ - pub fn sort_greatest_to_least(&mut self) { - self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); - } - /// Insert sorted greatest to least and increase .total accordingly - /// Insertion respects first come first serve so new delegations are pushed after existing - /// delegations if the amount is the same - pub fn insert_sorted_greatest_to_least(&mut self, delegation: Bond) { - self.total = self.total.saturating_add(delegation.amount); - // if delegations nonempty && last_element == delegation.amount => push input and return - if !self.delegations.is_empty() { - // if last_element == delegation.amount => push the delegation and return early - if self.delegations[self.delegations.len() - 1].amount == delegation.amount { - self.delegations.push(delegation); - // early return - return; - } - } - // else binary search insertion - match self.delegations.binary_search_by(|x| delegation.amount.cmp(&x.amount)) { - // sorted insertion on sorted vec - // enforces first come first serve for equal bond amounts - Ok(i) => { - let mut new_index = i + 1; - while new_index <= (self.delegations.len() - 1) { - if self.delegations[new_index].amount == delegation.amount { - new_index = new_index.saturating_add(1); - } else { - self.delegations.insert(new_index, delegation); - return; - } - } - self.delegations.push(delegation) - } - Err(i) => self.delegations.insert(i, delegation), - } - } - /// Return the capacity status for top delegations - pub fn top_capacity(&self) -> CapacityStatus { - match &self.delegations { - x if x.len() as u32 >= T::MaxTopDelegationsPerCandidate::get() => CapacityStatus::Full, - x if x.is_empty() => CapacityStatus::Empty, - _ => CapacityStatus::Partial, - } - } - /// Return the capacity status for bottom delegations - pub fn bottom_capacity(&self) -> CapacityStatus { - match &self.delegations { - x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => { - CapacityStatus::Full - } - x if x.is_empty() => CapacityStatus::Empty, - _ => CapacityStatus::Partial, - } - } - /// Return last delegation amount without popping the delegation - pub fn lowest_delegation_amount(&self) -> Balance { - self.delegations.last().map(|x| x.amount).unwrap_or_else(Balance::zero) - } - /// Return highest delegation amount - pub fn highest_delegation_amount(&self) -> Balance { - self.delegations.first().map(|x| x.amount).unwrap_or_else(Balance::zero) - } -} - -#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Capacity status for top or bottom delegations -pub enum CapacityStatus { - /// Reached capacity - Full, - /// Empty aka contains no delegations - Empty, - /// Partially full (nonempty and not full) - Partial, -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// All candidate info except the top and bottom delegations -pub struct CandidateMetadata { - /// This candidate's self bond amount - pub bond: Balance, - /// Total number of delegations to this candidate - pub delegation_count: u32, - /// Self bond + sum of top delegations - pub total_counted: Balance, - /// The smallest top delegation amount - pub lowest_top_delegation_amount: Balance, - /// The highest bottom delegation amount - pub highest_bottom_delegation_amount: Balance, - /// The smallest bottom delegation amount - pub lowest_bottom_delegation_amount: Balance, - /// Capacity status for top delegations - pub top_capacity: CapacityStatus, - /// Capacity status for bottom delegations - pub bottom_capacity: CapacityStatus, - /// Maximum 1 pending request to decrease candidate self bond at any given time - pub request: Option>, - /// Current status of the collator - pub status: CollatorStatus, -} - -impl< - Balance: Copy - + Zero - + PartialOrd - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + sp_std::fmt::Debug - + Saturating, -> CandidateMetadata -{ - pub fn new(bond: Balance) -> Self { - CandidateMetadata { - bond, - delegation_count: 0u32, - total_counted: bond, - lowest_top_delegation_amount: Zero::zero(), - highest_bottom_delegation_amount: Zero::zero(), - lowest_bottom_delegation_amount: Zero::zero(), - top_capacity: CapacityStatus::Empty, - bottom_capacity: CapacityStatus::Empty, - request: None, - status: CollatorStatus::Active, - } - } - pub fn is_active(&self) -> bool { - matches!(self.status, CollatorStatus::Active) - } - pub fn is_leaving(&self) -> bool { - matches!(self.status, CollatorStatus::Leaving(_)) - } - pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { - ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); - let now = >::get().current; - let when = now + T::LeaveCandidatesDelay::get(); - self.status = CollatorStatus::Leaving(when); - Ok((now, when)) - } - pub fn can_leave(&self) -> DispatchResult { - if let CollatorStatus::Leaving(when) = self.status { - ensure!(>::get().current >= when, Error::::CandidateCannotLeaveYet); - Ok(()) - } else { - Err(Error::::CandidateNotLeaving.into()) - } - } - pub fn go_offline(&mut self) { - self.status = CollatorStatus::Idle; - } - pub fn go_online(&mut self) { - self.status = CollatorStatus::Active; - } - pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult - where - BalanceOf: From, - { - ensure!( - >::get_collator_stakable_free_balance(&who) >= more.into(), - Error::::InsufficientBalance - ); - let new_total = >::get().saturating_add(more.into()); - >::put(new_total); - self.bond = self.bond.saturating_add(more); - T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); - self.total_counted = self.total_counted.saturating_add(more); - >::deposit_event(Event::CandidateBondedMore { - candidate: who, - amount: more.into(), - new_total_bond: self.bond.into(), - }); - Ok(()) - } - /// Schedule executable decrease of collator candidate self bond - /// Returns the round at which the collator can execute the pending request - pub fn schedule_bond_less( - &mut self, - less: Balance, - ) -> Result - where - BalanceOf: Into, - { - // ensure no pending request - ensure!(self.request.is_none(), Error::::PendingCandidateRequestAlreadyExists); - // ensure bond above min after decrease - ensure!(self.bond > less, Error::::CandidateBondBelowMin); - ensure!( - self.bond - less >= T::MinCandidateStk::get().into(), - Error::::CandidateBondBelowMin - ); - let when_executable = >::get().current + T::CandidateBondLessDelay::get(); - self.request = Some(CandidateBondLessRequest { amount: less, when_executable }); - Ok(when_executable) - } - /// Execute pending request to decrease the collator self bond - /// Returns the event to be emitted - pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult - where - BalanceOf: From, - { - let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; - ensure!( - request.when_executable <= >::get().current, - Error::::PendingCandidateRequestNotDueYet - ); - let new_total_staked = >::get().saturating_sub(request.amount.into()); - >::put(new_total_staked); - // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond - // (assumptions enforced by `schedule_bond_less`; if storage corrupts, must re-verify) - self.bond = self.bond.saturating_sub(request.amount); - T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); - self.total_counted = self.total_counted.saturating_sub(request.amount); - let event = Event::CandidateBondedLess { - candidate: who.clone(), - amount: request.amount.into(), - new_bond: self.bond.into(), - }; - // reset s.t. no pending request - self.request = None; - // update candidate pool value because it must change if self bond changes - if self.is_active() { - Pallet::::update_active(who, self.total_counted.into()); - } - Pallet::::deposit_event(event); - Ok(()) - } - /// Cancel candidate bond less request - pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult - where - BalanceOf: From, - { - let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; - let event = Event::CancelledCandidateBondLess { - candidate: who, - amount: request.amount.into(), - execute_round: request.when_executable, - }; - self.request = None; - Pallet::::deposit_event(event); - Ok(()) - } - /// Reset top delegations metadata - pub fn reset_top_data( - &mut self, - candidate: T::AccountId, - top_delegations: &Delegations>, - ) where - BalanceOf: Into + From, - { - self.lowest_top_delegation_amount = top_delegations.lowest_delegation_amount().into(); - self.top_capacity = top_delegations.top_capacity::(); - let old_total_counted = self.total_counted; - self.total_counted = self.bond.saturating_add(top_delegations.total.into()); - // CandidatePool value for candidate always changes if top delegations total changes - // so we moved the update into this function to deduplicate code and patch a bug that - // forgot to apply the update when increasing top delegation - if old_total_counted != self.total_counted && self.is_active() { - Pallet::::update_active(candidate, self.total_counted.into()); - } - } - /// Reset bottom delegations metadata - pub fn reset_bottom_data( - &mut self, - bottom_delegations: &Delegations>, - ) where - BalanceOf: Into, - { - self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); - self.highest_bottom_delegation_amount = - bottom_delegations.highest_delegation_amount().into(); - self.bottom_capacity = bottom_delegations.bottom_capacity::(); - } - /// Add delegation - /// Returns whether delegator was added and an optional negative total counted remainder - /// for if a bottom delegation was kicked - /// MUST ensure no delegation exists for this candidate in the `DelegatorState` before call - pub fn add_delegation( - &mut self, - candidate: &T::AccountId, - delegation: Bond>, - ) -> Result<(DelegatorAdded, Option), DispatchError> - where - BalanceOf: Into + From, - { - let mut less_total_staked = None; - let delegator_added = match self.top_capacity { - CapacityStatus::Full => { - // top is full, insert into top iff the lowest_top < amount - if self.lowest_top_delegation_amount < delegation.amount.into() { - // bumps lowest top to the bottom inside this function call - less_total_staked = self.add_top_delegation::(candidate, delegation); - DelegatorAdded::AddedToTop { new_total: self.total_counted } - } else { - // if bottom is full, only insert if greater than lowest bottom (which will - // be bumped out) - if matches!(self.bottom_capacity, CapacityStatus::Full) { - ensure!( - delegation.amount.into() > self.lowest_bottom_delegation_amount, - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - // need to subtract from total staked - less_total_staked = Some(self.lowest_bottom_delegation_amount); - } - // insert into bottom - self.add_bottom_delegation::(false, candidate, delegation); - DelegatorAdded::AddedToBottom - } - } - // top is either empty or partially full - _ => { - self.add_top_delegation::(candidate, delegation); - DelegatorAdded::AddedToTop { new_total: self.total_counted } - } - }; - Ok((delegator_added, less_total_staked)) - } - /// Add delegation to top delegation - /// Returns Option - /// Only call if lowest top delegation is less than delegation.amount || !top_full - pub fn add_top_delegation( - &mut self, - candidate: &T::AccountId, - delegation: Bond>, - ) -> Option - where - BalanceOf: Into + From, - { - let mut less_total_staked = None; - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); - let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); - if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { - // pop lowest top delegation - let new_bottom_delegation = top_delegations.delegations.pop().expect(""); - top_delegations.total = - top_delegations.total.saturating_sub(new_bottom_delegation.amount); - if matches!(self.bottom_capacity, CapacityStatus::Full) { - less_total_staked = Some(self.lowest_bottom_delegation_amount); - } - self.add_bottom_delegation::(true, candidate, new_bottom_delegation); - } - // insert into top - top_delegations.insert_sorted_greatest_to_least(delegation); - // update candidate info - self.reset_top_data::(candidate.clone(), &top_delegations); - if less_total_staked.is_none() { - // only increment delegation count if we are not kicking a bottom delegation - self.delegation_count = self.delegation_count.saturating_add(1u32); - } - >::insert(candidate, top_delegations); - less_total_staked - } - /// Add delegation to bottom delegations - /// Check before call that if capacity is full, inserted delegation is higher than lowest - /// bottom delegation (and if so, need to adjust the total storage item) - /// CALLER MUST ensure(lowest_bottom_to_be_kicked.amount < delegation.amount) - pub fn add_bottom_delegation( - &mut self, - bumped_from_top: bool, - candidate: &T::AccountId, - delegation: Bond>, - ) where - BalanceOf: Into + From, - { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); - // if bottom is full, kick the lowest bottom (which is expected to be lower than input - // as per check) - let increase_delegation_count = if bottom_delegations.delegations.len() as u32 - == T::MaxBottomDelegationsPerCandidate::get() - { - let lowest_bottom_to_be_kicked = bottom_delegations - .delegations - .pop() - .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); - // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller - // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick - // the lowest bottom to enforce first come first served - bottom_delegations.total = - bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); - // update delegator state - // total staked is updated via propagation of lowest bottom delegation amount prior - // to call - let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) - .expect("Delegation existence => DelegatorState existence"); - let leaving = delegator_state.delegations.0.len() == 1usize; - delegator_state.rm_delegation::(candidate); - >::delegation_remove_request_with_state( - candidate, - &lowest_bottom_to_be_kicked.owner, - &mut delegator_state, - ); - >::remove_auto_compound( - candidate, - &lowest_bottom_to_be_kicked.owner, - ); - - Pallet::::deposit_event(Event::DelegationKicked { - delegator: lowest_bottom_to_be_kicked.owner.clone(), - candidate: candidate.clone(), - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - if leaving { - >::remove(&lowest_bottom_to_be_kicked.owner); - Pallet::::deposit_event(Event::DelegatorLeft { - delegator: lowest_bottom_to_be_kicked.owner, - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - } else { - >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); - } - false - } else { - !bumped_from_top - }; - // only increase delegation count if new bottom delegation (1) doesn't come from top && - // (2) doesn't pop the lowest delegation from the bottom - if increase_delegation_count { - self.delegation_count = self.delegation_count.saturating_add(1u32); - } - bottom_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - } - /// Remove delegation - /// Removes from top if amount is above lowest top or top is not full - /// Return Ok(if_total_counted_changed) - pub fn rm_delegation_if_exists( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - amount: Balance, - ) -> Result - where - BalanceOf: Into + From, - { - let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; - let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { - self.rm_top_delegation::(candidate, delegator) - } else if amount_geq_lowest_top && lowest_top_eq_highest_bottom { - let result = self.rm_top_delegation::(candidate, delegator.clone()); - if result == Err(delegation_dne_err) { - // worst case removal - self.rm_bottom_delegation::(candidate, delegator) - } else { - result - } - } else { - self.rm_bottom_delegation::(candidate, delegator) - } - } - /// Remove top delegation, bumps top bottom delegation if exists - pub fn rm_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - ) -> Result - where - BalanceOf: Into + From, - { - let old_total_counted = self.total_counted; - // remove top delegation - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); - let mut actual_amount_option: Option> = None; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - actual_amount_option = Some(d.amount); - false - } - }) - .collect(); - let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; - top_delegations.total = top_delegations.total.saturating_sub(actual_amount); - // if bottom nonempty => bump top bottom to top - if !matches!(self.bottom_capacity, CapacityStatus::Empty) { - let mut bottom_delegations = - >::get(candidate).expect("bottom is nonempty as just checked"); - // expect already stored greatest to least by bond amount - let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = - bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - // insert highest bottom into top delegations - top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); - } - // update candidate info - self.reset_top_data::(candidate.clone(), &top_delegations); - self.delegation_count = self.delegation_count.saturating_sub(1u32); - >::insert(candidate, top_delegations); - // return whether total counted changed - Ok(old_total_counted == self.total_counted) - } - /// Remove bottom delegation - /// Returns if_total_counted_changed: bool - pub fn rm_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - ) -> Result - where - BalanceOf: Into, - { - // remove bottom delegation - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); - let mut actual_amount_option: Option> = None; - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - actual_amount_option = Some(d.amount); - false - } - }) - .collect(); - let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; - bottom_delegations.total = bottom_delegations.total.saturating_sub(actual_amount); - // update candidate info - self.reset_bottom_data::(&bottom_delegations); - self.delegation_count = self.delegation_count.saturating_sub(1u32); - >::insert(candidate, bottom_delegations); - Ok(false) - } - /// Increase delegation amount - pub fn increase_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { - // definitely in top - self.increase_top_delegation::(candidate, delegator, more) - } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { - // update top but if error then update bottom (because could be in bottom because - // lowest_top_eq_highest_bottom) - let result = self.increase_top_delegation::(candidate, delegator.clone(), more); - if result == Err(delegation_dne_err) { - self.increase_bottom_delegation::(candidate, delegator, bond, more) - } else { - result - } - } else { - self.increase_bottom_delegation::(candidate, delegator, bond, more) - } - } - /// Increase top delegation - pub fn increase_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); - let mut in_top = false; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_top = true; - let new_amount = d.amount.saturating_add(more); - Bond { owner: d.owner, amount: new_amount } - } - }) - .collect(); - ensure!(in_top, Error::::DelegationDNE); - top_delegations.total = top_delegations.total.saturating_add(more); - top_delegations.sort_greatest_to_least(); - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - Ok(true) - } - /// Increase bottom delegation - pub fn increase_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let mut bottom_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; - let mut delegation_option: Option>> = None; - let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount - { - // bump it from bottom - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_add(more), - }); - false - } - }) - .collect(); - let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; - bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); - // add it to top - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); - // if top is full, pop lowest top - if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { - // pop lowest top delegation - let new_bottom_delegation = top_delegations - .delegations - .pop() - .expect("Top capacity full => Exists at least 1 top delegation"); - top_delegations.total = - top_delegations.total.saturating_sub(new_bottom_delegation.amount); - bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); - } - // insert into top - top_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - true - } else { - let mut in_bottom = false; - // just increase the delegation - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_bottom = true; - Bond { owner: d.owner, amount: d.amount.saturating_add(more) } - } - }) - .collect(); - ensure!(in_bottom, Error::::DelegationDNE); - bottom_delegations.total = bottom_delegations.total.saturating_add(more); - bottom_delegations.sort_greatest_to_least(); - false - }; - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - Ok(in_top_after) - } - /// Decrease delegation - pub fn decrease_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: Balance, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { - // definitely in top - self.decrease_top_delegation::(candidate, delegator, bond.into(), less) - } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { - // update top but if error then update bottom (because could be in bottom because - // lowest_top_eq_highest_bottom) - let result = - self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); - if result == Err(delegation_dne_err) { - self.decrease_bottom_delegation::(candidate, delegator, less) - } else { - result - } - } else { - self.decrease_bottom_delegation::(candidate, delegator, less) - } - } - /// Decrease top delegation - pub fn decrease_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - // The delegation after the `decrease-delegation` will be strictly less than the - // highest bottom delegation - let bond_after_less_than_highest_bottom = - bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; - // The top delegations is full and the bottom delegations has at least one delegation - let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) - && !matches!(self.bottom_capacity, CapacityStatus::Empty); - let mut top_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; - let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { - let mut delegation_option: Option>> = None; - // take delegation from top - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - top_delegations.total = top_delegations.total.saturating_sub(d.amount); - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_sub(less), - }); - false - } - }) - .collect(); - let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; - // pop highest bottom by reverse and popping - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); - let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = - bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); - // insert highest bottom into top - top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); - // insert previous top into bottom - bottom_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - false - } else { - // keep it in the top - let mut is_in_top = false; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - is_in_top = true; - Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } - } - }) - .collect(); - ensure!(is_in_top, Error::::DelegationDNE); - top_delegations.total = top_delegations.total.saturating_sub(less); - top_delegations.sort_greatest_to_least(); - true - }; - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - Ok(in_top_after) - } - /// Decrease bottom delegation - pub fn decrease_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into, - { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); - let mut in_bottom = false; - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_bottom = true; - Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } - } - }) - .collect(); - ensure!(in_bottom, Error::::DelegationDNE); - bottom_delegations.sort_greatest_to_least(); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - Ok(false) - } -} - -// Temporary manual implementation for migration testing purposes -impl PartialEq for CollatorCandidate { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.id == other.id - && self.bond == other.bond - && self.total_counted == other.total_counted - && self.total_backing == other.total_backing - && self.request == other.request - && self.state == other.state; - if !must_be_true { - return false; - } - for (x, y) in self.delegators.0.iter().zip(other.delegators.0.iter()) { - if x != y { - return false; - } - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.top_delegations.iter().zip(other.top_delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.bottom_delegations.iter().zip(other.bottom_delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - true - } -} - -/// Convey relevant information describing if a delegator was added to the top or bottom -/// Delegations added to the top yield a new total -#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub enum DelegatorAdded { - AddedToTop { new_total: B }, - AddedToBottom, -} - -impl< - A: Ord + Clone + sp_std::fmt::Debug, - B: AtLeast32BitUnsigned - + Ord - + Copy - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::fmt::Debug, -> CollatorCandidate -{ - pub fn is_active(&self) -> bool { - self.state == CollatorStatus::Active - } -} - -impl From> for CollatorSnapshot { - fn from(other: CollatorCandidate) -> CollatorSnapshot { - CollatorSnapshot { - bond: other.bond, - delegations: other - .top_delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner, - amount: d.amount, - auto_compound: Percent::zero(), - }) - .collect(), - total: other.total_counted, - } - } -} - -#[allow(deprecated)] -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub enum DelegatorStatus { - /// Active with no scheduled exit - Active, - /// Schedule exit to revoke all ongoing delegations - #[deprecated(note = "must only be used for backwards compatibility reasons")] - Leaving(RoundIndex), -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Delegator state -pub struct Delegator { - /// Delegator account - pub id: AccountId, - /// All current delegations - pub delegations: OrderedSet>, - /// Total balance locked for this delegator - pub total: Balance, - /// Sum of pending revocation amounts + bond less amounts - pub less_total: Balance, - /// Status for this delegator - pub status: DelegatorStatus, -} - -// Temporary manual implementation for migration testing purposes -impl PartialEq for Delegator { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.id == other.id - && self.total == other.total - && self.less_total == other.less_total - && self.status == other.status; - if !must_be_true { - return false; - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.delegations.0.iter().zip(other.delegations.0.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - true - } -} - -impl< - AccountId: Ord + Clone, - Balance: Copy - + sp_std::ops::AddAssign - + sp_std::ops::Add - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + Ord - + Zero - + Default - + Saturating, -> Delegator -{ - pub fn new(id: AccountId, collator: AccountId, amount: Balance) -> Self { - Delegator { - id, - delegations: OrderedSet::from(vec![Bond { owner: collator, amount }]), - total: amount, - less_total: Balance::zero(), - status: DelegatorStatus::Active, - } - } - - pub fn default_with_total(id: AccountId, amount: Balance) -> Self { - Delegator { - id, - total: amount, - delegations: OrderedSet::from(vec![]), - less_total: Balance::zero(), - status: DelegatorStatus::Active, - } - } - - pub fn total(&self) -> Balance { - self.total - } - - pub fn total_sub_if(&mut self, amount: Balance, check: F) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - F: Fn(Balance) -> DispatchResult, - { - let total = self.total.saturating_sub(amount); - check(total)?; - self.total = total; - self.adjust_bond_lock::(BondAdjust::Decrease)?; - Ok(()) - } - - pub fn total_add(&mut self, amount: Balance) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - { - self.total = self.total.saturating_add(amount); - self.adjust_bond_lock::(BondAdjust::Increase(amount))?; - Ok(()) - } - - pub fn total_sub(&mut self, amount: Balance) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - { - self.total = self.total.saturating_sub(amount); - self.adjust_bond_lock::(BondAdjust::Decrease)?; - Ok(()) - } - - pub fn is_active(&self) -> bool { - matches!(self.status, DelegatorStatus::Active) - } - - pub fn add_delegation(&mut self, bond: Bond) -> bool { - let amt = bond.amount; - if self.delegations.insert(bond) { - self.total = self.total.saturating_add(amt); - true - } else { - false - } - } - // Return Some(remaining balance), must be more than MinDelegatorStk - // Return None if delegation not found - pub fn rm_delegation(&mut self, collator: &AccountId) -> Option - where - BalanceOf: From, - T::AccountId: From, - { - let mut amt: Option = None; - let delegations = self - .delegations - .0 - .iter() - .filter_map(|x| { - if &x.owner == collator { - amt = Some(x.amount); - None - } else { - Some(x.clone()) - } - }) - .collect(); - if let Some(balance) = amt { - self.delegations = OrderedSet::from(delegations); - self.total_sub::(balance).expect("Decreasing lock cannot fail, qed"); - Some(self.total) - } else { - None - } - } - - /// Increases the delegation amount and returns `true` if the delegation is part of the - /// TopDelegations set, `false` otherwise. - pub fn increase_delegation( - &mut self, - candidate: AccountId, - amount: Balance, - ) -> Result - where - BalanceOf: From, - T::AccountId: From, - Delegator>: From>, - { - let delegator_id: T::AccountId = self.id.clone().into(); - let candidate_id: T::AccountId = candidate.clone().into(); - let balance_amt: BalanceOf = amount.into(); - // increase delegation - for x in &mut self.delegations.0 { - if x.owner == candidate { - let before_amount: BalanceOf = x.amount.into(); - x.amount = x.amount.saturating_add(amount); - self.total = self.total.saturating_add(amount); - self.adjust_bond_lock::(BondAdjust::Increase(amount))?; - - // update collator state delegation - let mut collator_state = - >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; - let before = collator_state.total_counted; - let in_top = collator_state.increase_delegation::( - &candidate_id, - delegator_id.clone(), - before_amount, - balance_amt, - )?; - let after = collator_state.total_counted; - if collator_state.is_active() && (before != after) { - Pallet::::update_active(candidate_id.clone(), after); - } - >::insert(&candidate_id, collator_state); - let new_total_staked = >::get().saturating_add(balance_amt); - >::put(new_total_staked); - let nom_st: Delegator> = self.clone().into(); - >::insert(&delegator_id, nom_st); - return Ok(in_top); - } - } - Err(Error::::DelegationDNE.into()) - } - - /// Updates the bond locks for this delegator. - /// - /// This will take the current self.total and ensure that a lock of the same amount is applied - /// and when increasing the bond lock will also ensure that the account has enough free balance. - /// - /// `additional_required_balance` should reflect the change to the amount that should be locked if - /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is - /// not possible to query the amount that is locked for a given lock id. - pub fn adjust_bond_lock( - &mut self, - additional_required_balance: BondAdjust, - ) -> DispatchResult - where - BalanceOf: From, - T::AccountId: From, - { - match additional_required_balance { - BondAdjust::Increase(amount) => { - ensure!( - >::get_delegator_stakable_free_balance(&self.id.clone().into()) - >= amount.into(), - Error::::InsufficientBalance, - ); - - // additional sanity check: shouldn't ever want to lock more than total - if amount > self.total { - log::warn!("LOGIC ERROR: request to reserve more than bond total"); - return Err(DispatchError::Other("Invalid additional_required_balance")); - } - } - BondAdjust::Decrease => (), // do nothing on decrease - }; - - if self.total.is_zero() { - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &self.id.clone().into()); - } else { - T::Currency::set_lock( - DELEGATOR_LOCK_ID, - &self.id.clone().into(), - self.total.into(), - WithdrawReasons::all(), - ); - } - Ok(()) - } - - /// Retrieves the bond amount that a delegator has provided towards a collator. - /// Returns `None` if missing. - pub fn get_bond_amount(&self, collator: &AccountId) -> Option { - self.delegations.0.iter().find(|b| &b.owner == collator).map(|b| b.amount) - } -} - -pub mod deprecated { - #![allow(deprecated)] - - use super::*; - - #[deprecated(note = "use DelegationAction")] - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - /// Changes requested by the delegator - /// - limit of 1 ongoing change per delegation - pub enum DelegationChange { - Revoke, - Decrease, - } - - #[deprecated(note = "use ScheduledRequest")] - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - pub struct DelegationRequest { - pub collator: AccountId, - pub amount: Balance, - pub when_executable: RoundIndex, - pub action: DelegationChange, - } - - #[deprecated(note = "use DelegationScheduledRequests storage item")] - #[derive(Clone, Encode, PartialEq, Eq, Decode, RuntimeDebug, TypeInfo)] - /// Pending requests to mutate delegations for each delegator - pub struct PendingDelegationRequests { - /// Number of pending revocations (necessary for determining whether revoke is exit) - pub revocations_count: u32, - /// Map from collator -> Request (enforces at most 1 pending request per delegation) - pub requests: BTreeMap>, - /// Sum of pending revocation amounts + bond less amounts - pub less_total: Balance, - } - - impl Default for PendingDelegationRequests { - fn default() -> PendingDelegationRequests { - PendingDelegationRequests { - revocations_count: 0u32, - requests: BTreeMap::new(), - less_total: B::zero(), - } - } - } - - impl< - A: Ord + Clone, - B: Zero - + Ord - + Copy - + Clone - + sp_std::ops::AddAssign - + sp_std::ops::Add - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + Saturating, - > PendingDelegationRequests - { - /// New default (empty) pending requests - pub fn new() -> Self { - Self::default() - } - } - - #[deprecated(note = "use new crate::types::Delegator struct")] - #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] - /// Delegator state - pub struct Delegator { - /// Delegator account - pub id: AccountId, - /// All current delegations - pub delegations: OrderedSet>, - /// Total balance locked for this delegator - pub total: Balance, - /// Requests to change delegations, relevant iff active - pub requests: PendingDelegationRequests, - /// Status for this delegator - pub status: DelegatorStatus, - } - - // CollatorSnapshot - - #[deprecated(note = "use CollatorSnapshot with BondWithAutoCompound delegations")] - #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] - /// Snapshot of collator state at the start of the round for which they are selected - pub struct CollatorSnapshot { - /// The total value locked by the collator. - pub bond: Balance, - - /// The rewardable delegations. This list is a subset of total delegators, where certain - /// delegators are adjusted based on their scheduled - /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. - pub delegations: Vec>, - - /// The total counted value locked for the collator, including the self bond + total staked by - /// top delegators. - pub total: Balance, - } - - impl PartialEq for CollatorSnapshot { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.bond == other.bond && self.total == other.total; - if !must_be_true { - return false; - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.delegations.iter().zip(other.delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false; - } - } - true - } - } - - impl Default for CollatorSnapshot { - fn default() -> CollatorSnapshot { - CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } - } - } -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -/// DEPRECATED in favor of Delegator -/// Nominator state -pub struct Nominator2 { - /// All current delegations - pub delegations: OrderedSet>, - /// Delegations scheduled to be revoked - pub revocations: OrderedSet, - /// Total balance locked for this nominator - pub total: Balance, - /// Total number of revocations scheduled to be executed - pub scheduled_revocations_count: u32, - /// Total amount to be unbonded once revocations are executed - pub scheduled_revocations_total: Balance, - /// Status for this nominator - pub status: DelegatorStatus, -} - -// /// Temporary function to migrate state -// pub(crate) fn migrate_nominator_to_delegator_state( -// id: T::AccountId, -// nominator: Nominator2>, -// ) -> Delegator> { -// Delegator { -// id, -// delegations: nominator.delegations, -// total: nominator.total, -// requests: PendingDelegationRequests::new(), -// status: nominator.status, -// } -// } - -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// The current round index and transition information -pub struct RoundInfo { - /// Current round index - pub current: RoundIndex, - /// The first block of the current round - pub first: BlockNumber, - /// The length of the current round in number of blocks - pub length: u32, -} -impl + sp_std::ops::Sub + From + PartialOrd> - RoundInfo -{ - pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { - RoundInfo { current, first, length } - } - /// Check if the round should be updated - pub fn should_update(&self, now: B) -> bool { - now - self.first >= self.length.into() - } - /// New round - pub fn update(&mut self, now: B) { - self.current = self.current.saturating_add(1u32); - self.first = now; - } -} -impl + sp_std::ops::Sub + From + PartialOrd> - Default for RoundInfo -{ - fn default() -> RoundInfo { - RoundInfo::new(1u32, 1u32.into(), 20u32) - } -} - -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Reserve information { account, percent_of_inflation } -pub struct ParachainBondConfig { - /// Account which receives funds intended for parachain bond - pub account: AccountId, - /// Percent of inflation set aside for parachain bond account - pub percent: Percent, -} -impl Default for ParachainBondConfig { - fn default() -> ParachainBondConfig { - ParachainBondConfig { - account: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - percent: Percent::zero(), - } - } -} - -pub enum BondAdjust { - Increase(Balance), - Decrease, -} diff --git a/external/pallets/parachain-staking/src/weights.rs b/external/pallets/parachain-staking/src/weights.rs deleted file mode 100644 index 60ac48da0..000000000 --- a/external/pallets/parachain-staking/src/weights.rs +++ /dev/null @@ -1,903 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Autogenerated weights for parachain_staking -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-19, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 - -// Executed Command: -// ./target/release/moonbeam -// benchmark -// pallet -// --execution=wasm -// --wasm-execution=compiled -// --pallet -// parachain_staking -// --extrinsic -// * -// --steps -// 50 -// --repeat -// 20 -// --template=./benchmarking/frame-weight-template.hbs -// --json-file -// raw.json -// --output -// weights.rs - -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for parachain_staking. -pub trait WeightInfo { - #[rustfmt::skip] - fn set_staking_expectations() -> Weight; - #[rustfmt::skip] - fn set_inflation() -> Weight; - #[rustfmt::skip] - fn set_parachain_bond_account() -> Weight; - #[rustfmt::skip] - fn set_parachain_bond_reserve_percent() -> Weight; - #[rustfmt::skip] - fn set_total_selected() -> Weight; - #[rustfmt::skip] - fn set_collator_commission() -> Weight; - #[rustfmt::skip] - fn set_blocks_per_round() -> Weight; - #[rustfmt::skip] - fn join_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn schedule_leave_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn execute_leave_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn cancel_leave_candidates(x: u32, ) -> Weight; - #[rustfmt::skip] - fn go_offline() -> Weight; - #[rustfmt::skip] - fn go_online() -> Weight; - #[rustfmt::skip] - fn candidate_bond_more() -> Weight; - #[rustfmt::skip] - fn schedule_candidate_bond_less() -> Weight; - #[rustfmt::skip] - fn execute_candidate_bond_less() -> Weight; - #[rustfmt::skip] - fn cancel_candidate_bond_less() -> Weight; - #[rustfmt::skip] - fn delegate(x: u32, y: u32, ) -> Weight; - #[rustfmt::skip] - fn schedule_leave_delegators() -> Weight; - #[rustfmt::skip] - fn execute_leave_delegators(x: u32, ) -> Weight; - #[rustfmt::skip] - fn cancel_leave_delegators() -> Weight; - #[rustfmt::skip] - fn schedule_revoke_delegation() -> Weight; - #[rustfmt::skip] - fn delegator_bond_more() -> Weight; - #[rustfmt::skip] - fn schedule_delegator_bond_less() -> Weight; - #[rustfmt::skip] - fn execute_revoke_delegation() -> Weight; - #[rustfmt::skip] - fn execute_delegator_bond_less() -> Weight; - #[rustfmt::skip] - fn cancel_revoke_delegation() -> Weight; - #[rustfmt::skip] - fn cancel_delegator_bond_less() -> Weight; - #[rustfmt::skip] - fn prepare_staking_payouts() -> Weight; - #[rustfmt::skip] - fn get_rewardable_delegators(y: u32, ) -> Weight; - #[rustfmt::skip] - fn select_top_candidates(x: u32, y: u32, ) -> Weight; - #[rustfmt::skip] - fn pay_one_collator_reward(y: u32, ) -> Weight; - #[rustfmt::skip] - fn base_on_initialize() -> Weight; - #[rustfmt::skip] - fn set_auto_compound(x: u32, y: u32, ) -> Weight; - #[rustfmt::skip] - fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight; - #[rustfmt::skip] - fn mint_collator_reward() -> Weight; -} - -/// Weights for parachain_staking using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_staking_expectations() -> Weight { - Weight::from_ref_time(48_225_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_inflation() -> Weight { - Weight::from_ref_time(61_063_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_account() -> Weight { - Weight::from_ref_time(27_645_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_reserve_percent() -> Weight { - Weight::from_ref_time(26_922_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:1) - #[rustfmt::skip] - fn set_total_selected() -> Weight { - Weight::from_ref_time(29_263_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking CollatorCommission (r:1 w:1) - #[rustfmt::skip] - fn set_collator_commission() -> Weight { - Weight::from_ref_time(25_867_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(66_047_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:0 w:1) - // Storage: ParachainStaking BottomDelegations (r:0 w:1) - #[rustfmt::skip] - fn join_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(93_609_702_u64) - // Standard Error: 1_049 - .saturating_add(Weight::from_ref_time(156_227_u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(74_938_974_u64) - // Standard Error: 1_813 - .saturating_add(Weight::from_ref_time(136_560_u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: Balances Locks (r:2 w:2) - // Storage: System Account (r:2 w:2) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(120_885_000_u64) - // Standard Error: 73_687 - .saturating_add(Weight::from_ref_time(31_457_020_u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(5_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(70_048_572_u64) - // Standard Error: 1_524 - .saturating_add(Weight::from_ref_time(145_661_u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_offline() -> Weight { - Weight::from_ref_time(42_412_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_online() -> Weight { - Weight::from_ref_time(41_744_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn candidate_bond_more() -> Weight { - Weight::from_ref_time(68_900_000_u64) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn schedule_candidate_bond_less() -> Weight { - Weight::from_ref_time(38_239_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn execute_candidate_bond_less() -> Weight { - Weight::from_ref_time(76_166_000_u64) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn cancel_candidate_bond_less() -> Weight { - Weight::from_ref_time(35_581_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegate(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(131_245_351_u64) - // Standard Error: 19_323 - .saturating_add(Weight::from_ref_time(239_400_u64).saturating_mul(x as u64)) - // Standard Error: 6_339 - .saturating_add(Weight::from_ref_time(261_836_u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_delegators() -> Weight { - Weight::from_ref_time(44_609_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_delegators(x: u32, ) -> Weight { - Weight::from_ref_time(14_022_061_u64) - // Standard Error: 30_972 - .saturating_add(Weight::from_ref_time(29_549_278_u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_delegators() -> Weight { - Weight::from_ref_time(44_825_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_revoke_delegation() -> Weight { - Weight::from_ref_time(43_131_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegator_bond_more() -> Weight { - Weight::from_ref_time(90_452_000_u64) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_delegator_bond_less() -> Weight { - Weight::from_ref_time(43_388_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_revoke_delegation() -> Weight { - Weight::from_ref_time(112_401_000_u64) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_delegator_bond_less() -> Weight { - Weight::from_ref_time(97_377_000_u64) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_revoke_delegation() -> Weight { - Weight::from_ref_time(43_406_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_delegator_bond_less() -> Weight { - Weight::from_ref_time(49_020_000_u64) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking Staked (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CollatorCommission (r:1 w:0) - // Storage: ParachainStaking DelayedPayouts (r:0 w:1) - #[rustfmt::skip] - fn prepare_staking_payouts() -> Weight { - Weight::from_ref_time(59_628_000_u64) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - #[rustfmt::skip] - fn get_rewardable_delegators(y: u32, ) -> Weight { - Weight::from_ref_time(16_322_694_u64) - // Standard Error: 1_133 - .saturating_add(Weight::from_ref_time(233_812_u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(2_u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:0) - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:0) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:0 w:1) - // Storage: ParachainStaking AtStake (r:0 w:1) - #[rustfmt::skip] - fn select_top_candidates(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(44_110_000_u64) - // Standard Error: 237_049 - .saturating_add(Weight::from_ref_time(24_788_127_u64).saturating_mul(x as u64)) - // Standard Error: 118_210 - .saturating_add(Weight::from_ref_time(2_957_731_u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelayedPayouts (r:1 w:0) - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking AtStake (r:2 w:1) - // Storage: ParachainStaking AwardedPts (r:1 w:1) - // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn pay_one_collator_reward(y: u32, ) -> Weight { - Weight::from_ref_time(65_307_432_u64) - // Standard Error: 9_596 - .saturating_add(Weight::from_ref_time(17_073_916_u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y as u64))) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y as u64))) - } - #[rustfmt::skip] - fn base_on_initialize() -> Weight { - Weight::from_ref_time(10_890_000_u64) - } - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - #[rustfmt::skip] - fn set_auto_compound(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(64_797_700_u64) - // Standard Error: 5_810 - .saturating_add(Weight::from_ref_time(292_809_u64).saturating_mul(x as u64)) - // Standard Error: 17_394 - .saturating_add(Weight::from_ref_time(258_382_u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - #[rustfmt::skip] - fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { - Weight::from_ref_time(181_911_542_u64) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(120_473_u64).saturating_mul(x as u64)) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(80_638_u64).saturating_mul(y as u64)) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn mint_collator_reward() -> Weight { - Weight::from_ref_time(40_146_000_u64) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_staking_expectations() -> Weight { - Weight::from_ref_time(48_225_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_inflation() -> Weight { - Weight::from_ref_time(61_063_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_account() -> Weight { - Weight::from_ref_time(27_645_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - #[rustfmt::skip] - fn set_parachain_bond_reserve_percent() -> Weight { - Weight::from_ref_time(26_922_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:1) - #[rustfmt::skip] - fn set_total_selected() -> Weight { - Weight::from_ref_time(29_263_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking CollatorCommission (r:1 w:1) - #[rustfmt::skip] - fn set_collator_commission() -> Weight { - Weight::from_ref_time(25_867_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - #[rustfmt::skip] - fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(66_047_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:0 w:1) - // Storage: ParachainStaking BottomDelegations (r:0 w:1) - #[rustfmt::skip] - fn join_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(93_609_702_u64) - // Standard Error: 1_049 - .saturating_add(Weight::from_ref_time(156_227_u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(74_938_974_u64) - // Standard Error: 1_813 - .saturating_add(Weight::from_ref_time(136_560_u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: Balances Locks (r:2 w:2) - // Storage: System Account (r:2 w:2) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(120_885_000_u64) - // Standard Error: 73_687 - .saturating_add(Weight::from_ref_time(31_457_020_u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_candidates(x: u32, ) -> Weight { - Weight::from_ref_time(70_048_572_u64) - // Standard Error: 1_524 - .saturating_add(Weight::from_ref_time(145_661_u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_offline() -> Weight { - Weight::from_ref_time(42_412_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn go_online() -> Weight { - Weight::from_ref_time(41_744_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn candidate_bond_more() -> Weight { - Weight::from_ref_time(68_900_000_u64) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn schedule_candidate_bond_less() -> Weight { - Weight::from_ref_time(38_239_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - #[rustfmt::skip] - fn execute_candidate_bond_less() -> Weight { - Weight::from_ref_time(76_166_000_u64) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - #[rustfmt::skip] - fn cancel_candidate_bond_less() -> Weight { - Weight::from_ref_time(35_581_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegate(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(131_245_351_u64) - // Standard Error: 19_323 - .saturating_add(Weight::from_ref_time(239_400_u64).saturating_mul(x as u64)) - // Standard Error: 6_339 - .saturating_add(Weight::from_ref_time(261_836_u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_leave_delegators() -> Weight { - Weight::from_ref_time(44_609_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn execute_leave_delegators(x: u32, ) -> Weight { - Weight::from_ref_time(14_022_061_u64) - // Standard Error: 30_972 - .saturating_add(Weight::from_ref_time(29_549_278_u64).saturating_mul(x as u64)) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_leave_delegators() -> Weight { - Weight::from_ref_time(44_825_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_revoke_delegation() -> Weight { - Weight::from_ref_time(43_131_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn delegator_bond_more() -> Weight { - Weight::from_ref_time(90_452_000_u64) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn schedule_delegator_bond_less() -> Weight { - Weight::from_ref_time(43_388_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_revoke_delegation() -> Weight { - Weight::from_ref_time(112_401_000_u64) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - #[rustfmt::skip] - fn execute_delegator_bond_less() -> Weight { - Weight::from_ref_time(97_377_000_u64) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_revoke_delegation() -> Weight { - Weight::from_ref_time(43_406_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - #[rustfmt::skip] - fn cancel_delegator_bond_less() -> Weight { - Weight::from_ref_time(49_020_000_u64) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking Staked (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking CollatorCommission (r:1 w:0) - // Storage: ParachainStaking DelayedPayouts (r:0 w:1) - #[rustfmt::skip] - fn prepare_staking_payouts() -> Weight { - Weight::from_ref_time(59_628_000_u64) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - #[rustfmt::skip] - fn get_rewardable_delegators(y: u32, ) -> Weight { - Weight::from_ref_time(16_322_694_u64) - // Standard Error: 1_133 - .saturating_add(Weight::from_ref_time(233_812_u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:0) - // Storage: ParachainStaking TotalSelected (r:1 w:0) - // Storage: ParachainStaking CandidateInfo (r:1 w:0) - // Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - // Storage: ParachainStaking TopDelegations (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - // Storage: ParachainStaking SelectedCandidates (r:0 w:1) - // Storage: ParachainStaking AtStake (r:0 w:1) - #[rustfmt::skip] - fn select_top_candidates(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(44_110_000_u64) - // Standard Error: 237_049 - .saturating_add(Weight::from_ref_time(24_788_127_u64).saturating_mul(x as u64)) - // Standard Error: 118_210 - .saturating_add(Weight::from_ref_time(2_957_731_u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x as u64))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(x as u64))) - } - // Storage: ParachainStaking DelayedPayouts (r:1 w:0) - // Storage: ParachainStaking Points (r:1 w:0) - // Storage: ParachainStaking AtStake (r:2 w:1) - // Storage: ParachainStaking AwardedPts (r:1 w:1) - // Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn pay_one_collator_reward(y: u32, ) -> Weight { - Weight::from_ref_time(65_307_432_u64) - // Standard Error: 9_596 - .saturating_add(Weight::from_ref_time(17_073_916_u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y as u64))) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(y as u64))) - } - #[rustfmt::skip] - fn base_on_initialize() -> Weight { - Weight::from_ref_time(10_890_000_u64) - } - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - #[rustfmt::skip] - fn set_auto_compound(x: u32, y: u32, ) -> Weight { - Weight::from_ref_time(64_797_700_u64) - // Standard Error: 5_810 - .saturating_add(Weight::from_ref_time(292_809_u64).saturating_mul(x as u64)) - // Standard Error: 17_394 - .saturating_add(Weight::from_ref_time(258_382_u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidateInfo (r:1 w:1) - // Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - // Storage: ParachainStaking TopDelegations (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking Total (r:1 w:1) - // Storage: ParachainStaking BottomDelegations (r:1 w:1) - #[rustfmt::skip] - fn delegate_with_auto_compound(x: u32, y: u32, _z: u32, ) -> Weight { - Weight::from_ref_time(181_911_542_u64) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(120_473_u64).saturating_mul(x as u64)) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(80_638_u64).saturating_mul(y as u64)) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - // Storage: System Account (r:1 w:1) - #[rustfmt::skip] - fn mint_collator_reward() -> Weight { - Weight::from_ref_time(40_146_000_u64) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} diff --git a/external/session-keys/Cargo.toml b/external/session-keys/Cargo.toml deleted file mode 100644 index debbd84bd..000000000 --- a/external/session-keys/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -authors = ["PureStake"] -description = "Primitives for session keys" -edition = "2021" -name = "session-keys-primitives" -version = "0.1.0" - -[dependencies] -async-trait = { version = "0.1", optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -nimbus-primitives = { path = "../nimbus-primitives", default-features = false } -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0", default-features = false, features = ["derive"] } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", optional = true, default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } - -[features] -default = ["std"] -runtime-benchmarks = [] -std = [ - "async-trait", - "frame-support/std", - "nimbus-primitives/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-api/std", - "sp-application-crypto/std", - "sp-consensus-babe/std", - "sp-consensus-vrf/std", - "sp-core/std", - "sp-inherents/std", - "sp-keystore", - "sp-runtime/std", - "sp-std/std", -] diff --git a/external/session-keys/src/digest.rs b/external/session-keys/src/digest.rs deleted file mode 100644 index 2c92c2999..000000000 --- a/external/session-keys/src/digest.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! VRF pre digest object and conversion to DigestItem -use crate::vrf::{VrfSignature, VRF_ENGINE_ID}; -use parity_scale_codec::{Decode, Encode}; -use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; -use sp_runtime::{generic::DigestItem, RuntimeDebug}; - -/// Raw VRF pre-digest. -#[derive(Clone, RuntimeDebug, Encode, Decode)] -pub struct PreDigest { - /// VRF output - pub vrf_output: VRFOutput, - /// VRF proof - pub vrf_proof: VRFProof, -} - -/// A digest item which is usable with moonbeam VRF. -pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which contains a VRF pre-digest. - fn vrf_pre_digest(seal: PreDigest) -> Self; - - /// If this item is an VRF pre-digest, return it. - fn as_vrf_pre_digest(&self) -> Option; - - /// Construct a digest item which contains a VRF seal. - fn vrf_seal(signature: VrfSignature) -> Self; - - /// If this item is a VRF signature, return the signature. - fn as_vrf_seal(&self) -> Option; -} - -impl CompatibleDigestItem for DigestItem { - fn vrf_pre_digest(digest: PreDigest) -> Self { - DigestItem::PreRuntime(VRF_ENGINE_ID, digest.encode()) - } - - fn as_vrf_pre_digest(&self) -> Option { - self.pre_runtime_try_to(&VRF_ENGINE_ID) - } - - fn vrf_seal(signature: VrfSignature) -> Self { - DigestItem::Seal(VRF_ENGINE_ID, signature.encode()) - } - - fn as_vrf_seal(&self) -> Option { - self.seal_try_to(&VRF_ENGINE_ID) - } -} diff --git a/external/session-keys/src/inherent.rs b/external/session-keys/src/inherent.rs deleted file mode 100644 index b0f21f87d..000000000 --- a/external/session-keys/src/inherent.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . -use parity_scale_codec::{Decode, Encode}; -use sp_inherents::{Error, InherentData, InherentIdentifier, IsFatalError}; -use sp_runtime::RuntimeString; - -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(Debug, Decode))] -pub enum InherentError { - Other(RuntimeString), -} - -impl IsFatalError for InherentError { - fn is_fatal_error(&self) -> bool { - match *self { - InherentError::Other(_) => true, - } - } -} - -impl InherentError { - /// Try to create an instance ouf of the given identifier and data. - #[cfg(feature = "std")] - pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { - if id == &INHERENT_IDENTIFIER { - ::decode(&mut &*data).ok() - } else { - None - } - } -} - -/// The InherentIdentifier to set the babe randomness results -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"baberand"; - -/// A bare minimum inherent data provider that provides no real data. -/// The inherent is simply used as a way to kick off some computation -/// until https://github.com/paritytech/substrate/pull/10128 lands. -pub struct InherentDataProvider; - -#[cfg(feature = "std")] -#[async_trait::async_trait] -impl sp_inherents::InherentDataProvider for InherentDataProvider { - fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> { - inherent_data.put_data(INHERENT_IDENTIFIER, &()) - } - - async fn try_handle_error( - &self, - identifier: &InherentIdentifier, - _error: &[u8], - ) -> Option> { - // Don't process modules from other inherents - if *identifier != INHERENT_IDENTIFIER { - return None; - } - - // All errors with the randomness inherent are fatal - Some(Err(Error::Application(Box::from(String::from( - "Error processing dummy randomness inherent", - ))))) - } -} diff --git a/external/session-keys/src/lib.rs b/external/session-keys/src/lib.rs deleted file mode 100644 index bae1a16af..000000000 --- a/external/session-keys/src/lib.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! Primitives for session keys -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod digest; -pub mod inherent; -pub mod vrf; -pub use digest::*; -pub use inherent::*; -pub use vrf::*; - -/// A Trait to lookup keys from AuthorIds -pub trait KeysLookup { - #[cfg(feature = "runtime-benchmarks")] - type Account; - fn lookup_keys(author: &AuthorId) -> Option; - #[cfg(feature = "runtime-benchmarks")] - fn set_keys(id: AuthorId, account: Self::Account, keys: Keys); -} - -// A dummy impl used in simple tests -impl KeysLookup for () { - #[cfg(feature = "runtime-benchmarks")] - type Account = (); - fn lookup_keys(_: &AuthorId) -> Option { - None - } - #[cfg(feature = "runtime-benchmarks")] - fn set_keys(_id: AuthorId, _account: Self::Account, _keys: Keys) {} -} diff --git a/external/session-keys/src/vrf.rs b/external/session-keys/src/vrf.rs deleted file mode 100644 index caf1c3b13..000000000 --- a/external/session-keys/src/vrf.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! VRF Key type -use nimbus_primitives::NimbusId; -use sp_application_crypto::{sr25519, KeyTypeId, UncheckedFrom}; -use sp_consensus_babe::Transcript; -#[cfg(feature = "std")] -use sp_keystore::vrf::{VRFTranscriptData, VRFTranscriptValue}; -use sp_runtime::{BoundToRuntimeAppPublic, ConsensusEngineId}; - -/// Make VRF transcript from the VrfInput -pub fn make_transcript>(last_vrf_output: Hash) -> Transcript { - let mut transcript = Transcript::new(&VRF_ENGINE_ID); - transcript.append_message(b"last vrf output", last_vrf_output.as_ref()); - transcript -} - -/// Make a VRF transcript data container -#[cfg(feature = "std")] -pub fn make_transcript_data>(last_vrf_output: Hash) -> VRFTranscriptData { - VRFTranscriptData { - label: &VRF_ENGINE_ID, - items: vec![( - "last vrf output", - VRFTranscriptValue::Bytes(last_vrf_output.as_ref().to_vec()), - )], - } -} - -/// Struct to implement `BoundToRuntimeAppPublic` by assigning Public = VrfId -pub struct VrfSessionKey; - -impl BoundToRuntimeAppPublic for VrfSessionKey { - type Public = VrfId; -} - -impl From for VrfId { - fn from(nimbus_id: NimbusId) -> VrfId { - let nimbus_as_sr25519: sr25519::Public = nimbus_id.into(); - let sr25519_as_bytes: [u8; 32] = nimbus_as_sr25519.into(); - sr25519::Public::unchecked_from(sr25519_as_bytes).into() - } -} - -/// The ConsensusEngineId for VRF keys -pub const VRF_ENGINE_ID: ConsensusEngineId = *b"rand"; - -/// The KeyTypeId used for VRF keys -pub const VRF_KEY_ID: KeyTypeId = KeyTypeId(VRF_ENGINE_ID); - -/// VRFInOut context. -pub static VRF_INOUT_CONTEXT: &[u8] = b"VRFInOutContext"; - -// The strongly-typed crypto wrappers to be used by VRF in the keystore -mod vrf_crypto { - use sp_application_crypto::{app_crypto, sr25519}; - app_crypto!(sr25519, crate::VRF_KEY_ID); -} - -/// A vrf public key. -pub type VrfId = vrf_crypto::Public; - -/// A vrf signature. -pub type VrfSignature = vrf_crypto::Signature; - -sp_application_crypto::with_pair! { - /// A vrf key pair - pub type VrfPair = vrf_crypto::Pair; -} - -sp_api::decl_runtime_apis! { - pub trait VrfApi { - fn get_last_vrf_output() -> Option; - fn vrf_key_lookup(nimbus_id: nimbus_primitives::NimbusId) -> Option; - } -} - -#[test] -fn nimbus_to_vrf_id() { - for x in 0u8..10u8 { - let nimbus_id: NimbusId = sr25519::Public::unchecked_from([x; 32]).into(); - let expected_vrf_id: VrfId = sr25519::Public::unchecked_from([x; 32]).into(); - let nimbus_to_vrf_id: VrfId = nimbus_id.into(); - assert_eq!(expected_vrf_id, nimbus_to_vrf_id); - } -} diff --git a/external/vrf/Cargo.toml b/external/vrf/Cargo.toml deleted file mode 100644 index 76915e432..000000000 --- a/external/vrf/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -authors = ["PureStake"] -edition = "2018" -homepage = "https://moonbeam.network" -license = "GPL-3.0-only" -name = "moonbeam-vrf" -repository = "https://github.com/PureStake/moonbeam/" -version = "0.1.0" - -[dependencies] -# Substrate -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.32", default-features = false } - -# Moonbeam -session-keys-primitives = { path = "../session-keys" } - -# Nimbus -nimbus-primitives = { path = "../nimbus-primitives" } - -# Polkadot -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.32" } diff --git a/external/vrf/src/lib.rs b/external/vrf/src/lib.rs deleted file mode 100644 index 6fac4740d..000000000 --- a/external/vrf/src/lib.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Moonbeam is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Moonbeam. If not, see . - -//! VRF client primitives for client-side verification - -use nimbus_primitives::NimbusId; -use session_keys_primitives::{make_transcript, make_transcript_data, PreDigest, VrfApi, VrfId}; -use sp_application_crypto::{AppKey, ByteArray}; -use sp_consensus_vrf::schnorrkel::{PublicKey, VRFOutput, VRFProof}; -use sp_core::H256; -use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; - -/// Uses the runtime API to get the VRF inputs and sign them with the VRF key that -/// corresponds to the authoring NimbusId. -pub fn vrf_pre_digest( - client: &C, - keystore: &SyncCryptoStorePtr, - nimbus_id: NimbusId, - parent: H256, -) -> Option -where - B: sp_runtime::traits::Block, - C: sp_api::ProvideRuntimeApi, - C::Api: VrfApi, -{ - let at = sp_api::BlockId::Hash(parent); - let runtime_api = client.runtime_api(); - - // first ? for runtime API, second ? for if last vrf output is not available - let last_vrf_output = runtime_api.get_last_vrf_output(&at).ok()??; - // first ? for runtime API, second ? for not VRF key associated with NimbusId - let key: VrfId = runtime_api.vrf_key_lookup(&at, nimbus_id).ok()??; - let vrf_pre_digest = sign_vrf(last_vrf_output, key, keystore)?; - Some(session_keys_primitives::digest::CompatibleDigestItem::vrf_pre_digest(vrf_pre_digest)) -} - -/// Signs the VrfInput using the private key corresponding to the input `key` public key -/// to be found in the input keystore -fn sign_vrf(last_vrf_output: H256, key: VrfId, keystore: &SyncCryptoStorePtr) -> Option { - let transcript = make_transcript(last_vrf_output); - let transcript_data = make_transcript_data(last_vrf_output); - let try_sign = - SyncCryptoStore::sr25519_vrf_sign(&**keystore, VrfId::ID, key.as_ref(), transcript_data); - if let Ok(Some(signature)) = try_sign { - let public = PublicKey::from_bytes(&key.to_raw_vec()).ok()?; - if signature.output.attach_input_hash(&public, transcript).is_err() { - // VRF signature cannot be validated using key and transcript - return None; - } - Some(PreDigest { - vrf_output: VRFOutput(signature.output), - vrf_proof: VRFProof(signature.proof), - }) - } else { - // VRF key not found in keystore or VRF signing failed - None - } -} diff --git a/node/Cargo.toml b/node/Cargo.toml index 352653004..0ee6646ce 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -63,18 +63,18 @@ cumulus-relay-chain-rpc-interface = { branch = "polkadot-v0.9.32", git = "https: # Parachain -moonbeam-vrf = { path = "../external/vrf", optional = true } -nimbus-consensus = { default-features = false, path = "../external/nimbus-consensus", optional = true } -nimbus-primitives = { default-features = false, path = "../external/nimbus-primitives", optional = true } -pallet-author-inherent = { default-features = false, path = "../external/pallets/author-inherent", optional = true } -pallet-parachain-staking = { default-features = false, path = "../external/pallets/parachain-staking", optional = true } +moonbeam-vrf = { git = "https://github.com/zeitgeistpm/external", optional = true } +nimbus-consensus = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +nimbus-primitives = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-inherent = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-parachain-staking = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } parity-scale-codec = { optional = true, version = "3.0.0" } sc-chain-spec = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } sc-network = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } sc-network-common = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } sc-tracing = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } serde = { features = ["derive"], optional = true, version = "1.0.144" } -session-keys-primitives = { default-features = false, path = "../external/session-keys", optional = true } +session-keys-primitives = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } sp-keystore = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } substrate-prometheus-endpoint = { branch = "polkadot-v0.9.32", git = "https://github.com/paritytech/substrate", optional = true } diff --git a/runtime/battery-station/Cargo.toml b/runtime/battery-station/Cargo.toml index 0dfe20cbb..018126c82 100644 --- a/runtime/battery-station/Cargo.toml +++ b/runtime/battery-station/Cargo.toml @@ -64,12 +64,12 @@ cumulus-primitives-utility = { branch = "polkadot-v0.9.32", default-features = f parachain-info = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/cumulus", optional = true } # Parachain -nimbus-primitives = { default-features = false, path = "../../external/nimbus-primitives", optional = true } -pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } -pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } -pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } -pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } -session-keys-primitives = { default-features = false, path = "../../external/session-keys", optional = true } +nimbus-primitives = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-inherent = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-mapping = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-slot-filter = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-parachain-staking = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +session-keys-primitives = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } # Polkadot diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 9acb6a2d3..c35c07394 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -5,9 +5,9 @@ frame-support = { branch = "polkadot-v0.9.32", default-features = false, git = " frame-system = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } orml-currencies = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } orml-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } -pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } -pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } -pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } +pallet-author-inherent = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-mapping = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-slot-filter = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } pallet-balances = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-bounties = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-collective = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } @@ -15,7 +15,7 @@ pallet-democracy = { branch = "polkadot-v0.9.32", default-features = false, git pallet-identity = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-membership = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-multisig = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } -pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } +pallet-parachain-staking = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } pallet-preimage = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-proxy = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-randomness-collective-flip = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } diff --git a/runtime/zeitgeist/Cargo.toml b/runtime/zeitgeist/Cargo.toml index ec9db678a..b216aeac2 100644 --- a/runtime/zeitgeist/Cargo.toml +++ b/runtime/zeitgeist/Cargo.toml @@ -63,12 +63,12 @@ parachain-info = { branch = "polkadot-v0.9.32", default-features = false, git = # Parachain -nimbus-primitives = { default-features = false, path = "../../external/nimbus-primitives", optional = true } -pallet-author-inherent = { default-features = false, path = "../../external/pallets/author-inherent", optional = true } -pallet-author-mapping = { default-features = false, path = "../../external/pallets/author-mapping", optional = true } -pallet-author-slot-filter = { default-features = false, path = "../../external/pallets/author-slot-filter", optional = true } -pallet-parachain-staking = { default-features = false, path = "../../external/pallets/parachain-staking", optional = true } -session-keys-primitives = { default-features = false, path = "../../external/session-keys", optional = true } +nimbus-primitives = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-inherent = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-mapping = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-author-slot-filter = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +pallet-parachain-staking = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } +session-keys-primitives = { default-features = false, git = "https://github.com/zeitgeistpm/external", optional = true } # Polkadot From 01e9591cb1277d42f46953b384fc810674ae870b Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Thu, 4 May 2023 12:24:53 +0200 Subject: [PATCH 16/22] Fix dependencies --- Cargo.lock | 1 + runtime/battery-station/Cargo.toml | 5 ++--- runtime/zeitgeist/Cargo.toml | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46d0b186f..28287f47d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12918,6 +12918,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "kusama-runtime", "log", "nimbus-primitives", "orml-asset-registry", diff --git a/runtime/battery-station/Cargo.toml b/runtime/battery-station/Cargo.toml index f25c385a2..5ebb54694 100644 --- a/runtime/battery-station/Cargo.toml +++ b/runtime/battery-station/Cargo.toml @@ -30,6 +30,7 @@ pallet-treasury = { branch = "polkadot-v0.9.32", default-features = false, git = pallet-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-vesting = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } +polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } sp-block-builder = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } @@ -94,7 +95,6 @@ orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, g orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } orml-xtokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } pallet-xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } -polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot" } polkadot-runtime-parachains = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } rococo-runtime = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } @@ -154,7 +154,6 @@ parachain = [ "orml-xcm-support", "orml-xtokens", "pallet-xcm", - "polkadot-primitives", "polkadot-runtime-parachains", "rococo-runtime", "xcm-builder", @@ -242,6 +241,7 @@ std = [ "pallet-utility/std", "pallet-vesting/std", "parity-scale-codec/std", + "polkadot-primitives/std", "scale-info/std", "sp-api/std", "sp-block-builder/std", @@ -301,7 +301,6 @@ std = [ "orml-xcm-support?/std", "orml-xtokens?/std", "pallet-xcm?/std", - "polkadot-primitives?/std", "polkadot-runtime-parachains?/std", "rococo-runtime?/std", "xcm-builder?/std", diff --git a/runtime/zeitgeist/Cargo.toml b/runtime/zeitgeist/Cargo.toml index e44ea74b8..42ae549cb 100644 --- a/runtime/zeitgeist/Cargo.toml +++ b/runtime/zeitgeist/Cargo.toml @@ -28,6 +28,7 @@ pallet-treasury = { branch = "polkadot-v0.9.32", default-features = false, git = pallet-utility = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } pallet-vesting = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } +polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } sp-api = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } sp-block-builder = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/paritytech/substrate" } @@ -93,8 +94,7 @@ orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, g orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } orml-xtokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } pallet-xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } -polkadot-primitives = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot" } -polkadot-runtime = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/zeitgeistpm/polkadot", optional = true } +polkadot-runtime = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } polkadot-runtime-parachains = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } xcm-builder = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } @@ -148,7 +148,6 @@ parachain = [ # XCM - "polkadot-primitives", "polkadot-runtime", "polkadot-runtime-parachains", "orml-asset-registry", @@ -239,6 +238,7 @@ std = [ "pallet-utility/std", "pallet-vesting/std", "parity-scale-codec/std", + "polkadot-primitives/std", "scale-info/std", "sp-api/std", "sp-block-builder/std", @@ -281,7 +281,6 @@ std = [ # XCM - "polkadot-primitives?/std", "polkadot-runtime?/std", "polkadot-runtime-parachains?/std", "orml-asset-registry?/std", From f075c70b597064a0cde0d6960c8882198672a55e Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Mon, 22 May 2023 11:41:52 +0200 Subject: [PATCH 17/22] Add missing feature to polkadot-cli --- Cargo.lock | 1 - node/Cargo.toml | 1 + runtime/zeitgeist/Cargo.toml | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28287f47d..46d0b186f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12918,7 +12918,6 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", - "kusama-runtime", "log", "nimbus-primitives", "orml-asset-registry", diff --git a/node/Cargo.toml b/node/Cargo.toml index 0ee6646ce..9b8bf813d 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -158,6 +158,7 @@ runtime-benchmarks = [ "battery-station-runtime?/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-benchmarking-cli/runtime-benchmarks", + "polkadot-cli?/runtime-benchmarks", "polkadot-service?/runtime-benchmarks", "zeitgeist-runtime?/runtime-benchmarks", ] diff --git a/runtime/zeitgeist/Cargo.toml b/runtime/zeitgeist/Cargo.toml index 42ae549cb..417df6562 100644 --- a/runtime/zeitgeist/Cargo.toml +++ b/runtime/zeitgeist/Cargo.toml @@ -88,7 +88,6 @@ hex-literal = { default-features = false, optional = true, version = "0.3.4" } log = { version = "0.4.17", default-features = false, optional = true } # XCM -kusama-runtime = { branch = "release-v0.9.32", default-features = false, git = "https://github.com/paritytech/polkadot", optional = true } orml-asset-registry = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } orml-unknown-tokens = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } orml-xcm-support = { branch = "polkadot-v0.9.32", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library", optional = true } From fd0b51a581ee633f5308f6e45ba6bbf177436b1a Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Mon, 22 May 2023 17:37:57 +0200 Subject: [PATCH 18/22] Use proper origins and traits --- .../battery-station/src/integration_tests/xcm/test_net.rs | 5 ++++- .../src/integration_tests/xcm/tests/transfers.rs | 2 +- .../zeitgeist/src/integration_tests/xcm/tests/transfers.rs | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/runtime/battery-station/src/integration_tests/xcm/test_net.rs b/runtime/battery-station/src/integration_tests/xcm/test_net.rs index c2cbbe296..bd7e87b94 100644 --- a/runtime/battery-station/src/integration_tests/xcm/test_net.rs +++ b/runtime/battery-station/src/integration_tests/xcm/test_net.rs @@ -21,7 +21,10 @@ use crate::{ CurrencyId, DmpQueue, Runtime, RuntimeOrigin, XcmpQueue, }; use frame_support::{traits::GenesisBuild, weights::Weight}; -use polkadot_primitives::v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; +use polkadot_primitives::{ + runtime_api::runtime_decl_for_ParachainHost::ParachainHostV3, + v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}, +}; use polkadot_runtime_parachains::configuration::HostConfiguration; use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; diff --git a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs index fc71c3157..78b326029 100644 --- a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs @@ -187,7 +187,7 @@ fn transfer_roc_from_relay_chain() { assert!(initial_balance >= transfer_amount); assert_ok!(rococo_runtime::XcmPallet::reserve_transfer_assets( - rococo_runtime::Origin::signed(ALICE.into()), + rococo_runtime::RuntimeOrigin::signed(ALICE.into()), Box::new(Parachain(battery_station::ID).into().into()), Box::new(Junction::AccountId32 { network: NetworkId::Any, id: BOB }.into().into()), Box::new((Here, transfer_amount).into()), diff --git a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs index e940b3fea..b537311f3 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs @@ -187,7 +187,7 @@ fn transfer_dot_from_relay_chain() { assert!(initial_balance >= transfer_amount); assert_ok!(polkadot_runtime::XcmPallet::reserve_transfer_assets( - polkadot_runtime::Origin::signed(ALICE.into()), + polkadot_runtime::RuntimeOrigin::signed(ALICE.into()), Box::new(Parachain(zeitgeist::ID).into().into()), Box::new(Junction::AccountId32 { network: NetworkId::Any, id: BOB }.into().into()), Box::new((Here, transfer_amount).into()), From db88e31da64ee8e851d5193217530704701df371 Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Tue, 23 May 2023 10:57:31 +0200 Subject: [PATCH 19/22] Apply most recent migration code --- zrml/prediction-markets/src/migrations.rs | 41 +++++++++++------------ 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index b43ee6cf5..78d716df8 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -26,8 +26,8 @@ use alloc::format; use alloc::vec::Vec; #[cfg(feature = "try-runtime")] use frame_support::migration::storage_key_iter; -// #[cfg(feature = "try-runtime")] -// use frame_support::traits::OnRuntimeUpgradeHelpersExt; +#[cfg(feature = "try-runtime")] +use frame_support::traits::OnRuntimeUpgradeHelpersExt; use frame_support::{ dispatch::Weight, log, @@ -150,7 +150,7 @@ impl OnRuntimeUpgrade for AddOutsiderBo } #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, &'static str> { + fn pre_upgrade() -> Result<(), &'static str> { use frame_support::pallet_prelude::Blake2_128Concat; let old_markets = storage_key_iter::, OldMarketOf, Blake2_128Concat>( @@ -158,30 +158,27 @@ impl OnRuntimeUpgrade for AddOutsiderBo MARKETS, ) .collect::>(); - // Self::set_temp_storage(old_markets, "old_markets"); + Self::set_temp_storage(old_markets, "old_markets"); - // let markets = Markets::::iter_keys().count() as u32; - // let decodable_markets = Markets::::iter_values().count() as u32; - // if markets != decodable_markets { - // log::error!( - // "Can only decode {} of {} markets - others will be dropped", - // decodable_markets, - // markets - // ); - // } else { - // log::info!("Markets: {}, Decodable Markets: {}", markets, decodable_markets); - // } + let markets = Markets::::iter_keys().count() as u32; + let decodable_markets = Markets::::iter_values().count() as u32; + if markets != decodable_markets { + log::error!( + "Can only decode {} of {} markets - others will be dropped", + decodable_markets, + markets + ); + } else { + log::info!("Markets: {}, Decodable Markets: {}", markets, decodable_markets); + } - Ok(old_markets.encode()) + Ok(()) } #[cfg(feature = "try-runtime")] - fn post_upgrade(old_markets: Vec) -> Result<(), &'static str> { - // let old_markets: BTreeMap, OldMarketOf> = - // Self::get_temp_storage("old_markets").unwrap(); + fn post_upgrade() -> Result<(), &'static str> { let old_markets: BTreeMap, OldMarketOf> = - Decode::decode(&mut old_markets.as_slice()) - .expect("old_markets not generated properly by pre_upgrade"); + Self::get_temp_storage("old_markets").unwrap(); let new_market_count = >::market_iter().count(); assert_eq!(old_markets.len(), new_market_count); for (market_id, new_market) in >::market_iter() { @@ -406,4 +403,4 @@ mod utility { let hash = key_to_hash::(pool_id); put_storage_value(SWAPS, POOLS, &hash, Some(pool)); } -} +} \ No newline at end of file From 2c18a7c0862370b0303097a5b887c9725c18cb76 Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Tue, 23 May 2023 10:58:35 +0200 Subject: [PATCH 20/22] Cargo fmt --- zrml/prediction-markets/src/migrations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 78d716df8..15c18bf56 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -403,4 +403,4 @@ mod utility { let hash = key_to_hash::(pool_id); put_storage_value(SWAPS, POOLS, &hash, Some(pool)); } -} \ No newline at end of file +} From 752aee99a1eb78112dd8f8824c13151e1e0a9990 Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Tue, 23 May 2023 13:26:32 +0200 Subject: [PATCH 21/22] Use new state transfer scheme in try-runtime --- zrml/prediction-markets/src/migrations.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 15c18bf56..e1b0c42ae 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -26,8 +26,6 @@ use alloc::format; use alloc::vec::Vec; #[cfg(feature = "try-runtime")] use frame_support::migration::storage_key_iter; -#[cfg(feature = "try-runtime")] -use frame_support::traits::OnRuntimeUpgradeHelpersExt; use frame_support::{ dispatch::Weight, log, @@ -150,7 +148,7 @@ impl OnRuntimeUpgrade for AddOutsiderBo } #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result<(), &'static str> { + fn pre_upgrade() -> Result, &'static str> { use frame_support::pallet_prelude::Blake2_128Concat; let old_markets = storage_key_iter::, OldMarketOf, Blake2_128Concat>( @@ -158,7 +156,6 @@ impl OnRuntimeUpgrade for AddOutsiderBo MARKETS, ) .collect::>(); - Self::set_temp_storage(old_markets, "old_markets"); let markets = Markets::::iter_keys().count() as u32; let decodable_markets = Markets::::iter_values().count() as u32; @@ -172,13 +169,14 @@ impl OnRuntimeUpgrade for AddOutsiderBo log::info!("Markets: {}, Decodable Markets: {}", markets, decodable_markets); } - Ok(()) + Ok(old_markets.encode()) } #[cfg(feature = "try-runtime")] - fn post_upgrade() -> Result<(), &'static str> { + fn post_upgrade(previous_state: Vec) -> Result<(), &'static str> { let old_markets: BTreeMap, OldMarketOf> = - Self::get_temp_storage("old_markets").unwrap(); + Decode::decode(&mut &previous_state[..]) + .expect("Failed to decode state: Invalid state"); let new_market_count = >::market_iter().count(); assert_eq!(old_markets.len(), new_market_count); for (market_id, new_market) in >::market_iter() { From 6f82f9a43d2be7b22df02837fdcc06e03f1d156a Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Thu, 25 May 2023 16:59:48 +0200 Subject: [PATCH 22/22] Respect new XCM fee on Rococo & Polkadot --- .../src/integration_tests/xcm/tests/transfers.rs | 2 +- runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs index 78b326029..77631353a 100644 --- a/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/battery-station/src/integration_tests/xcm/tests/transfers.rs @@ -235,7 +235,7 @@ fn transfer_roc_to_relay_chain() { }); RococoNet::execute_with(|| { - assert_eq!(rococo_runtime::Balances::free_balance(&BOB.into()), 948_894_198_216); + assert_eq!(rococo_runtime::Balances::free_balance(&BOB.into()), 999_988_806_429); }); } diff --git a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs index b537311f3..316fb19d1 100644 --- a/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs +++ b/runtime/zeitgeist/src/integration_tests/xcm/tests/transfers.rs @@ -235,7 +235,7 @@ fn transfer_dot_to_relay_chain() { }); PolkadotNet::execute_with(|| { - assert_eq!(polkadot_runtime::Balances::free_balance(&BOB.into()), 19_530_582_548); + assert_eq!(polkadot_runtime::Balances::free_balance(&BOB.into()), 19_573_469_824); }); }