diff --git a/Cargo.lock b/Cargo.lock index 0a9e201290a50..3d51a0fb1ffa4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1189,9 +1189,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70d3ad08698a0568b0562f22710fe6bfc1f4a61a367c77d0398c562eadd453a" +checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9" dependencies = [ "smallvec", ] @@ -1440,9 +1440,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "7.0.0" +version = "7.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e1f7e5d046697d34b593bdba8ee31f4649366e452a2ccabb3baf3511e503d1" +checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b" dependencies = [ "strum", "strum_macros", @@ -2915,6 +2915,7 @@ dependencies = [ "frame-support", "frame-system", "frame-try-runtime", + "log", "pallet-balances", "pallet-transaction-payment", "parity-scale-codec", @@ -2994,12 +2995,14 @@ dependencies = [ "sp-genesis-builder", "sp-inherents", "sp-io", + "sp-metadata-ir", "sp-runtime", "sp-staking", "sp-state-machine", "sp-std", "sp-tracing", "sp-weights", + "static_assertions", "tt-call", ] @@ -3046,6 +3049,7 @@ version = "3.0.0" dependencies = [ "frame-benchmarking", "frame-executive", + "frame-metadata", "frame-support", "frame-support-test-pallet", "frame-system", @@ -3058,6 +3062,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-io", + "sp-metadata-ir", "sp-runtime", "sp-state-machine", "sp-std", @@ -3708,33 +3713,19 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" -dependencies = [ - "http", - "hyper", - "log", - "rustls 0.20.8", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.23.4", - "webpki-roots", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", "log", - "rustls 0.21.1", + "rustls 0.21.6", "rustls-native-certs", "tokio", - "tokio-rustls 0.24.0", + "tokio-rustls", + "webpki-roots 0.23.1", ] [[package]] @@ -4050,9 +4041,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -4065,9 +4056,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" +checksum = "c8b3815d9f5d5de348e5f162b316dc9cdf4548305ebb15b4eb9328e66cf27d7a" dependencies = [ "futures-util", "http", @@ -4078,17 +4069,17 @@ dependencies = [ "soketto", "thiserror", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls", "tokio-util", "tracing", - "webpki-roots", + "webpki-roots 0.25.2", ] [[package]] name = "jsonrpsee-core" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +checksum = "2b5dde66c53d6dcdc8caea1874a45632ec0fcf5b437789f1e45766a1512ce803" dependencies = [ "anyhow", "arrayvec 0.7.2", @@ -4114,13 +4105,13 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" +checksum = "7e5f9fabdd5d79344728521bb65e3106b49ec405a78b66fbff073b72b389fa43" dependencies = [ "async-trait", "hyper", - "hyper-rustls 0.23.2", + "hyper-rustls", "jsonrpsee-core", "jsonrpsee-types", "rustc-hash", @@ -4133,9 +4124,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" +checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" dependencies = [ "heck", "proc-macro-crate", @@ -4146,9 +4137,9 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb69dad85df79527c019659a992498d03f8495390496da2f07e6c24c2b356fc" +checksum = "cf4d945a6008c9b03db3354fb3c83ee02d2faa9f2e755ec1dfb69c3551b8f4ba" dependencies = [ "futures-channel", "futures-util", @@ -4168,9 +4159,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +checksum = "245ba8e5aa633dd1c1e4fae72bce06e71f42d34c14a2767c6b4d173b57bee5e5" dependencies = [ "anyhow", "beef", @@ -4182,9 +4173,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b83daeecfc6517cfe210df24e570fb06213533dfb990318fae781f4c7119dd9" +checksum = "4e1b3975ed5d73f456478681a417128597acd6a2487855fdb7b4a3d4d195bf5e" dependencies = [ "http", "jsonrpsee-client-transport", @@ -4252,6 +4243,7 @@ dependencies = [ "pallet-bags-list", "pallet-balances", "pallet-bounties", + "pallet-broker", "pallet-child-bounties", "pallet-collective", "pallet-contracts", @@ -4290,6 +4282,7 @@ dependencies = [ "pallet-referenda", "pallet-remark", "pallet-root-testing", + "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-session", @@ -4307,6 +4300,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", + "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", @@ -4328,6 +4322,7 @@ dependencies = [ "sp-staking", "sp-statement-store", "sp-std", + "sp-storage", "sp-transaction-pool", "sp-version", "static_assertions", @@ -4387,9 +4382,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.145" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc86cde3ff845662b8f4ef6cb50ea0e20c524eb3d29ae048287e06a1b3fa6a81" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -4816,7 +4811,7 @@ dependencies = [ "rw-stream-sink", "soketto", "url", - "webpki-roots", + "webpki-roots 0.22.6", ] [[package]] @@ -5835,6 +5830,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-std", + "sp-storage", "sp-transaction-pool", "sp-version", "substrate-wasm-builder", @@ -6203,6 +6199,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "pallet-balances", "parity-scale-codec", "scale-info", @@ -6233,6 +6230,7 @@ version = "4.0.0-dev" dependencies = [ "frame-support", "frame-system", + "log", "pallet-timestamp", "parity-scale-codec", "scale-info", @@ -6378,6 +6376,7 @@ dependencies = [ "frame-election-provider-support", "frame-support", "frame-system", + "log", "pallet-authorship", "pallet-balances", "pallet-offences", @@ -6394,6 +6393,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", + "sp-state-machine", "sp-std", ] @@ -6418,6 +6418,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-staking", + "sp-state-machine", "sp-std", ] @@ -6439,6 +6440,23 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-broker" +version = "0.1.0" +dependencies = [ + "bitvec", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-child-bounties" version = "4.0.0-dev" @@ -6681,6 +6699,7 @@ dependencies = [ "parity-scale-codec", "sp-npos-elections", "sp-runtime", + "sp-std", ] [[package]] @@ -6989,6 +7008,7 @@ dependencies = [ "frame-support", "frame-system", "itertools", + "log", "parity-scale-codec", "scale-info", "sp-core", @@ -7257,6 +7277,7 @@ dependencies = [ "scale-info", "sp-core", "sp-io", + "sp-metadata-ir", "sp-runtime", "sp-std", ] @@ -7412,6 +7433,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-safe-mode" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-proxy", + "pallet-utility", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-salary" version = "4.0.0-dev" @@ -7480,6 +7520,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", + "sp-state-machine", "sp-std", "sp-trie", ] @@ -7654,6 +7695,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "sp-std", ] [[package]] @@ -7671,6 +7713,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", + "sp-storage", "sp-timestamp", ] @@ -7777,6 +7820,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-tx-pause" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-proxy", + "pallet-utility", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-uniques" version = "4.0.0-dev" @@ -9033,13 +9094,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.1" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ "log", "ring 0.16.20", - "rustls-webpki", + "rustls-webpki 0.101.4", "sct 0.7.0", ] @@ -9066,9 +9127,19 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" +dependencies = [ + "ring 0.16.20", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring 0.16.20", "untrusted", @@ -10061,7 +10132,7 @@ dependencies = [ "futures", "futures-timer", "hyper", - "hyper-rustls 0.24.0", + "hyper-rustls", "lazy_static", "libp2p", "log", @@ -12479,9 +12550,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -12718,22 +12789,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.8", - "tokio", - "webpki 0.22.0", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.1", + "rustls 0.21.6", "tokio", ] @@ -13828,6 +13888,21 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.2", +] + +[[package]] +name = "webpki-roots" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" + [[package]] name = "webrtc" version = "0.6.0" @@ -14368,9 +14443,9 @@ dependencies = [ [[package]] name = "xattr" -version = "0.2.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 9ee8142e23e76..3585a5ecd3572 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,6 +131,7 @@ members = [ "frame/benchmarking", "frame/benchmarking/pov", "frame/bounties", + "frame/broker", "frame/child-bounties", "frame/collective", "frame/contracts", @@ -187,6 +188,8 @@ members = [ "frame/recovery", "frame/referenda", "frame/remark", + "frame/tx-pause", + "frame/safe-mode", "frame/salary", "frame/scheduler", "frame/scored-pool", diff --git a/README.md b/README.md index b6b5d0ccc9c41..59e0cff015d39 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,13 @@ -# Substrate · [![GitHub license](https://img.shields.io/badge/license-GPL3%2FApache2-blue)](#LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/substrate/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/substrate/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.md) [![Stack Exchange](https://img.shields.io/badge/Substrate-Community%20&%20Support-24CC85?logo=stackexchange)](https://substrate.stackexchange.com/) -

- -

+Dear contributors and users, -Substrate is a next-generation framework for blockchain innovation 🚀. +We would like to inform you that we have recently made significant changes to our repository structure. In order to streamline our development process and foster better contributions, we have merged three separate repositories Cumulus, Substrate and Polkadot into a single new repository: [the Polkadot SDK](https://github.com/paritytech/polkadot-sdk). Go ahead and make sure to support us by giving a star ⭐️ to the new repo. -## Getting Started +By consolidating our codebase, we aim to enhance collaboration and provide a more efficient platform for future development. -Head to [docs.substrate.io](https://docs.substrate.io) and follow the [installation](https://docs.substrate.io/install/) instructions. -Then try out one of the [tutorials](https://docs.substrate.io/tutorials/). -Refer to the [Docker instructions](./docker/README.md) to quickly run Substrate, Substrate Node Template, Subkey, or to build a chain spec. +If you currently have an open pull request in any of the merged repositories, we kindly request that you resubmit your PR in the new repository. This will ensure that your contributions are considered within the updated context and enable us to review and merge them more effectively. -## Community & Support +We appreciate your understanding and ongoing support throughout this transition. Should you have any questions or require further assistance, please don't hesitate to [reach out to us](https://forum.polkadot.network/t/psa-parity-is-currently-working-on-merging-the-polkadot-stack-repositories-into-one-single-repository/2883). -Join the highly active and supportive community on the [Substrate Stack Exchange](https://substrate.stackexchange.com/) to ask questions about use and problems you run into using this software. -Please do report bugs and [issues here](https://github.com/paritytech/substrate/issues) for anything you suspect requires action in the source. +Best Regards, -## Contributions & Code of Conduct - -Please follow the contributions guidelines as outlined in [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md). -In all communications and contributions, this project follows the [Contributor Covenant Code of Conduct](docs/CODE_OF_CONDUCT.md). - -## Security - -The security policy and procedures can be found in [`docs/SECURITY.md`](docs/SECURITY.md). - -## License - -- Substrate Primitives (`sp-*`), Frame (`frame-*`) and the pallets (`pallets-*`), binaries (`/bin`) and all other utilities are licensed under [Apache 2.0](LICENSE-APACHE2). -- Substrate Client (`/client/*` / `sc-*`) is licensed under [GPL v3.0 with a classpath linking exception](LICENSE-GPL3). - -The reason for the split-licensing is to ensure that for the vast majority of teams using Substrate to create feature-chains, then all changes can be made entirely in Apache2-licensed code, allowing teams full freedom over what and how they release and giving licensing clarity to commercial teams. - -In the interests of the community, we require any deeper improvements made to Substrate's core logic (e.g. Substrate's internal consensus, crypto or database code) to be contributed back so everyone can benefit. +Parity Technologies \ No newline at end of file diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index b05fed96bc8a2..6eb5b4df9c536 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -70,19 +70,19 @@ substrate-build-script-utils = { version = "3.0.0", path = "../../../utils/build default = [] # Dependencies that are only required if runtime benchmarking should be build. runtime-benchmarks = [ - "node-template-runtime/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", "frame-benchmarking-cli/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", + "node-template-runtime/runtime-benchmarks", "sc-service/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] # Enable features that allow the runtime to be tried and debugged. Name might be subject to change # in the near future. try-runtime = [ - "node-template-runtime/try-runtime", - "try-runtime-cli/try-runtime", "frame-system/try-runtime", + "node-template-runtime/try-runtime", "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", + "try-runtime-cli/try-runtime", ] diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml index f468374c2ff9f..ba108cd0052fe 100644 --- a/bin/node-template/pallets/template/Cargo.toml +++ b/bin/node-template/pallets/template/Cargo.toml @@ -20,6 +20,7 @@ scale-info = { version = "2.5.0", default-features = false, features = ["derive" frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../../../../frame/benchmarking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../../frame/system" } +sp-std = { version = "8.0.0", default-features = false, path = "../../../../primitives/std" } [dev-dependencies] sp-core = { version = "21.0.0", path = "../../../../primitives/core" } @@ -27,7 +28,7 @@ sp-io = { version = "23.0.0", path = "../../../../primitives/io" } sp-runtime = { version = "24.0.0", path = "../../../../primitives/runtime" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -36,16 +37,17 @@ std = [ "scale-info/std", "sp-core/std", "sp-io/std", - "sp-runtime/std" + "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/bin/node-template/pallets/template/src/benchmarking.rs b/bin/node-template/pallets/template/src/benchmarking.rs index 5a262417629c5..6c3cae6066b41 100644 --- a/bin/node-template/pallets/template/src/benchmarking.rs +++ b/bin/node-template/pallets/template/src/benchmarking.rs @@ -1,6 +1,7 @@ //! Benchmarking setup for pallet-template #![cfg(feature = "runtime-benchmarks")] use super::*; +use sp_std::vec; #[allow(unused)] use crate::Pallet as Template; diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml index 51e30187c9d63..5f4411df54110 100644 --- a/bin/node-template/runtime/Cargo.toml +++ b/bin/node-template/runtime/Cargo.toml @@ -36,6 +36,7 @@ sp-offchain = { version = "4.0.0-dev", default-features = false, path = "../../. sp-runtime = { version = "24.0.0", default-features = false, path = "../../../primitives/runtime" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" } +sp-storage = { version = "13.0.0", default-features = false, path = "../../../primitives/storage" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-version = { version = "22.0.0", default-features = false, path = "../../../primitives/version" } @@ -54,18 +55,17 @@ pallet-template = { version = "4.0.0-dev", default-features = false, path = "../ substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder", optional = true } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-try-runtime?/std", - "frame-system-benchmarking?/std", - "frame-benchmarking?/std", "codec/std", - "scale-info/std", + "frame-benchmarking?/std", "frame-executive/std", "frame-support/std", + "frame-system-benchmarking?/std", "frame-system-rpc-runtime-api/std", "frame-system/std", "frame-try-runtime/std", + "frame-try-runtime?/std", "pallet-aura/std", "pallet-balances/std", "pallet-grandpa/std", @@ -74,6 +74,7 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "scale-info/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -84,6 +85,7 @@ std = [ "sp-runtime/std", "sp-session/std", "sp-std/std", + "sp-storage/std", "sp-transaction-pool/std", "sp-version/std", "substrate-wasm-builder", @@ -101,10 +103,10 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", ] try-runtime = [ - "frame-try-runtime/try-runtime", "frame-executive/try-runtime", - "frame-system/try-runtime", "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", "pallet-aura/try-runtime", "pallet-balances/try-runtime", "pallet-grandpa/try-runtime", @@ -112,6 +114,6 @@ try-runtime = [ "pallet-template/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] +experimental = [ "pallet-aura/experimental" ] diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index c3375d2ee601a..216be9588bca1 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -531,8 +531,8 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; - + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; + use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; use baseline::Pallet as BaselineBench; diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 37f03fbb0dd7e..fcab4cc6517a9 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -147,22 +147,22 @@ pallet-balances = { version = "4.0.0-dev", path = "../../../frame/balances" } sc-storage-monitor = { version = "0.1.0", path = "../../../client/storage-monitor" } [features] -default = ["cli"] +default = [ "cli" ] cli = [ + "clap", + "clap_complete", + "frame-benchmarking-cli", "node-inspect", "sc-cli", - "frame-benchmarking-cli", - "substrate-frame-cli", "sc-service/rocksdb", - "clap", - "clap_complete", "substrate-build-script-utils", + "substrate-frame-cli", "try-runtime-cli", ] runtime-benchmarks = [ - "kitchensink-runtime/runtime-benchmarks", "frame-benchmarking-cli/runtime-benchmarks", "frame-system/runtime-benchmarks", + "kitchensink-runtime/runtime-benchmarks", "pallet-asset-tx-payment/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -170,14 +170,13 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] # Enable features that allow the runtime to be tried and debugged. Name might be subject to change # in the near future. try-runtime = [ - "kitchensink-runtime/try-runtime", - "try-runtime-cli/try-runtime", "frame-system/try-runtime", + "kitchensink-runtime/try-runtime", "pallet-asset-conversion-tx-payment/try-runtime", "pallet-asset-tx-payment/try-runtime", "pallet-assets/try-runtime", @@ -185,7 +184,8 @@ try-runtime = [ "pallet-im-online/try-runtime", "pallet-timestamp/try-runtime", "sp-runtime/try-runtime", - "substrate-cli-test-utils/try-runtime" + "substrate-cli-test-utils/try-runtime", + "try-runtime-cli/try-runtime", ] [[bench]] diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index 57d367e7c49a8..51beaad03688a 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -358,6 +358,8 @@ pub fn testnet_genesis( transaction_storage: Default::default(), transaction_payment: Default::default(), alliance: Default::default(), + safe_mode: Default::default(), + tx_pause: Default::default(), alliance_motion: Default::default(), nomination_pools: NominationPoolsConfig { min_create_bond: 10 * DOLLARS, diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index ac178c67f7188..586d0bce2dbbc 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -17,8 +17,5 @@ sp-core = { version = "21.0.0", default-features = false, path = "../../../primi sp-runtime = { version = "24.0.0", default-features = false, path = "../../../primitives/runtime" } [features] -default = ["std"] -std = [ - "sp-core/std", - "sp-runtime/std", -] +default = [ "std" ] +std = [ "sp-core/std", "sp-runtime/std" ] diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index de0ec1a5489a8..4aa048efcf60a 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -40,6 +40,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../../primiti sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-runtime = { version = "24.0.0", default-features = false, path = "../../../primitives/runtime" } sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/staking" } +sp-storage = { version = "13.0.0", default-features = false, path = "../../../primitives/storage" } sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } sp-statement-store = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/statement-store" } @@ -66,6 +67,7 @@ pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../. pallet-bags-list = { version = "4.0.0-dev", default-features = false, path = "../../../frame/bags-list" } pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../../frame/balances" } pallet-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/bounties" } +pallet-broker = { version = "0.1.0", default-features = false, path = "../../../frame/broker" } pallet-child-bounties = { version = "4.0.0-dev", default-features = false, path = "../../../frame/child-bounties" } pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../../../frame/collective" } pallet-contracts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/contracts" } @@ -127,128 +129,138 @@ pallet-transaction-storage = { version = "4.0.0-dev", default-features = false, pallet-uniques = { version = "4.0.0-dev", default-features = false, path = "../../../frame/uniques" } pallet-vesting = { version = "4.0.0-dev", default-features = false, path = "../../../frame/vesting" } pallet-whitelist = { version = "4.0.0-dev", default-features = false, path = "../../../frame/whitelist" } +pallet-tx-pause = { version = "4.0.0-dev", default-features = false, path = "../../../frame/tx-pause" } +pallet-safe-mode = { version = "4.0.0-dev", default-features = false, path = "../../../frame/safe-mode" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder", optional = true } [features] -default = ["std"] -with-tracing = ["frame-executive/with-tracing"] +default = [ "std" ] +with-tracing = [ "frame-executive/with-tracing" ] std = [ - "pallet-whitelist/std", - "pallet-offences-benchmarking?/std", - "pallet-election-provider-support-benchmarking?/std", - "pallet-asset-conversion-tx-payment/std", - "pallet-asset-tx-payment/std", - "frame-system-benchmarking?/std", + "codec/std", + "frame-benchmarking-pallet-pov/std", + "frame-benchmarking/std", "frame-election-provider-support/std", - "sp-authority-discovery/std", + "frame-executive/std", + "frame-support/std", + "frame-system-benchmarking?/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime?/std", + "log/std", + "node-primitives/std", + "pallet-alliance/std", + "pallet-asset-conversion-tx-payment/std", "pallet-asset-conversion/std", + "pallet-asset-rate/std", + "pallet-asset-tx-payment/std", "pallet-assets/std", "pallet-authority-discovery/std", "pallet-authorship/std", - "sp-consensus-babe/std", - "sp-consensus-grandpa/std", "pallet-babe/std", "pallet-bags-list/std", "pallet-balances/std", "pallet-bounties/std", - "sp-block-builder/std", - "codec/std", - "scale-info/std", + "pallet-broker/std", + "pallet-child-bounties/std", "pallet-collective/std", - "pallet-contracts/std", "pallet-contracts-primitives/std", + "pallet-contracts/std", "pallet-conviction-voting/std", "pallet-core-fellowship/std", "pallet-democracy/std", + "pallet-election-provider-multi-phase/std", + "pallet-election-provider-support-benchmarking?/std", "pallet-elections-phragmen/std", "pallet-fast-unstake/std", - "frame-executive/std", - "pallet-nis/std", + "pallet-glutton/std", "pallet-grandpa/std", + "pallet-identity/std", "pallet-im-online/std", "pallet-indices/std", - "sp-inherents/std", + "pallet-insecure-randomness-collective-flip/std", "pallet-lottery/std", "pallet-membership/std", "pallet-message-queue/std", "pallet-mmr/std", "pallet-multisig/std", - "pallet-nomination-pools/std", - "pallet-nomination-pools-runtime-api/std", + "pallet-nft-fractionalization/std", + "pallet-nfts-runtime-api/std", + "pallet-nfts/std", + "pallet-nis/std", "pallet-nomination-pools-benchmarking?/std", - "pallet-identity/std", - "pallet-scheduler/std", - "node-primitives/std", - "sp-offchain/std", + "pallet-nomination-pools-runtime-api/std", + "pallet-nomination-pools/std", + "pallet-offences-benchmarking?/std", "pallet-offences/std", - "pallet-glutton/std", "pallet-preimage/std", "pallet-proxy/std", - "sp-core/std", - "pallet-insecure-randomness-collective-flip/std", - "sp-std/std", - "pallet-session/std", + "pallet-ranked-collective/std", + "pallet-recovery/std", + "pallet-referenda/std", + "pallet-remark/std", + "pallet-root-testing/std", + "pallet-safe-mode/std", + "pallet-salary/std", + "pallet-scheduler/std", "pallet-session-benchmarking?/std", - "sp-api/std", - "sp-runtime/std", - "sp-staking/std", - "pallet-staking/std", + "pallet-session/std", + "pallet-society/std", "pallet-staking-runtime-api/std", + "pallet-staking/std", "pallet-state-trie-migration/std", "pallet-statement/std", - "pallet-salary/std", - "sp-session/std", "pallet-sudo/std", - "frame-support/std", - "frame-benchmarking/std", - "frame-benchmarking-pallet-pov/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "pallet-election-provider-multi-phase/std", "pallet-timestamp/std", "pallet-tips/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", "pallet-transaction-storage/std", "pallet-treasury/std", - "pallet-asset-rate/std", - "sp-transaction-pool/std", - "sp-statement-store/std", - "pallet-utility/std", - "sp-version/std", - "pallet-society/std", - "pallet-ranked-collective/std", - "pallet-referenda/std", - "pallet-remark/std", - "pallet-root-testing/std", - "pallet-recovery/std", + "pallet-tx-pause/std", "pallet-uniques/std", - "pallet-nfts/std", - "pallet-nfts-runtime-api/std", - "pallet-nft-fractionalization/std", + "pallet-utility/std", "pallet-vesting/std", - "log/std", - "frame-try-runtime?/std", + "pallet-whitelist/std", + "scale-info/std", + "sp-api/std", + "sp-authority-discovery/std", + "sp-block-builder/std", + "sp-consensus-babe/std", + "sp-consensus-grandpa/std", + "sp-core/std", + "sp-inherents/std", "sp-io/std", - "pallet-child-bounties/std", - "pallet-alliance/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-staking/std", + "sp-statement-store/std", + "sp-std/std", + "sp-storage/std", + "sp-transaction-pool/std", + "sp-version/std", "substrate-wasm-builder", ] runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", "frame-benchmarking-pallet-pov/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-election-provider-support/runtime-benchmarks", "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "pallet-alliance/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", + "pallet-asset-rate/runtime-benchmarks", + "pallet-asset-tx-payment/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-babe/runtime-benchmarks", "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-bounties/runtime-benchmarks", + "pallet-broker/runtime-benchmarks", "pallet-child-bounties/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-contracts/runtime-benchmarks", @@ -259,7 +271,7 @@ runtime-benchmarks = [ "pallet-election-provider-support-benchmarking/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-fast-unstake/runtime-benchmarks", - "pallet-nis/runtime-benchmarks", + "pallet-glutton/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", @@ -269,17 +281,22 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-mmr/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", + "pallet-nft-fractionalization/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", + "pallet-nis/runtime-benchmarks", "pallet-nomination-pools-benchmarking/runtime-benchmarks", + "pallet-nomination-pools/runtime-benchmarks", "pallet-offences-benchmarking/runtime-benchmarks", - "pallet-glutton/runtime-benchmarks", + "pallet-offences/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks", "pallet-ranked-collective/runtime-benchmarks", - "pallet-referenda/runtime-benchmarks", "pallet-recovery/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", "pallet-remark/runtime-benchmarks", + "pallet-safe-mode/runtime-benchmarks", "pallet-salary/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", "pallet-session-benchmarking/runtime-benchmarks", "pallet-society/runtime-benchmarks", "pallet-staking/runtime-benchmarks", @@ -289,28 +306,26 @@ runtime-benchmarks = [ "pallet-tips/runtime-benchmarks", "pallet-transaction-storage/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", - "pallet-asset-rate/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", + "pallet-tx-pause/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", - "pallet-nfts/runtime-benchmarks", - "pallet-nft-fractionalization/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", "pallet-whitelist/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-election-provider-support/runtime-benchmarks", - "pallet-asset-tx-payment/runtime-benchmarks", - "pallet-nomination-pools/runtime-benchmarks", - "pallet-offences/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "frame-try-runtime/try-runtime", "frame-benchmarking-pallet-pov/try-runtime", + "frame-election-provider-support/try-runtime", "frame-executive/try-runtime", - "frame-system/try-runtime", "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", "pallet-alliance/try-runtime", + "pallet-asset-conversion-tx-payment/try-runtime", "pallet-asset-conversion/try-runtime", + "pallet-asset-rate/try-runtime", + "pallet-asset-tx-payment/try-runtime", "pallet-assets/try-runtime", "pallet-authority-discovery/try-runtime", "pallet-authorship/try-runtime", @@ -318,6 +333,7 @@ try-runtime = [ "pallet-bags-list/try-runtime", "pallet-balances/try-runtime", "pallet-bounties/try-runtime", + "pallet-broker/try-runtime", "pallet-child-bounties/try-runtime", "pallet-collective/try-runtime", "pallet-contracts/try-runtime", @@ -327,50 +343,47 @@ try-runtime = [ "pallet-election-provider-multi-phase/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-fast-unstake/try-runtime", - "pallet-nis/try-runtime", + "pallet-glutton/try-runtime", "pallet-grandpa/try-runtime", + "pallet-identity/try-runtime", "pallet-im-online/try-runtime", "pallet-indices/try-runtime", - "pallet-identity/try-runtime", + "pallet-insecure-randomness-collective-flip/try-runtime", "pallet-lottery/try-runtime", "pallet-membership/try-runtime", "pallet-message-queue/try-runtime", "pallet-mmr/try-runtime", "pallet-multisig/try-runtime", + "pallet-nft-fractionalization/try-runtime", + "pallet-nfts/try-runtime", + "pallet-nis/try-runtime", "pallet-nomination-pools/try-runtime", "pallet-offences/try-runtime", - "pallet-glutton/try-runtime", "pallet-preimage/try-runtime", "pallet-proxy/try-runtime", - "pallet-insecure-randomness-collective-flip/try-runtime", "pallet-ranked-collective/try-runtime", "pallet-recovery/try-runtime", "pallet-referenda/try-runtime", "pallet-remark/try-runtime", "pallet-root-testing/try-runtime", + "pallet-safe-mode/try-runtime", "pallet-salary/try-runtime", + "pallet-scheduler/try-runtime", "pallet-session/try-runtime", + "pallet-society/try-runtime", "pallet-staking/try-runtime", "pallet-state-trie-migration/try-runtime", "pallet-statement/try-runtime", - "pallet-scheduler/try-runtime", - "pallet-society/try-runtime", "pallet-sudo/try-runtime", "pallet-timestamp/try-runtime", "pallet-tips/try-runtime", - "pallet-treasury/try-runtime", - "pallet-asset-rate/try-runtime", - "pallet-utility/try-runtime", "pallet-transaction-payment/try-runtime", - "pallet-asset-conversion-tx-payment/try-runtime", - "pallet-asset-tx-payment/try-runtime", "pallet-transaction-storage/try-runtime", + "pallet-treasury/try-runtime", + "pallet-tx-pause/try-runtime", "pallet-uniques/try-runtime", - "pallet-nfts/try-runtime", - "pallet-nft-fractionalization/try-runtime", + "pallet-utility/try-runtime", "pallet-vesting/try-runtime", "pallet-whitelist/try-runtime", - "frame-election-provider-support/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] -unsafe-debug = ["pallet-contracts/unsafe-debug"] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 4e1b6d4e8bec0..4f34e4ecd8122 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -35,11 +35,11 @@ use frame_support::{ pallet_prelude::Get, parameter_types, traits::{ - fungible::ItemOf, + fungible::{Balanced, Credit, ItemOf}, tokens::{nonfungibles_v2::Inspect, GetSalary, PayFromAccount}, - AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Currency, EitherOfDiverse, - EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, - LockIdentifier, Nothing, OnUnbalanced, WithdrawReasons, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Contains, Currency, + EitherOfDiverse, EqualPrivilegeOnly, Imbalance, InsideBoth, InstanceFilter, + KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, WithdrawReasons, }, weights::{ constants::{ @@ -47,7 +47,7 @@ use frame_support::{ }, ConstantMultiplier, IdentityFee, Weight, }, - BoundedVec, PalletId, RuntimeDebug, + BoundedVec, PalletId, }; use frame_system::{ limits::{BlockLength, BlockWeights}, @@ -56,6 +56,7 @@ use frame_system::{ pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Moment, Nonce}; use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter}; +use pallet_broker::{CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600}; use pallet_election_provider_multi_phase::SolutionAccuracyOf; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_nfts::PalletFeatures; @@ -63,6 +64,7 @@ use pallet_nis::WithMaximumOf; use pallet_session::historical as pallet_session_historical; pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; +use pallet_tx_pause::RuntimeCallNameOf; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_grandpa::AuthorityId as GrandpaId; @@ -78,6 +80,7 @@ use sp_runtime::{ }, transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perbill, Percent, Permill, Perquintill, + RuntimeDebug, }; use sp_std::prelude::*; #[cfg(any(feature = "std", test))] @@ -218,8 +221,67 @@ parameter_types! { const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct()); +/// Calls that can bypass the safe-mode pallet. +pub struct SafeModeWhitelistedCalls; +impl Contains for SafeModeWhitelistedCalls { + fn contains(call: &RuntimeCall) -> bool { + match call { + RuntimeCall::System(_) | RuntimeCall::SafeMode(_) | RuntimeCall::TxPause(_) => true, + _ => false, + } + } +} + +/// Calls that cannot be paused by the tx-pause pallet. +pub struct TxPauseWhitelistedCalls; +/// Whitelist `Balances::transfer_keep_alive`, all others are pauseable. +impl Contains> for TxPauseWhitelistedCalls { + fn contains(full_name: &RuntimeCallNameOf) -> bool { + match (full_name.0.as_slice(), full_name.1.as_slice()) { + (b"Balances", b"transfer_keep_alive") => true, + _ => false, + } + } +} + +impl pallet_tx_pause::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureRoot; + type UnpauseOrigin = EnsureRoot; + type WhitelistedCalls = TxPauseWhitelistedCalls; + type MaxNameLen = ConstU32<256>; + type WeightInfo = pallet_tx_pause::weights::SubstrateWeight; +} + +parameter_types! { + pub const EnterDuration: BlockNumber = 4 * HOURS; + pub const EnterDepositAmount: Balance = 2_000_000 * DOLLARS; + pub const ExtendDuration: BlockNumber = 2 * HOURS; + pub const ExtendDepositAmount: Balance = 1_000_000 * DOLLARS; + pub const ReleaseDelay: u32 = 2 * DAYS; +} + +impl pallet_safe_mode::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; + type WhitelistedCalls = SafeModeWhitelistedCalls; + type EnterDuration = EnterDuration; + type EnterDepositAmount = EnterDepositAmount; + type ExtendDuration = ExtendDuration; + type ExtendDepositAmount = ExtendDepositAmount; + type ForceEnterOrigin = EnsureRootWithSuccess>; + type ForceExtendOrigin = EnsureRootWithSuccess>; + type ForceExitOrigin = EnsureRoot; + type ForceDepositOrigin = EnsureRoot; + type ReleaseDelay = ReleaseDelay; + type Notify = (); + type WeightInfo = pallet_safe_mode::weights::SubstrateWeight; +} + impl frame_system::Config for Runtime { - type BaseCallFilter = Everything; + type BaseCallFilter = InsideBoth; type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; type DbWeight = RocksDbWeight; @@ -1263,8 +1325,8 @@ impl pallet_contracts::Config for Runtime { type Migrations = pallet_contracts::migration::codegen::BenchMigrations; type MaxDelegateDependencies = ConstU32<32>; type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; - #[cfg(feature = "unsafe-debug")] type Debug = (); + type Environment = (); } impl pallet_sudo::Config for Runtime { @@ -1680,8 +1742,8 @@ impl pallet_core_fellowship::Config for Runtime { type Balance = Balance; type ParamsOrigin = frame_system::EnsureRoot; type InductOrigin = pallet_core_fellowship::EnsureInducted; - type ApproveOrigin = frame_system::EnsureRootWithSuccess>; - type PromoteOrigin = frame_system::EnsureRootWithSuccess>; + type ApproveOrigin = EnsureRootWithSuccess>; + type PromoteOrigin = EnsureRootWithSuccess>; type EvidenceSize = ConstU32<16_384>; } @@ -1876,6 +1938,77 @@ impl pallet_statement::Config for Runtime { type MaxAllowedBytes = MaxAllowedBytes; } +parameter_types! { + pub const BrokerPalletId: PalletId = PalletId(*b"py/broke"); +} + +pub struct IntoAuthor; +impl OnUnbalanced> for IntoAuthor { + fn on_nonzero_unbalanced(credit: Credit) { + if let Some(author) = Authorship::author() { + let _ = >::resolve(&author, credit); + } + } +} + +parameter_types! { + pub storage CoreCount: Option = None; + pub storage CoretimeRevenue: Option<(BlockNumber, Balance)> = None; +} + +pub struct CoretimeProvider; +impl CoretimeInterface for CoretimeProvider { + type AccountId = AccountId; + type Balance = Balance; + type BlockNumber = BlockNumber; + fn latest() -> Self::BlockNumber { + System::block_number() + } + fn request_core_count(_count: CoreIndex) {} + fn request_revenue_info_at(_when: Self::BlockNumber) {} + fn credit_account(_who: Self::AccountId, _amount: Self::Balance) {} + fn assign_core( + _core: CoreIndex, + _begin: Self::BlockNumber, + _assignment: Vec<(CoreAssignment, PartsOf57600)>, + _end_hint: Option, + ) { + } + fn check_notify_core_count() -> Option { + let count = CoreCount::get(); + CoreCount::set(&None); + count + } + fn check_notify_revenue_info() -> Option<(Self::BlockNumber, Self::Balance)> { + let revenue = CoretimeRevenue::get(); + CoretimeRevenue::set(&None); + revenue + } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_core_count(count: u16) { + CoreCount::set(&Some(count)); + } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_revenue_info(when: Self::BlockNumber, revenue: Self::Balance) { + CoretimeRevenue::set(&Some((when, revenue))); + } +} + +impl pallet_broker::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type OnRevenue = IntoAuthor; + type TimeslicePeriod = ConstU32<2>; + type MaxLeasedCores = ConstU32<5>; + type MaxReservedCores = ConstU32<5>; + type Coretime = CoretimeProvider; + type ConvertBalance = traits::Identity; + type WeightInfo = (); + type PalletId = BrokerPalletId; + type AdminOrigin = EnsureRoot; + type PriceAdapter = pallet_broker::Linear; +} + construct_runtime!( pub struct Runtime { @@ -1948,7 +2081,10 @@ construct_runtime!( FastUnstake: pallet_fast_unstake, MessageQueue: pallet_message_queue, Pov: frame_benchmarking_pallet_pov, + TxPause: pallet_tx_pause, + SafeMode: pallet_safe_mode, Statement: pallet_statement, + Broker: pallet_broker, } ); @@ -2029,6 +2165,7 @@ mod benches { [pallet_bags_list, VoterList] [pallet_balances, Balances] [pallet_bounties, Bounties] + [pallet_broker, Broker] [pallet_child_bounties, ChildBounties] [pallet_collective, Council] [pallet_conviction_voting, ConvictionVoting] @@ -2078,6 +2215,8 @@ mod benches { [pallet_utility, Utility] [pallet_vesting, Vesting] [pallet_whitelist, Whitelist] + [pallet_tx_pause, TxPause] + [pallet_safe_mode, SafeMode] ); } @@ -2569,7 +2708,8 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; + use sp_storage::TrackedStorageKey; // Trying to add benchmarks directly to the Session Pallet caused cyclic dependency // issues. To get around that, we separated the Session benchmarks into its own crate, diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 8063b8ef45708..6e7bcebfc00d1 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -101,6 +101,8 @@ pub fn config_endowed(code: Option<&[u8]>, extra_endowed: Vec) -> Run alliance: Default::default(), alliance_motion: Default::default(), nomination_pools: Default::default(), + safe_mode: Default::default(), + tx_pause: Default::default(), glutton: GluttonConfig { compute: Default::default(), storage: Default::default(), diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 61750766fa3f8..92ddbe59fc562 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -52,5 +52,5 @@ futures-timer = "3.0.1" sp-tracing = { version = "10.0.0", path = "../../primitives/tracing" } [features] -default = ["rocksdb"] -rocksdb = ["sc-client-db/rocksdb"] +default = [ "rocksdb" ] +rocksdb = [ "sc-client-db/rocksdb" ] diff --git a/client/consensus/beefy/src/communication/peers.rs b/client/consensus/beefy/src/communication/peers.rs index 4704b8dcf4576..8f2d5cc90a1d9 100644 --- a/client/consensus/beefy/src/communication/peers.rs +++ b/client/consensus/beefy/src/communication/peers.rs @@ -24,7 +24,7 @@ use std::collections::{HashMap, VecDeque}; /// Report specifying a reputation change for a given peer. #[derive(Debug, PartialEq)] -pub(crate) struct PeerReport { +pub struct PeerReport { pub who: PeerId, pub cost_benefit: ReputationChange, } diff --git a/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs b/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs index 8240dd71104c2..b8d8cd35434c9 100644 --- a/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs +++ b/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs @@ -18,7 +18,7 @@ use codec::DecodeAll; use futures::{channel::oneshot, StreamExt}; -use log::{debug, error, trace}; +use log::{debug, trace}; use sc_client_api::BlockBackend; use sc_network::{ config as netconfig, config::RequestResponseConfig, types::ProtocolName, PeerId, @@ -182,7 +182,9 @@ where } /// Run [`BeefyJustifsRequestHandler`]. - pub async fn run(mut self) { + /// + /// Should never end, returns `Error` otherwise. + pub async fn run(&mut self) -> Error { trace!(target: BEEFY_SYNC_LOG_TARGET, "🥩 Running BeefyJustifsRequestHandler"); while let Ok(request) = self @@ -215,9 +217,6 @@ where }, } } - error!( - target: crate::LOG_TARGET, - "🥩 On-demand requests receiver stream terminated, closing worker." - ); + Error::RequestsReceiverStreamClosed } } diff --git a/client/consensus/beefy/src/communication/request_response/mod.rs b/client/consensus/beefy/src/communication/request_response/mod.rs index 1801512fa5421..4bad3b061c8e9 100644 --- a/client/consensus/beefy/src/communication/request_response/mod.rs +++ b/client/consensus/beefy/src/communication/request_response/mod.rs @@ -75,7 +75,7 @@ pub struct JustificationRequest { } #[derive(Debug, thiserror::Error)] -pub(crate) enum Error { +pub enum Error { #[error(transparent)] Client(#[from] sp_blockchain::Error), @@ -102,4 +102,7 @@ pub(crate) enum Error { #[error("Internal error while getting response.")] ResponseError, + + #[error("On-demand requests receiver stream terminated.")] + RequestsReceiverStreamClosed, } diff --git a/client/consensus/beefy/src/error.rs b/client/consensus/beefy/src/error.rs index 08b9960f41a1a..b4773f940193e 100644 --- a/client/consensus/beefy/src/error.rs +++ b/client/consensus/beefy/src/error.rs @@ -34,8 +34,18 @@ pub enum Error { Signature(String), #[error("Session uninitialized")] UninitSession, - #[error("pallet-beefy was reset, please restart voter")] + #[error("pallet-beefy was reset")] ConsensusReset, + #[error("Block import stream terminated")] + BlockImportStreamTerminated, + #[error("Gossip Engine terminated")] + GossipEngineTerminated, + #[error("Finality proofs gossiping stream terminated")] + FinalityProofGossipStreamTerminated, + #[error("Finality stream terminated")] + FinalityStreamTerminated, + #[error("Votes gossiping stream terminated")] + VotesGossipStreamTerminated, } #[cfg(test)] diff --git a/client/consensus/beefy/src/lib.rs b/client/consensus/beefy/src/lib.rs index da339dae7e1f5..0b3baa007c1ce 100644 --- a/client/consensus/beefy/src/lib.rs +++ b/client/consensus/beefy/src/lib.rs @@ -221,7 +221,7 @@ pub async fn start_beefy_gadget( B: Block, BE: Backend, C: Client + BlockBackend, - P: PayloadProvider, + P: PayloadProvider + Clone, R: ProvideRuntimeApi, R::Api: BeefyApi + MmrApi>, N: GossipNetwork + NetworkRequest + Send + Sync + 'static, @@ -237,7 +237,7 @@ pub async fn start_beefy_gadget( min_block_delta, prometheus_registry, links, - on_demand_justifications_handler, + mut on_demand_justifications_handler, } = beefy_params; let BeefyNetworkParams { @@ -248,83 +248,105 @@ pub async fn start_beefy_gadget( .. } = network_params; - let known_peers = Arc::new(Mutex::new(KnownPeers::new())); - // Default votes filter is to discard everything. - // Validator is updated later with correct starting round and set id. - let (gossip_validator, gossip_report_stream) = - communication::gossip::GossipValidator::new(known_peers.clone()); - let gossip_validator = Arc::new(gossip_validator); - let mut gossip_engine = GossipEngine::new( - network.clone(), - sync.clone(), - gossip_protocol_name, - gossip_validator.clone(), - None, - ); let metrics = register_metrics(prometheus_registry.clone()); - // The `GossipValidator` adds and removes known peers based on valid votes and network events. - let on_demand_justifications = OnDemandJustificationsEngine::new( - network.clone(), - justifications_protocol_name, - known_peers, - prometheus_registry.clone(), - ); - // Subscribe to finality notifications and justifications before waiting for runtime pallet and // reuse the streams, so we don't miss notifications while waiting for pallet to be available. let mut finality_notifications = client.finality_notification_stream().fuse(); - let block_import_justif = links.from_block_import_justif_stream.subscribe(100_000).fuse(); - - // Wait for BEEFY pallet to be active before starting voter. - let persisted_state = - match wait_for_runtime_pallet(&*runtime, &mut gossip_engine, &mut finality_notifications) - .await - .and_then(|(beefy_genesis, best_grandpa)| { - load_or_init_voter_state( - &*backend, - &*runtime, - beefy_genesis, - best_grandpa, - min_block_delta, - ) - }) { + let mut block_import_justif = links.from_block_import_justif_stream.subscribe(100_000).fuse(); + + // We re-create and re-run the worker in this loop in order to quickly reinit and resume after + // select recoverable errors. + loop { + let known_peers = Arc::new(Mutex::new(KnownPeers::new())); + // Default votes filter is to discard everything. + // Validator is updated later with correct starting round and set id. + let (gossip_validator, gossip_report_stream) = + communication::gossip::GossipValidator::new(known_peers.clone()); + let gossip_validator = Arc::new(gossip_validator); + let mut gossip_engine = GossipEngine::new( + network.clone(), + sync.clone(), + gossip_protocol_name.clone(), + gossip_validator.clone(), + None, + ); + + // The `GossipValidator` adds and removes known peers based on valid votes and network + // events. + let on_demand_justifications = OnDemandJustificationsEngine::new( + network.clone(), + justifications_protocol_name.clone(), + known_peers, + prometheus_registry.clone(), + ); + + // Wait for BEEFY pallet to be active before starting voter. + let persisted_state = match wait_for_runtime_pallet( + &*runtime, + &mut gossip_engine, + &mut finality_notifications, + ) + .await + .and_then(|(beefy_genesis, best_grandpa)| { + load_or_init_voter_state( + &*backend, + &*runtime, + beefy_genesis, + best_grandpa, + min_block_delta, + ) + }) { Ok(state) => state, Err(e) => { error!(target: LOG_TARGET, "Error: {:?}. Terminating.", e); return }, }; - // Update the gossip validator with the right starting round and set id. - if let Err(e) = persisted_state - .gossip_filter_config() - .map(|f| gossip_validator.update_filter(f)) - { - error!(target: LOG_TARGET, "Error: {:?}. Terminating.", e); - return - } + // Update the gossip validator with the right starting round and set id. + if let Err(e) = persisted_state + .gossip_filter_config() + .map(|f| gossip_validator.update_filter(f)) + { + error!(target: LOG_TARGET, "Error: {:?}. Terminating.", e); + return + } - let worker = worker::BeefyWorker { - backend, - payload_provider, - runtime, - sync, - key_store: key_store.into(), - gossip_engine, - gossip_validator, - gossip_report_stream, - on_demand_justifications, - links, - metrics, - pending_justifications: BTreeMap::new(), - persisted_state, - }; + let worker = worker::BeefyWorker { + backend: backend.clone(), + payload_provider: payload_provider.clone(), + runtime: runtime.clone(), + sync: sync.clone(), + key_store: key_store.clone().into(), + gossip_engine, + gossip_validator, + gossip_report_stream, + on_demand_justifications, + links: links.clone(), + metrics: metrics.clone(), + pending_justifications: BTreeMap::new(), + persisted_state, + }; - futures::future::select( - Box::pin(worker.run(block_import_justif, finality_notifications)), - Box::pin(on_demand_justifications_handler.run()), - ) - .await; + match futures::future::select( + Box::pin(worker.run(&mut block_import_justif, &mut finality_notifications)), + Box::pin(on_demand_justifications_handler.run()), + ) + .await + { + // On `ConsensusReset` error, just reinit and restart voter. + futures::future::Either::Left((error::Error::ConsensusReset, _)) => { + error!(target: LOG_TARGET, "🥩 Error: {:?}. Restarting voter.", error::Error::ConsensusReset); + continue + }, + // On other errors, bring down / finish the task. + futures::future::Either::Left((worker_err, _)) => + error!(target: LOG_TARGET, "🥩 Error: {:?}. Terminating.", worker_err), + futures::future::Either::Right((odj_handler_err, _)) => + error!(target: LOG_TARGET, "🥩 Error: {:?}. Terminating.", odj_handler_err), + }; + return + } } fn load_or_init_voter_state( diff --git a/client/consensus/beefy/src/worker.rs b/client/consensus/beefy/src/worker.rs index 17a8891b06142..0d3845a270368 100644 --- a/client/consensus/beefy/src/worker.rs +++ b/client/consensus/beefy/src/worker.rs @@ -447,11 +447,7 @@ where .ok() .flatten() .filter(|genesis| *genesis == self.persisted_state.pallet_genesis) - .ok_or_else(|| { - let err = Error::ConsensusReset; - error!(target: LOG_TARGET, "🥩 Error: {}", err); - err - })?; + .ok_or(Error::ConsensusReset)?; if *header.number() > self.best_grandpa_block() { // update best GRANDPA finalized block we have seen @@ -795,11 +791,12 @@ where /// Main loop for BEEFY worker. /// /// Run the main async loop which is driven by finality notifications and gossiped votes. + /// Should never end, returns `Error` otherwise. pub(crate) async fn run( mut self, - mut block_import_justif: Fuse>>, - mut finality_notifications: Fuse>, - ) { + block_import_justif: &mut Fuse>>, + finality_notifications: &mut Fuse>, + ) -> Error { info!( target: LOG_TARGET, "🥩 run BEEFY worker, best grandpa: #{:?}.", @@ -848,17 +845,17 @@ where // Use `select_biased!` to prioritize order below. // Process finality notifications first since these drive the voter. notification = finality_notifications.next() => { - if notification.and_then(|notif| { - self.handle_finality_notification(¬if).ok() - }).is_none() { - error!(target: LOG_TARGET, "🥩 Finality stream terminated, closing worker."); - return; + if let Some(notif) = notification { + if let Err(err) = self.handle_finality_notification(¬if) { + return err; + } + } else { + return Error::FinalityStreamTerminated; } }, // Make sure to pump gossip engine. _ = gossip_engine => { - error!(target: LOG_TARGET, "🥩 Gossip engine has terminated, closing worker."); - return; + return Error::GossipEngineTerminated; }, // Process incoming justifications as these can make some in-flight votes obsolete. response_info = self.on_demand_justifications.next().fuse() => { @@ -881,8 +878,7 @@ where debug!(target: LOG_TARGET, "🥩 {}", err); } } else { - error!(target: LOG_TARGET, "🥩 Block import stream terminated, closing worker."); - return; + return Error::BlockImportStreamTerminated; } }, justif = gossip_proofs.next() => { @@ -892,11 +888,7 @@ where debug!(target: LOG_TARGET, "🥩 {}", err); } } else { - error!( - target: LOG_TARGET, - "🥩 Finality proofs gossiping stream terminated, closing worker." - ); - return; + return Error::FinalityProofGossipStreamTerminated; } }, // Finally process incoming votes. @@ -907,11 +899,7 @@ where debug!(target: LOG_TARGET, "🥩 {}", err); } } else { - error!( - target: LOG_TARGET, - "🥩 Votes gossiping stream terminated, closing worker." - ); - return; + return Error::VotesGossipStreamTerminated; } }, // Process peer reports. diff --git a/client/consensus/grandpa/src/communication/gossip.rs b/client/consensus/grandpa/src/communication/gossip.rs index 5688aff3ea717..3a78b157d5b1b 100644 --- a/client/consensus/grandpa/src/communication/gossip.rs +++ b/client/consensus/grandpa/src/communication/gossip.rs @@ -546,9 +546,7 @@ impl Peers { who: &PeerId, update: NeighborPacket, ) -> Result>, Misbehavior> { - let Some(peer) = self.inner.get_mut(who) else { - return Ok(None) - }; + let Some(peer) = self.inner.get_mut(who) else { return Ok(None) }; let invalid_change = peer.view.set_id > update.set_id || peer.view.round > update.round && peer.view.set_id == update.set_id || diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index c3b891b84e893..1e5db966e66db 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -173,7 +173,7 @@ pub async fn run_manual_seal( SC: SelectChain + 'static, TP: TransactionPool, CIDP: CreateInherentDataProviders, - P: Send + Sync + 'static, + P: codec::Encode + Send + Sync + 'static, { while let Some(command) = commands_stream.next().await { match command { @@ -231,7 +231,7 @@ pub async fn run_instant_seal( SC: SelectChain + 'static, TP: TransactionPool, CIDP: CreateInherentDataProviders, - P: Send + Sync + 'static, + P: codec::Encode + Send + Sync + 'static, { // instant-seal creates blocks as soon as transactions are imported // into the transaction pool. @@ -281,7 +281,7 @@ pub async fn run_instant_seal_and_finalize( SC: SelectChain + 'static, TP: TransactionPool, CIDP: CreateInherentDataProviders, - P: Send + Sync + 'static, + P: codec::Encode + Send + Sync + 'static, { // Creates and finalizes blocks as soon as transactions are imported // into the transaction pool. @@ -459,7 +459,8 @@ mod tests { needs_justification: false, bad_justification: false, is_new_best: true, - } + }, + proof_size: 0 } ); // assert that there's a new block in the db. @@ -549,7 +550,8 @@ mod tests { needs_justification: false, bad_justification: false, is_new_best: true, - } + }, + proof_size: created_block.proof_size } ); // assert that there's a new block in the db. @@ -625,7 +627,8 @@ mod tests { needs_justification: false, bad_justification: false, is_new_best: true, - } + }, + proof_size: 0 } ); // assert that there's a new block in the db. @@ -711,7 +714,8 @@ mod tests { needs_justification: false, bad_justification: false, is_new_best: true - } + }, + proof_size: 0 } ); diff --git a/client/consensus/manual-seal/src/rpc.rs b/client/consensus/manual-seal/src/rpc.rs index 85abcdc08574b..c0b3af69bedf4 100644 --- a/client/consensus/manual-seal/src/rpc.rs +++ b/client/consensus/manual-seal/src/rpc.rs @@ -97,6 +97,8 @@ pub struct CreatedBlock { pub hash: Hash, /// some extra details about the import operation pub aux: ImportedAux, + /// uncompacted storage proof size (zero mean that there is no proof) + pub proof_size: usize, } impl ManualSeal { diff --git a/client/consensus/manual-seal/src/seal_block.rs b/client/consensus/manual-seal/src/seal_block.rs index 4b6230c3efc3d..716e889ec0395 100644 --- a/client/consensus/manual-seal/src/seal_block.rs +++ b/client/consensus/manual-seal/src/seal_block.rs @@ -83,7 +83,7 @@ pub async fn seal_block( TP: TransactionPool, SC: SelectChain, CIDP: CreateInherentDataProviders, - P: Send + Sync + 'static, + P: codec::Encode + Send + Sync + 'static, { let future = async { if pool.status().ready == 0 && !create_empty { @@ -131,6 +131,7 @@ pub async fn seal_block( let (header, body) = proposal.block.deconstruct(); let proof = proposal.proof; + let proof_size = proof.encoded_size(); let mut params = BlockImportParams::new(BlockOrigin::Own, header.clone()); params.body = Some(body); params.finalized = finalize; @@ -149,8 +150,11 @@ pub async fn seal_block( post_header.digest_mut().logs.extend(params.post_digests.iter().cloned()); match block_import.import_block(params).await? { - ImportResult::Imported(aux) => - Ok(CreatedBlock { hash: ::Header::hash(&post_header), aux }), + ImportResult::Imported(aux) => Ok(CreatedBlock { + hash: ::Header::hash(&post_header), + aux, + proof_size, + }), other => Err(other.into()), } }; diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 1845158dac112..e351798a026f7 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -51,9 +51,9 @@ default = [] test-helpers = [] runtime-benchmarks = [ "kitchensink-runtime/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] -rocksdb = ["kvdb-rocksdb"] +rocksdb = [ "kvdb-rocksdb" ] [[bench]] name = "state_access" diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index 6a056ce7dfa34..e7252ef3f19cb 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -55,7 +55,7 @@ name = "bench" harness = false [features] -default = ["std"] +default = [ "std" ] # This crate does not have `no_std` support, we just require this for tests std = [ "sc-runtime-test/std", @@ -63,13 +63,13 @@ std = [ "sp-core/std", "sp-externalities/std", "sp-io/std", - "sp-runtime/std", "sp-runtime-interface/std", + "sp-runtime/std", "sp-state-machine/std", "sp-tracing/std", "sp-trie/std", "sp-version/std", "sp-wasm-interface/std", - "substrate-test-runtime/std" + "substrate-test-runtime/std", ] wasm-extern-trace = [] diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index abf2fb5c27ad5..628297ade6b74 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -23,12 +23,12 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../../primiti substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder", optional = true } [features] -default = ["std"] +default = [ "std" ] std = [ "sp-core/std", "sp-io/std", + "sp-runtime-interface/std", "sp-runtime/std", "sp-std/std", "substrate-wasm-builder", - "sp-runtime-interface/std" ] diff --git a/client/rpc-spec-v2/src/chain_head/api.rs b/client/rpc-spec-v2/src/chain_head/api.rs index c002b75efe037..682cd690dd10c 100644 --- a/client/rpc-spec-v2/src/chain_head/api.rs +++ b/client/rpc-spec-v2/src/chain_head/api.rs @@ -119,4 +119,31 @@ pub trait ChainHeadApi { /// This method is unstable and subject to change in the future. #[method(name = "chainHead_unstable_unpin", blocking)] fn chain_head_unstable_unpin(&self, follow_subscription: String, hash: Hash) -> RpcResult<()>; + + /// Resumes a storage fetch started with `chainHead_storage` after it has generated an + /// `operationWaitingForContinue` event. + /// + /// # Unstable + /// + /// This method is unstable and subject to change in the future. + #[method(name = "chainHead_unstable_continue", blocking)] + fn chain_head_unstable_continue( + &self, + follow_subscription: String, + operation_id: String, + ) -> RpcResult<()>; + + /// Stops an operation started with chainHead_unstable_body, chainHead_unstable_call, or + /// chainHead_unstable_storage. If the operation was still in progress, this interrupts it. If + /// the operation was already finished, this call has no effect. + /// + /// # Unstable + /// + /// This method is unstable and subject to change in the future. + #[method(name = "chainHead_unstable_stopOperation", blocking)] + fn chain_head_unstable_stop_operation( + &self, + follow_subscription: String, + operation_id: String, + ) -> RpcResult<()>; } diff --git a/client/rpc-spec-v2/src/chain_head/chain_head.rs b/client/rpc-spec-v2/src/chain_head/chain_head.rs index 79cf251f18068..bae7c84df0ed9 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head.rs @@ -61,6 +61,9 @@ pub struct ChainHeadConfig { pub subscription_max_pinned_duration: Duration, /// The maximum number of ongoing operations per subscription. pub subscription_max_ongoing_operations: usize, + /// The maximum number of items reported by the `chainHead_storage` before + /// pagination is required. + pub operation_max_storage_items: usize, } /// Maximum pinned blocks across all connections. @@ -78,12 +81,17 @@ const MAX_PINNED_DURATION: Duration = Duration::from_secs(60); /// Note: The lower limit imposed by the spec is 16. const MAX_ONGOING_OPERATIONS: usize = 16; +/// The maximum number of items the `chainHead_storage` can return +/// before paginations is required. +const MAX_STORAGE_ITER_ITEMS: usize = 5; + impl Default for ChainHeadConfig { fn default() -> Self { ChainHeadConfig { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: MAX_PINNED_DURATION, subscription_max_ongoing_operations: MAX_ONGOING_OPERATIONS, + operation_max_storage_items: MAX_STORAGE_ITER_ITEMS, } } } @@ -100,6 +108,9 @@ pub struct ChainHead, Block: BlockT, Client> { subscriptions: Arc>, /// The hexadecimal encoded hash of the genesis block. genesis_hash: String, + /// The maximum number of items reported by the `chainHead_storage` before + /// pagination is required. + operation_max_storage_items: usize, /// Phantom member to pin the block type. _phantom: PhantomData, } @@ -124,6 +135,7 @@ impl, Block: BlockT, Client> ChainHead { config.subscription_max_ongoing_operations, backend, )), + operation_max_storage_items: config.operation_max_storage_items, genesis_hash, _phantom: PhantomData, } @@ -232,7 +244,7 @@ where follow_subscription: String, hash: Block::Hash, ) -> RpcResult { - let block_guard = match self.subscriptions.lock_block(&follow_subscription, hash, 1) { + let mut block_guard = match self.subscriptions.lock_block(&follow_subscription, hash, 1) { Ok(block) => block, Err(SubscriptionManagementError::SubscriptionAbsent) | Err(SubscriptionManagementError::ExceededLimits) => return Ok(MethodResponse::LimitReached), @@ -243,6 +255,8 @@ where Err(_) => return Err(ChainHeadRpcError::InvalidBlock.into()), }; + let operation_id = block_guard.operation().operation_id(); + let event = match self.client.block(hash) { Ok(Some(signed_block)) => { let extrinsics = signed_block @@ -252,7 +266,7 @@ where .map(|extrinsic| hex_string(&extrinsic.encode())) .collect(); FollowEvent::::OperationBodyDone(OperationBodyDone { - operation_id: block_guard.operation_id(), + operation_id: operation_id.clone(), value: extrinsics, }) }, @@ -268,16 +282,13 @@ where return Err(ChainHeadRpcError::InvalidBlock.into()) }, Err(error) => FollowEvent::::OperationError(OperationError { - operation_id: block_guard.operation_id(), + operation_id: operation_id.clone(), error: error.to_string(), }), }; let _ = block_guard.response_sender().unbounded_send(event); - Ok(MethodResponse::Started(MethodResponseStarted { - operation_id: block_guard.operation_id(), - discarded_items: None, - })) + Ok(MethodResponse::Started(MethodResponseStarted { operation_id, discarded_items: None })) } fn chain_head_unstable_header( @@ -337,7 +348,7 @@ where .transpose()? .map(ChildInfo::new_default_from_vec); - let block_guard = + let mut block_guard = match self.subscriptions.lock_block(&follow_subscription, hash, items.len()) { Ok(block) => block, Err(SubscriptionManagementError::SubscriptionAbsent) | @@ -349,17 +360,21 @@ where Err(_) => return Err(ChainHeadRpcError::InvalidBlock.into()), }; - let storage_client = ChainHeadStorage::::new(self.client.clone()); - let operation_id = block_guard.operation_id(); + let mut storage_client = ChainHeadStorage::::new( + self.client.clone(), + self.operation_max_storage_items, + ); + let operation = block_guard.operation(); + let operation_id = operation.operation_id(); // The number of operations we are allowed to execute. - let num_operations = block_guard.num_reserved(); + let num_operations = operation.num_reserved(); let discarded = items.len().saturating_sub(num_operations); let mut items = items; items.truncate(num_operations); let fut = async move { - storage_client.generate_events(block_guard, hash, items, child_trie); + storage_client.generate_events(block_guard, hash, items, child_trie).await; }; self.executor @@ -379,7 +394,7 @@ where ) -> RpcResult { let call_parameters = Bytes::from(parse_hex_param(call_parameters)?); - let block_guard = match self.subscriptions.lock_block(&follow_subscription, hash, 1) { + let mut block_guard = match self.subscriptions.lock_block(&follow_subscription, hash, 1) { Ok(block) => block, Err(SubscriptionManagementError::SubscriptionAbsent) | Err(SubscriptionManagementError::ExceededLimits) => { @@ -401,28 +416,26 @@ where .into()) } + let operation_id = block_guard.operation().operation_id(); let event = self .client .executor() .call(hash, &function, &call_parameters, CallContext::Offchain) .map(|result| { FollowEvent::::OperationCallDone(OperationCallDone { - operation_id: block_guard.operation_id(), + operation_id: operation_id.clone(), output: hex_string(&result), }) }) .unwrap_or_else(|error| { FollowEvent::::OperationError(OperationError { - operation_id: block_guard.operation_id(), + operation_id: operation_id.clone(), error: error.to_string(), }) }); let _ = block_guard.response_sender().unbounded_send(event); - Ok(MethodResponse::Started(MethodResponseStarted { - operation_id: block_guard.operation_id(), - discarded_items: None, - })) + Ok(MethodResponse::Started(MethodResponseStarted { operation_id, discarded_items: None })) } fn chain_head_unstable_unpin( @@ -443,4 +456,35 @@ where Err(_) => Err(ChainHeadRpcError::InvalidBlock.into()), } } + + fn chain_head_unstable_continue( + &self, + follow_subscription: String, + operation_id: String, + ) -> RpcResult<()> { + let Some(operation) = self.subscriptions.get_operation(&follow_subscription, &operation_id) else { + return Ok(()) + }; + + if !operation.submit_continue() { + // Continue called without generating a `WaitingForContinue` event. + Err(ChainHeadRpcError::InvalidContinue.into()) + } else { + Ok(()) + } + } + + fn chain_head_unstable_stop_operation( + &self, + follow_subscription: String, + operation_id: String, + ) -> RpcResult<()> { + let Some(operation) = self.subscriptions.get_operation(&follow_subscription, &operation_id) else { + return Ok(()) + }; + + operation.stop_operation(); + + Ok(()) + } } diff --git a/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs b/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs index 393e4489c8c07..5e1f38f9a9978 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs @@ -18,7 +18,7 @@ //! Implementation of the `chainHead_storage` method. -use std::{marker::PhantomData, sync::Arc}; +use std::{collections::VecDeque, marker::PhantomData, sync::Arc}; use sc_client_api::{Backend, ChildInfo, StorageKey, StorageProvider}; use sc_utils::mpsc::TracingUnboundedSender; @@ -37,10 +37,6 @@ use super::{ FollowEvent, }; -/// The maximum number of items the `chainHead_storage` can return -/// before paginations is required. -const MAX_ITER_ITEMS: usize = 10; - /// The query type of an interation. enum IterQueryType { /// Iterating over (key, value) pairs. @@ -53,16 +49,34 @@ enum IterQueryType { pub struct ChainHeadStorage { /// Substrate client. client: Arc, - _phantom: PhantomData<(Block, BE)>, + /// Queue of operations that may require pagination. + iter_operations: VecDeque, + /// The maximum number of items reported by the `chainHead_storage` before + /// pagination is required. + operation_max_storage_items: usize, + _phandom: PhantomData<(BE, Block)>, } impl ChainHeadStorage { /// Constructs a new [`ChainHeadStorage`]. - pub fn new(client: Arc) -> Self { - Self { client, _phantom: PhantomData } + pub fn new(client: Arc, operation_max_storage_items: usize) -> Self { + Self { + client, + iter_operations: VecDeque::new(), + operation_max_storage_items, + _phandom: PhantomData, + } } } +/// Query to iterate over storage. +struct QueryIter { + /// The next key from which the iteration should continue. + next_key: StorageKey, + /// The type of the query (either value or hash). + ty: IterQueryType, +} + /// Checks if the provided key (main or child key) is valid /// for queries. /// @@ -77,7 +91,7 @@ fn is_key_queryable(key: &[u8]) -> bool { type QueryResult = Result, String>; /// The result of iterating over keys. -type QueryIterResult = Result, String>; +type QueryIterResult = Result<(Vec, Option), String>; impl ChainHeadStorage where @@ -131,64 +145,118 @@ where .unwrap_or_else(|error| QueryResult::Err(error.to_string())) } - /// Handle iterating over (key, value) or (key, hash) pairs. - fn query_storage_iter( + /// Iterate over at most `operation_max_storage_items` keys. + /// + /// Returns the storage result with a potential next key to resume iteration. + fn query_storage_iter_pagination( &self, + query: QueryIter, hash: Block::Hash, - key: &StorageKey, child_key: Option<&ChildInfo>, - ty: IterQueryType, ) -> QueryIterResult { - let keys_iter = if let Some(child_key) = child_key { - self.client.child_storage_keys(hash, child_key.to_owned(), Some(key), None) + let QueryIter { next_key, ty } = query; + + let mut keys_iter = if let Some(child_key) = child_key { + self.client + .child_storage_keys(hash, child_key.to_owned(), Some(&next_key), None) } else { - self.client.storage_keys(hash, Some(key), None) + self.client.storage_keys(hash, Some(&next_key), None) } - .map_err(|error| error.to_string())?; + .map_err(|err| err.to_string())?; + + let mut ret = Vec::with_capacity(self.operation_max_storage_items); + for _ in 0..self.operation_max_storage_items { + let Some(key) = keys_iter.next() else { + break + }; - let mut ret = Vec::with_capacity(MAX_ITER_ITEMS); - let mut keys_iter = keys_iter.take(MAX_ITER_ITEMS); - while let Some(key) = keys_iter.next() { let result = match ty { IterQueryType::Value => self.query_storage_value(hash, &key, child_key), IterQueryType::Hash => self.query_storage_hash(hash, &key, child_key), }?; - if let Some(result) = result { - ret.push(result); + if let Some(value) = result { + ret.push(value); } } - QueryIterResult::Ok(ret) + // Save the next key if any to continue the iteration. + let maybe_next_query = keys_iter.next().map(|next_key| QueryIter { next_key, ty }); + Ok((ret, maybe_next_query)) } - /// Generate the block events for the `chainHead_storage` method. - pub fn generate_events( - &self, - block_guard: BlockGuard, + /// Iterate over (key, hash) and (key, value) generating the `WaitingForContinue` event if + /// necessary. + async fn generate_storage_iter_events( + &mut self, + mut block_guard: BlockGuard, hash: Block::Hash, - items: Vec>, child_key: Option, ) { - /// Build and send the opaque error back to the `chainHead_follow` method. - fn send_error( - sender: &TracingUnboundedSender>, - operation_id: String, - error: String, - ) { - let _ = - sender.unbounded_send(FollowEvent::::OperationError(OperationError { - operation_id, - error, - })); + let sender = block_guard.response_sender(); + let operation = block_guard.operation(); + + while let Some(query) = self.iter_operations.pop_front() { + if operation.was_stopped() { + return + } + + let result = self.query_storage_iter_pagination(query, hash, child_key.as_ref()); + let (events, maybe_next_query) = match result { + QueryIterResult::Ok(result) => result, + QueryIterResult::Err(error) => { + send_error::(&sender, operation.operation_id(), error.to_string()); + return + }, + }; + + if !events.is_empty() { + // Send back the results of the iteration produced so far. + let _ = sender.unbounded_send(FollowEvent::::OperationStorageItems( + OperationStorageItems { operation_id: operation.operation_id(), items: events }, + )); + } + + if let Some(next_query) = maybe_next_query { + let _ = + sender.unbounded_send(FollowEvent::::OperationWaitingForContinue( + OperationId { operation_id: operation.operation_id() }, + )); + + // The operation might be continued or cancelled only after the + // `OperationWaitingForContinue` is generated above. + operation.wait_for_continue().await; + + // Give a chance for the other items to advance next time. + self.iter_operations.push_back(next_query); + } + } + + if operation.was_stopped() { + return } + let _ = + sender.unbounded_send(FollowEvent::::OperationStorageDone(OperationId { + operation_id: operation.operation_id(), + })); + } + + /// Generate the block events for the `chainHead_storage` method. + pub async fn generate_events( + &mut self, + mut block_guard: BlockGuard, + hash: Block::Hash, + items: Vec>, + child_key: Option, + ) { let sender = block_guard.response_sender(); + let operation = block_guard.operation(); if let Some(child_key) = child_key.as_ref() { if !is_key_queryable(child_key.storage_key()) { let _ = sender.unbounded_send(FollowEvent::::OperationStorageDone( - OperationId { operation_id: block_guard.operation_id() }, + OperationId { operation_id: operation.operation_id() }, )); return } @@ -206,7 +274,7 @@ where Ok(Some(value)) => storage_results.push(value), Ok(None) => continue, Err(error) => { - send_error::(&sender, block_guard.operation_id(), error); + send_error::(&sender, operation.operation_id(), error); return }, } @@ -216,34 +284,16 @@ where Ok(Some(value)) => storage_results.push(value), Ok(None) => continue, Err(error) => { - send_error::(&sender, block_guard.operation_id(), error); + send_error::(&sender, operation.operation_id(), error); return }, }, - StorageQueryType::DescendantsValues => match self.query_storage_iter( - hash, - &item.key, - child_key.as_ref(), - IterQueryType::Value, - ) { - Ok(values) => storage_results.extend(values), - Err(error) => { - send_error::(&sender, block_guard.operation_id(), error); - return - }, - }, - StorageQueryType::DescendantsHashes => match self.query_storage_iter( - hash, - &item.key, - child_key.as_ref(), - IterQueryType::Hash, - ) { - Ok(values) => storage_results.extend(values), - Err(error) => { - send_error::(&sender, block_guard.operation_id(), error); - return - }, - }, + StorageQueryType::DescendantsValues => self + .iter_operations + .push_back(QueryIter { next_key: item.key, ty: IterQueryType::Value }), + StorageQueryType::DescendantsHashes => self + .iter_operations + .push_back(QueryIter { next_key: item.key, ty: IterQueryType::Hash }), _ => continue, }; } @@ -251,15 +301,24 @@ where if !storage_results.is_empty() { let _ = sender.unbounded_send(FollowEvent::::OperationStorageItems( OperationStorageItems { - operation_id: block_guard.operation_id(), + operation_id: operation.operation_id(), items: storage_results, }, )); } - let _ = - sender.unbounded_send(FollowEvent::::OperationStorageDone(OperationId { - operation_id: block_guard.operation_id(), - })); + self.generate_storage_iter_events(block_guard, hash, child_key).await } } + +/// Build and send the opaque error back to the `chainHead_follow` method. +fn send_error( + sender: &TracingUnboundedSender>, + operation_id: String, + error: String, +) { + let _ = sender.unbounded_send(FollowEvent::::OperationError(OperationError { + operation_id, + error, + })); +} diff --git a/client/rpc-spec-v2/src/chain_head/subscription/inner.rs b/client/rpc-spec-v2/src/chain_head/subscription/inner.rs index 9f42be4a2f7f6..d6f64acd63f5f 100644 --- a/client/rpc-spec-v2/src/chain_head/subscription/inner.rs +++ b/client/rpc-spec-v2/src/chain_head/subscription/inner.rs @@ -17,12 +17,13 @@ // along with this program. If not, see . use futures::channel::oneshot; +use parking_lot::Mutex; use sc_client_api::Backend; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_runtime::traits::Block as BlockT; use std::{ collections::{hash_map::Entry, HashMap}, - sync::Arc, + sync::{atomic::AtomicBool, Arc}, time::{Duration, Instant}, }; @@ -154,12 +155,184 @@ struct PermitOperations { _permit: tokio::sync::OwnedSemaphorePermit, } -impl PermitOperations { +/// The state of one operation. +/// +/// This is directly exposed to users via `chain_head_unstable_continue` and +/// `chain_head_unstable_stop_operation`. +#[derive(Clone)] +pub struct OperationState { + /// The shared operation state that holds information about the + /// `waitingForContinue` event and cancellation. + shared_state: Arc, + /// Send notifications when the user calls `chainHead_continue` method. + send_continue: tokio::sync::mpsc::Sender<()>, +} + +impl OperationState { + /// Returns true if `chainHead_continue` is called after the + /// `waitingForContinue` event was emitted for the associated + /// operation ID. + pub fn submit_continue(&self) -> bool { + // `waitingForContinue` not generated. + if !self.shared_state.requested_continue.load(std::sync::atomic::Ordering::Acquire) { + return false + } + + // Has enough capacity for 1 message. + // Can fail if the `stop_operation` propagated the stop first. + self.send_continue.try_send(()).is_ok() + } + + /// Stops the operation if `waitingForContinue` event was emitted for the associated + /// operation ID. + /// + /// Returns nothing in accordance with `chainHead_unstable_stopOperation`. + pub fn stop_operation(&self) { + // `waitingForContinue` not generated. + if !self.shared_state.requested_continue.load(std::sync::atomic::Ordering::Acquire) { + return + } + + self.shared_state + .operation_stopped + .store(true, std::sync::atomic::Ordering::Release); + + // Send might not have enough capacity if `submit_continue` was sent first. + // However, the `operation_stopped` boolean was set. + let _ = self.send_continue.try_send(()); + } +} + +/// The shared operation state between the backend [`RegisteredOperation`] and frontend +/// [`RegisteredOperation`]. +struct SharedOperationState { + /// True if the `chainHead` generated `waitingForContinue` event. + requested_continue: AtomicBool, + /// True if the operation was cancelled by the user. + operation_stopped: AtomicBool, +} + +impl SharedOperationState { + /// Constructs a new [`SharedOperationState`]. + /// + /// This is efficiently cloned under a single heap allocation. + fn new() -> Arc { + Arc::new(SharedOperationState { + requested_continue: AtomicBool::new(false), + operation_stopped: AtomicBool::new(false), + }) + } +} + +/// The registered operation passed to the `chainHead` methods. +/// +/// This is used internally by the `chainHead` methods. +pub struct RegisteredOperation { + /// The shared operation state that holds information about the + /// `waitingForContinue` event and cancellation. + shared_state: Arc, + /// Receive notifications when the user calls `chainHead_continue` method. + recv_continue: tokio::sync::mpsc::Receiver<()>, + /// The operation ID of the request. + operation_id: String, + /// Track the operations ID of this subscription. + operations: Arc>>, + /// Permit a number of items to be executed by this operation. + permit: PermitOperations, +} + +impl RegisteredOperation { + /// Wait until the user calls `chainHead_continue` or the operation + /// is cancelled via `chainHead_stopOperation`. + pub async fn wait_for_continue(&mut self) { + self.shared_state + .requested_continue + .store(true, std::sync::atomic::Ordering::Release); + + // The sender part of this channel is around for as long as this object exists, + // because it is stored in the `OperationState` of the `operations` field. + // The sender part is removed from tracking when this object is dropped. + let _ = self.recv_continue.recv().await; + + self.shared_state + .requested_continue + .store(false, std::sync::atomic::Ordering::Release); + } + + /// Returns true if the current operation was stopped. + pub fn was_stopped(&self) -> bool { + self.shared_state.operation_stopped.load(std::sync::atomic::Ordering::Acquire) + } + + /// Get the operation ID. + pub fn operation_id(&self) -> String { + self.operation_id.clone() + } + /// Returns the number of reserved elements for this permit. /// /// This can be smaller than the number of items requested via [`LimitOperations::reserve()`]. - fn num_reserved(&self) -> usize { - self.num_ops + pub fn num_reserved(&self) -> usize { + self.permit.num_ops + } +} + +impl Drop for RegisteredOperation { + fn drop(&mut self) { + let mut operations = self.operations.lock(); + operations.remove(&self.operation_id); + } +} + +/// The ongoing operations of a subscription. +struct Operations { + /// The next operation ID to be generated. + next_operation_id: usize, + /// Limit the number of ongoing operations. + limits: LimitOperations, + /// Track the operations ID of this subscription. + operations: Arc>>, +} + +impl Operations { + /// Constructs a new [`Operations`]. + fn new(max_operations: usize) -> Self { + Operations { + next_operation_id: 0, + limits: LimitOperations::new(max_operations), + operations: Default::default(), + } + } + + /// Register a new operation. + pub fn register_operation(&mut self, to_reserve: usize) -> Option { + let permit = self.limits.reserve_at_most(to_reserve)?; + + let operation_id = self.next_operation_id(); + + // At most one message can be sent. + let (send_continue, recv_continue) = tokio::sync::mpsc::channel(1); + let shared_state = SharedOperationState::new(); + + let state = OperationState { send_continue, shared_state: shared_state.clone() }; + + // Cloned operations for removing the current ID on drop. + let operations = self.operations.clone(); + operations.lock().insert(operation_id.clone(), state); + + Some(RegisteredOperation { shared_state, operation_id, recv_continue, operations, permit }) + } + + /// Get the associated operation state with the ID. + pub fn get_operation(&self, id: &str) -> Option { + self.operations.lock().get(id).map(|state| state.clone()) + } + + /// Generate the next operation ID for this subscription. + fn next_operation_id(&mut self) -> String { + let op_id = self.next_operation_id; + self.next_operation_id += 1; + op_id.to_string() } } @@ -180,10 +353,8 @@ struct SubscriptionState { /// /// This object is cloned between methods. response_sender: TracingUnboundedSender>, - /// Limit the number of ongoing operations. - limits: LimitOperations, - /// The next operation ID. - next_operation_id: usize, + /// The ongoing operations of a subscription. + operations: Operations, /// Track the block hashes available for this subscription. /// /// This implementation assumes: @@ -296,18 +467,16 @@ impl SubscriptionState { timestamp } - /// Generate the next operation ID for this subscription. - fn next_operation_id(&mut self) -> usize { - let op_id = self.next_operation_id; - self.next_operation_id = self.next_operation_id.wrapping_add(1); - op_id + /// Register a new operation. + /// + /// The registered operation can execute at least one item and at most the requested items. + fn register_operation(&mut self, to_reserve: usize) -> Option { + self.operations.register_operation(to_reserve) } - /// Reserves capacity to execute at least one operation and at most the requested items. - /// - /// For more details see [`PermitOperations`]. - fn reserve_at_most(&self, to_reserve: usize) -> Option { - self.limits.reserve_at_most(to_reserve) + /// Get the associated operation state with the ID. + pub fn get_operation(&self, id: &str) -> Option { + self.operations.get_operation(id) } } @@ -318,8 +487,7 @@ pub struct BlockGuard> { hash: Block::Hash, with_runtime: bool, response_sender: TracingUnboundedSender>, - operation_id: String, - permit_operations: PermitOperations, + operation: RegisteredOperation, backend: Arc, } @@ -337,22 +505,14 @@ impl> BlockGuard { hash: Block::Hash, with_runtime: bool, response_sender: TracingUnboundedSender>, - operation_id: usize, - permit_operations: PermitOperations, + operation: RegisteredOperation, backend: Arc, ) -> Result { backend .pin_block(hash) .map_err(|err| SubscriptionManagementError::Custom(err.to_string()))?; - Ok(Self { - hash, - with_runtime, - response_sender, - operation_id: operation_id.to_string(), - permit_operations, - backend, - }) + Ok(Self { hash, with_runtime, response_sender, operation, backend }) } /// The `with_runtime` flag of the subscription. @@ -365,16 +525,9 @@ impl> BlockGuard { self.response_sender.clone() } - /// The operation ID of this method. - pub fn operation_id(&self) -> String { - self.operation_id.clone() - } - - /// Returns the number of reserved elements for this permit. - /// - /// This can be smaller than the number of items requested. - pub fn num_reserved(&self) -> usize { - self.permit_operations.num_reserved() + /// Get the details of the registered operation. + pub fn operation(&mut self) -> &mut RegisteredOperation { + &mut self.operation } } @@ -445,9 +598,8 @@ impl> SubscriptionsInner { with_runtime, tx_stop: Some(tx_stop), response_sender, - limits: LimitOperations::new(self.max_ongoing_operations), - next_operation_id: 0, blocks: Default::default(), + operations: Operations::new(self.max_ongoing_operations), }; entry.insert(state); @@ -631,21 +783,24 @@ impl> SubscriptionsInner { return Err(SubscriptionManagementError::BlockHashAbsent) } - let Some(permit_operations) = sub.reserve_at_most(to_reserve) else { + let Some(operation) = sub.register_operation(to_reserve) else { // Error when the server cannot execute at least one operation. return Err(SubscriptionManagementError::ExceededLimits) }; - let operation_id = sub.next_operation_id(); BlockGuard::new( hash, sub.with_runtime, sub.response_sender.clone(), - operation_id, - permit_operations, + operation, self.backend.clone(), ) } + + pub fn get_operation(&mut self, sub_id: &str, id: &str) -> Option { + let state = self.subs.get(sub_id)?; + state.get_operation(id) + } } #[cfg(test)] @@ -758,8 +913,7 @@ mod tests { with_runtime: false, tx_stop: None, response_sender, - next_operation_id: 0, - limits: LimitOperations::new(MAX_OPERATIONS_PER_SUB), + operations: Operations::new(MAX_OPERATIONS_PER_SUB), blocks: Default::default(), }; @@ -788,9 +942,8 @@ mod tests { with_runtime: false, tx_stop: None, response_sender, - next_operation_id: 0, - limits: LimitOperations::new(MAX_OPERATIONS_PER_SUB), blocks: Default::default(), + operations: Operations::new(MAX_OPERATIONS_PER_SUB), }; let hash = H256::random(); @@ -1107,12 +1260,12 @@ mod tests { // One operation is reserved. let permit_one = ops.reserve_at_most(1).unwrap(); - assert_eq!(permit_one.num_reserved(), 1); + assert_eq!(permit_one.num_ops, 1); // Request 2 operations, however there is capacity only for one. let permit_two = ops.reserve_at_most(2).unwrap(); // Number of reserved permits is smaller than provided. - assert_eq!(permit_two.num_reserved(), 1); + assert_eq!(permit_two.num_ops, 1); // Try to reserve operations when there's no space. let permit = ops.reserve_at_most(1); @@ -1123,6 +1276,6 @@ mod tests { // Can reserve again let permit_three = ops.reserve_at_most(1).unwrap(); - assert_eq!(permit_three.num_reserved(), 1); + assert_eq!(permit_three.num_ops, 1); } } diff --git a/client/rpc-spec-v2/src/chain_head/subscription/mod.rs b/client/rpc-spec-v2/src/chain_head/subscription/mod.rs index 39618ecfc1b3e..b25b1a4913b49 100644 --- a/client/rpc-spec-v2/src/chain_head/subscription/mod.rs +++ b/client/rpc-spec-v2/src/chain_head/subscription/mod.rs @@ -25,6 +25,8 @@ mod error; mod inner; use self::inner::SubscriptionsInner; + +pub use self::inner::OperationState; pub use error::SubscriptionManagementError; pub use inner::{BlockGuard, InsertedSubscriptionData}; @@ -126,4 +128,10 @@ impl> SubscriptionManagement { let mut inner = self.inner.write(); inner.lock_block(sub_id, hash, to_reserve) } + + /// Get the operation state. + pub fn get_operation(&self, sub_id: &str, operation_id: &str) -> Option { + let mut inner = self.inner.write(); + inner.get_operation(sub_id, operation_id) + } } diff --git a/client/rpc-spec-v2/src/chain_head/tests.rs b/client/rpc-spec-v2/src/chain_head/tests.rs index 4bda06d3cf01c..00ed9089058ee 100644 --- a/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/client/rpc-spec-v2/src/chain_head/tests.rs @@ -25,7 +25,7 @@ use sp_core::{ Blake2Hasher, Hasher, }; use sp_version::RuntimeVersion; -use std::{collections::HashSet, sync::Arc, time::Duration}; +use std::{collections::HashSet, fmt::Debug, sync::Arc, time::Duration}; use substrate_test_runtime::Transfer; use substrate_test_runtime_client::{ prelude::*, runtime, runtime::RuntimeApi, Backend, BlockBuilderExt, Client, @@ -37,12 +37,14 @@ type Block = substrate_test_runtime_client::runtime::Block; const MAX_PINNED_BLOCKS: usize = 32; const MAX_PINNED_SECS: u64 = 60; const MAX_OPERATIONS: usize = 16; +const MAX_PAGINATION_LIMIT: usize = 5; const CHAIN_GENESIS: [u8; 32] = [0; 32]; const INVALID_HASH: [u8; 32] = [1; 32]; const KEY: &[u8] = b":mock"; const VALUE: &[u8] = b"hello world"; const CHILD_STORAGE_KEY: &[u8] = b"child"; const CHILD_VALUE: &[u8] = b"child value"; +const DOES_NOT_PRODUCE_EVENTS_SECONDS: u64 = 10; async fn get_next_event(sub: &mut RpcSubscription) -> T { let (event, _sub_id) = tokio::time::timeout(std::time::Duration::from_secs(60), sub.next()) @@ -53,6 +55,13 @@ async fn get_next_event(sub: &mut RpcSubscriptio event } +async fn does_not_produce_event( + sub: &mut RpcSubscription, + duration: std::time::Duration, +) { + tokio::time::timeout(duration, sub.next::()).await.unwrap_err(); +} + async fn run_with_timeout(future: F) -> ::Output { tokio::time::timeout(std::time::Duration::from_secs(60 * 10), future) .await @@ -84,6 +93,7 @@ async fn setup_api() -> ( global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -127,6 +137,7 @@ async fn follow_subscription_produces_blocks() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -188,6 +199,7 @@ async fn follow_with_runtime() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -299,6 +311,7 @@ async fn get_genesis() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -508,6 +521,7 @@ async fn call_runtime_without_flag() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -743,11 +757,16 @@ async fn get_storage_multi_query_iter() { assert_matches!( get_next_event::>(&mut block_sub).await, FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && - res.items.len() == 2 && + res.items.len() == 1 && + res.items[0].key == key && + res.items[0].result == StorageResultType::Hash(expected_hash) + ); + assert_matches!( + get_next_event::>(&mut block_sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && res.items[0].key == key && - res.items[1].key == key && - res.items[0].result == StorageResultType::Hash(expected_hash) && - res.items[1].result == StorageResultType::Value(expected_value) + res.items[0].result == StorageResultType::Value(expected_value) ); assert_matches!( get_next_event::>(&mut block_sub).await, @@ -788,11 +807,16 @@ async fn get_storage_multi_query_iter() { assert_matches!( get_next_event::>(&mut block_sub).await, FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && - res.items.len() == 2 && + res.items.len() == 1 && res.items[0].key == key && - res.items[1].key == key && - res.items[0].result == StorageResultType::Hash(expected_hash) && - res.items[1].result == StorageResultType::Value(expected_value) + res.items[0].result == StorageResultType::Hash(expected_hash) + ); + assert_matches!( + get_next_event::>(&mut block_sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && + res.items[0].key == key && + res.items[0].result == StorageResultType::Value(expected_value) ); assert_matches!( get_next_event::>(&mut block_sub).await, @@ -1137,6 +1161,7 @@ async fn separate_operation_ids_for_subscriptions() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1217,6 +1242,7 @@ async fn follow_generates_initial_blocks() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1348,6 +1374,7 @@ async fn follow_exceeding_pinned_blocks() { global_max_pinned_blocks: 2, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1402,6 +1429,7 @@ async fn follow_with_unpin() { global_max_pinned_blocks: 2, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1486,6 +1514,7 @@ async fn follow_prune_best_block() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1646,6 +1675,7 @@ async fn follow_forks_pruned_block() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1763,6 +1793,7 @@ async fn follow_report_multiple_pruned_block() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -1971,6 +2002,7 @@ async fn pin_block_references() { global_max_pinned_blocks: 3, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -2084,6 +2116,7 @@ async fn follow_finalized_before_new_block() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -2184,6 +2217,7 @@ async fn ensure_operation_limits_works() { global_max_pinned_blocks: MAX_PINNED_BLOCKS, subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), subscription_max_ongoing_operations: 1, + operation_max_storage_items: MAX_PAGINATION_LIMIT, }, ) .into_rpc(); @@ -2259,3 +2293,275 @@ async fn ensure_operation_limits_works() { FollowEvent::OperationCallDone(done) if done.operation_id == operation_id && done.output == "0x0000000000000000" ); } + +#[tokio::test] +async fn check_continue_operation() { + let child_info = ChildInfo::new_default(CHILD_STORAGE_KEY); + let builder = TestClientBuilder::new().add_extra_child_storage( + &child_info, + KEY.to_vec(), + CHILD_VALUE.to_vec(), + ); + let backend = builder.backend(); + let mut client = Arc::new(builder.build()); + + // Configure the chainHead with maximum 1 item before asking for pagination. + let api = ChainHead::new( + client.clone(), + backend, + Arc::new(TaskExecutor::default()), + CHAIN_GENESIS, + ChainHeadConfig { + global_max_pinned_blocks: MAX_PINNED_BLOCKS, + subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), + subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: 1, + }, + ) + .into_rpc(); + + let mut sub = api.subscribe("chainHead_unstable_follow", [true]).await.unwrap(); + let sub_id = sub.subscription_id(); + let sub_id = serde_json::to_string(&sub_id).unwrap(); + + // Import a new block with storage changes. + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push_storage_change(b":m".to_vec(), Some(b"a".to_vec())).unwrap(); + builder.push_storage_change(b":mo".to_vec(), Some(b"ab".to_vec())).unwrap(); + builder.push_storage_change(b":moc".to_vec(), Some(b"abc".to_vec())).unwrap(); + builder.push_storage_change(b":mock".to_vec(), Some(b"abcd".to_vec())).unwrap(); + let block = builder.build().unwrap().block; + let block_hash = format!("{:?}", block.header.hash()); + client.import(BlockOrigin::Own, block.clone()).await.unwrap(); + + // Ensure the imported block is propagated and pinned for this subscription. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::Initialized(_) + ); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::NewBlock(_) + ); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::BestBlockChanged(_) + ); + + let invalid_hash = hex_string(&INVALID_HASH); + + // Invalid subscription ID must produce no results. + let _res: () = api + .call("chainHead_unstable_continue", ["invalid_sub_id", &invalid_hash]) + .await + .unwrap(); + + // Invalid operation ID must produce no results. + let _res: () = api.call("chainHead_unstable_continue", [&sub_id, &invalid_hash]).await.unwrap(); + + // Valid call with storage at the key. + let response: MethodResponse = api + .call( + "chainHead_unstable_storage", + rpc_params![ + &sub_id, + &block_hash, + vec![StorageQuery { + key: hex_string(b":m"), + query_type: StorageQueryType::DescendantsValues + }] + ], + ) + .await + .unwrap(); + let operation_id = match response { + MethodResponse::Started(started) => started.operation_id, + MethodResponse::LimitReached => panic!("Expected started response"), + }; + + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && + res.items[0].key == hex_string(b":m") && + res.items[0].result == StorageResultType::Value(hex_string(b"a")) + ); + + // Pagination event. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationWaitingForContinue(res) if res.operation_id == operation_id + ); + + does_not_produce_event::>( + &mut sub, + std::time::Duration::from_secs(DOES_NOT_PRODUCE_EVENTS_SECONDS), + ) + .await; + let _res: () = api.call("chainHead_unstable_continue", [&sub_id, &operation_id]).await.unwrap(); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && + res.items[0].key == hex_string(b":mo") && + res.items[0].result == StorageResultType::Value(hex_string(b"ab")) + ); + + // Pagination event. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationWaitingForContinue(res) if res.operation_id == operation_id + ); + + does_not_produce_event::>( + &mut sub, + std::time::Duration::from_secs(DOES_NOT_PRODUCE_EVENTS_SECONDS), + ) + .await; + let _res: () = api.call("chainHead_unstable_continue", [&sub_id, &operation_id]).await.unwrap(); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && + res.items[0].key == hex_string(b":moc") && + res.items[0].result == StorageResultType::Value(hex_string(b"abc")) + ); + + // Pagination event. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationWaitingForContinue(res) if res.operation_id == operation_id + ); + does_not_produce_event::>( + &mut sub, + std::time::Duration::from_secs(DOES_NOT_PRODUCE_EVENTS_SECONDS), + ) + .await; + let _res: () = api.call("chainHead_unstable_continue", [&sub_id, &operation_id]).await.unwrap(); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && + res.items[0].key == hex_string(b":mock") && + res.items[0].result == StorageResultType::Value(hex_string(b"abcd")) + ); + + // Finished. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationStorageDone(done) if done.operation_id == operation_id + ); +} + +#[tokio::test] +async fn stop_storage_operation() { + let child_info = ChildInfo::new_default(CHILD_STORAGE_KEY); + let builder = TestClientBuilder::new().add_extra_child_storage( + &child_info, + KEY.to_vec(), + CHILD_VALUE.to_vec(), + ); + let backend = builder.backend(); + let mut client = Arc::new(builder.build()); + + // Configure the chainHead with maximum 1 item before asking for pagination. + let api = ChainHead::new( + client.clone(), + backend, + Arc::new(TaskExecutor::default()), + CHAIN_GENESIS, + ChainHeadConfig { + global_max_pinned_blocks: MAX_PINNED_BLOCKS, + subscription_max_pinned_duration: Duration::from_secs(MAX_PINNED_SECS), + subscription_max_ongoing_operations: MAX_OPERATIONS, + operation_max_storage_items: 1, + }, + ) + .into_rpc(); + + let mut sub = api.subscribe("chainHead_unstable_follow", [true]).await.unwrap(); + let sub_id = sub.subscription_id(); + let sub_id = serde_json::to_string(&sub_id).unwrap(); + + // Import a new block with storage changes. + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push_storage_change(b":m".to_vec(), Some(b"a".to_vec())).unwrap(); + builder.push_storage_change(b":mo".to_vec(), Some(b"ab".to_vec())).unwrap(); + let block = builder.build().unwrap().block; + let block_hash = format!("{:?}", block.header.hash()); + client.import(BlockOrigin::Own, block.clone()).await.unwrap(); + + // Ensure the imported block is propagated and pinned for this subscription. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::Initialized(_) + ); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::NewBlock(_) + ); + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::BestBlockChanged(_) + ); + + let invalid_hash = hex_string(&INVALID_HASH); + + // Invalid subscription ID must produce no results. + let _res: () = api + .call("chainHead_unstable_stopOperation", ["invalid_sub_id", &invalid_hash]) + .await + .unwrap(); + + // Invalid operation ID must produce no results. + let _res: () = api + .call("chainHead_unstable_stopOperation", [&sub_id, &invalid_hash]) + .await + .unwrap(); + + // Valid call with storage at the key. + let response: MethodResponse = api + .call( + "chainHead_unstable_storage", + rpc_params![ + &sub_id, + &block_hash, + vec![StorageQuery { + key: hex_string(b":m"), + query_type: StorageQueryType::DescendantsValues + }] + ], + ) + .await + .unwrap(); + let operation_id = match response { + MethodResponse::Started(started) => started.operation_id, + MethodResponse::LimitReached => panic!("Expected started response"), + }; + + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationStorageItems(res) if res.operation_id == operation_id && + res.items.len() == 1 && + res.items[0].key == hex_string(b":m") && + res.items[0].result == StorageResultType::Value(hex_string(b"a")) + ); + + // Pagination event. + assert_matches!( + get_next_event::>(&mut sub).await, + FollowEvent::OperationWaitingForContinue(res) if res.operation_id == operation_id + ); + + // Stop the operation. + let _res: () = api + .call("chainHead_unstable_stopOperation", [&sub_id, &operation_id]) + .await + .unwrap(); + + does_not_produce_event::>( + &mut sub, + std::time::Duration::from_secs(DOES_NOT_PRODUCE_EVENTS_SECONDS), + ) + .await; +} diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index 9ad2fcf778f2d..6dcd8b8e4bace 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -13,15 +13,15 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [features] -default = ["rocksdb"] +default = [ "rocksdb" ] # The RocksDB feature activates the RocksDB database backend. If it is not activated, and you pass # a path to a database, an error will be produced at runtime. -rocksdb = ["sc-client-db/rocksdb"] +rocksdb = [ "sc-client-db/rocksdb" ] # exposes the client type test-helpers = [] runtime-benchmarks = [ "sc-client-db/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] [dependencies] diff --git a/client/utils/Cargo.toml b/client/utils/Cargo.toml index 40b742f373886..21b082a35fd6e 100644 --- a/client/utils/Cargo.toml +++ b/client/utils/Cargo.toml @@ -20,7 +20,7 @@ prometheus = { version = "0.13.0", default-features = false } sp-arithmetic = { version = "16.0.0", default-features = false, path = "../../primitives/arithmetic" } [features] -default = ["metered"] +default = [ "metered" ] metered = [] [dev-dependencies] diff --git a/docs/STYLE_GUIDE.md b/docs/STYLE_GUIDE.md index 8854f885a4b22..a89dcf52ffc0b 100644 --- a/docs/STYLE_GUIDE.md +++ b/docs/STYLE_GUIDE.md @@ -5,7 +5,7 @@ title: Style Guide for Rust in Substrate Where possible these styles are enforced by settings in `rustfmt.toml` so if you run `cargo fmt` then you will adhere to most of these style guidelines automatically. -# Formatting +# Code Formatting - Indent using tabs. - Lines should be longer than 100 characters long only in exceptional circumstances and certainly @@ -147,3 +147,26 @@ let mut target_path = - how likely is it that invariants could be violated, - are issues stemming from the use of unsafe code caught by existing tests/tooling, - what are the consequences if the problems slip into production. + +# Manifest Formatting + +> **TLDR** +> You can use the CLI tool [Zepter](https://crates.io/crates/zepter) to format the files: `zepter format features` + +Rust `Cargo.toml` files need to respect certain formatting rules. All entries need to be alphabetically sorted. This makes it easier to read them and insert new entries. The exhaustive list of rules is enforced by the CI. The general format looks like this: + +- The feature is written as a single line if it fits within 80 chars: +```toml +[features] +default = [ "std" ] +``` + +- Otherwise the feature is broken down into multiple lines with one entry per line. Each line is padded with one tab and no trailing spaces but a trailing comma. +```toml +[features] +default = [ + "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + # Comments go here as well ;) + "std", +] +``` diff --git a/frame/alliance/Cargo.toml b/frame/alliance/Cargo.toml index d0330ddfd6721..77703a7739d6e 100644 --- a/frame/alliance/Cargo.toml +++ b/frame/alliance/Cargo.toml @@ -39,33 +39,33 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } pallet-collective = { version = "4.0.0-dev", path = "../collective" } [features] -default = ["std"] +default = [ "std" ] std = [ - "sp-core-hashing?/std", - "pallet-collective?/std", + "codec/std", "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", "log/std", - "codec/std", + "pallet-balances/std", + "pallet-collective?/std", + "pallet-identity/std", "scale-info/std", - "sp-std/std", + "sp-core-hashing?/std", "sp-core/std", "sp-io/std", "sp-runtime/std", - "frame-support/std", - "frame-system/std", - "pallet-identity/std", - "pallet-balances/std" + "sp-std/std", ] runtime-benchmarks = [ "array-bytes", - "sp-core-hashing", "frame-benchmarking/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-identity/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" + "sp-core-hashing", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -73,5 +73,5 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-collective?/try-runtime", "pallet-identity/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/alliance/src/lib.rs b/frame/alliance/src/lib.rs index c103f975f23be..1986354a0941c 100644 --- a/frame/alliance/src/lib.rs +++ b/frame/alliance/src/lib.rs @@ -94,6 +94,7 @@ pub mod migration; mod types; pub mod weights; +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use sp_runtime::{ @@ -103,13 +104,11 @@ use sp_runtime::{ use sp_std::{convert::TryInto, prelude::*}; use frame_support::{ - codec::{Decode, Encode, MaxEncodedLen}, dispatch::{ DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, GetDispatchInfo, PostDispatchInfo, }, ensure, - scale_info::TypeInfo, traits::{ ChangeMembers, Currency, Get, InitializeMembers, IsSubType, OnUnbalanced, ReservableCurrency, @@ -117,6 +116,7 @@ use frame_support::{ weights::Weight, }; use pallet_identity::IdentityField; +use scale_info::TypeInfo; pub use pallet::*; pub use types::*; diff --git a/frame/asset-conversion/Cargo.toml b/frame/asset-conversion/Cargo.toml index 77bfab48bbf08..2ad8d9d473e05 100644 --- a/frame/asset-conversion/Cargo.toml +++ b/frame/asset-conversion/Cargo.toml @@ -31,34 +31,34 @@ pallet-assets = { version = "4.0.0-dev", path = "../assets" } primitive-types = { version = "0.12.0", default-features = false, features = ["codec", "scale-info", "num-traits"] } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "scale-info/std", - "sp-std/std", - "sp-runtime/std", - "sp-arithmetic/std", "pallet-assets/std", "pallet-balances/std", + "scale-info/std", "sp-api/std", + "sp-arithmetic/std", "sp-core/std", - "sp-io/std" + "sp-io/std", + "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-assets/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/asset-conversion/src/lib.rs b/frame/asset-conversion/src/lib.rs index 3a16ab875c06a..d1d68f3e10fbb 100644 --- a/frame/asset-conversion/src/lib.rs +++ b/frame/asset-conversion/src/lib.rs @@ -147,6 +147,9 @@ pub mod pallet { /// Type that identifies either the native currency or a token class from `Assets`. /// `Ord` is added because of `get_pool_id`. + /// + /// The pool's `AccountId` is derived from this type. Any changes to the type may + /// necessitate a migration. type MultiAssetId: AssetId + Ord + From; /// Type to convert an `AssetId` into `MultiAssetId`. @@ -1193,7 +1196,9 @@ pub mod pallet { () ); } else { - let MultiAssetIdConversionResult::Converted(asset_id) = T::MultiAssetIdConverter::try_convert(asset) else { + let MultiAssetIdConversionResult::Converted(asset_id) = + T::MultiAssetIdConverter::try_convert(asset) + else { return Err(()) }; let minimal = T::Assets::minimum_balance(asset_id); diff --git a/frame/asset-conversion/src/tests.rs b/frame/asset-conversion/src/tests.rs index 80faf5363b011..450a074ec3675 100644 --- a/frame/asset-conversion/src/tests.rs +++ b/frame/asset-conversion/src/tests.rs @@ -66,7 +66,11 @@ fn pool_assets() -> Vec { fn create_tokens(owner: u128, tokens: Vec>) { for token_id in tokens { - let MultiAssetIdConversionResult::Converted(asset_id) = NativeOrAssetIdConverter::try_convert(&token_id) else { unreachable!("invalid token") }; + let MultiAssetIdConversionResult::Converted(asset_id) = + NativeOrAssetIdConverter::try_convert(&token_id) + else { + unreachable!("invalid token") + }; assert_ok!(Assets::force_create(RuntimeOrigin::root(), asset_id, owner, false, 1)); } } diff --git a/frame/asset-conversion/src/types.rs b/frame/asset-conversion/src/types.rs index 7cd9743ff04b8..9c28bd7666b71 100644 --- a/frame/asset-conversion/src/types.rs +++ b/frame/asset-conversion/src/types.rs @@ -21,6 +21,10 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_std::{cmp::Ordering, marker::PhantomData}; +/// Pool ID. +/// +/// The pool's `AccountId` is derived from this type. Any changes to the type may necessitate a +/// migration. pub(super) type PoolIdOf = (::MultiAssetId, ::MultiAssetId); /// Stores the lp_token asset id a particular pool has been assigned. diff --git a/frame/asset-rate/Cargo.toml b/frame/asset-rate/Cargo.toml index ebea548d88c91..4a37be8c452b1 100644 --- a/frame/asset-rate/Cargo.toml +++ b/frame/asset-rate/Cargo.toml @@ -30,30 +30,30 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-core = { version = "21.0.0", default-features = false, path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", + "sp-core?/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core?/std", - "pallet-balances/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-core", "sp-runtime/runtime-benchmarks", - "sp-core", - "pallet-balances/runtime-benchmarks" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-balances/try-runtime", "sp-runtime/try-runtime", - "pallet-balances/try-runtime" ] diff --git a/frame/asset-rate/src/benchmarking.rs b/frame/asset-rate/src/benchmarking.rs index 0e13697806043..12edcf5aee025 100644 --- a/frame/asset-rate/src/benchmarking.rs +++ b/frame/asset-rate/src/benchmarking.rs @@ -25,6 +25,7 @@ use frame_benchmarking::v2::*; use frame_support::assert_ok; use frame_system::RawOrigin; use sp_core::crypto::FromEntropy; +use sp_std::vec; /// Trait describing the factory function for the `AssetKind` parameter. pub trait AssetKindFactory { diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 4bef7195958f9..5795bbb228625 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } # Needed for various traits. In our case, `OnFinalize`. @@ -31,29 +32,30 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", - "scale-info/std", - "sp-core/std", - "sp-std/std", - "sp-runtime/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "frame-benchmarking?/std", + "log/std", "pallet-balances/std", - "sp-io/std" + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/assets/src/migration.rs b/frame/assets/src/migration.rs index d854a64afb57f..efe77714c524d 100644 --- a/frame/assets/src/migration.rs +++ b/frame/assets/src/migration.rs @@ -16,7 +16,8 @@ // limitations under the License. use super::*; -use frame_support::{log, traits::OnRuntimeUpgrade}; +use frame_support::traits::OnRuntimeUpgrade; +use log; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml index bf5018250d8c9..da154d4421f3c 100644 --- a/frame/atomic-swap/Cargo.toml +++ b/frame/atomic-swap/Cargo.toml @@ -26,21 +26,21 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 99c8c2fb497f0..67eb99fcd5fbe 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -28,24 +29,25 @@ sp-core = { version = "21.0.0", default-features = false, path = "../../primitiv sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", + "log/std", "pallet-timestamp/std", "scale-info/std", "sp-application-crypto/std", "sp-consensus-aura/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std", - "sp-io/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] experimental = [] diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index 641d5fc47e90e..b314a3601e15f 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -40,10 +40,10 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ - log, traits::{DisabledValidators, FindAuthor, Get, OnTimestampSet, OneSessionHandler}, BoundedSlice, BoundedVec, ConsensusEngineId, Parameter, }; +use log; use sp_consensus_aura::{AuthorityIndex, ConsensusLog, Slot, AURA_ENGINE_ID}; use sp_runtime::{ generic::DigestItem, diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 4e5025d7c770e..4096e2bbd548d 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -32,7 +32,7 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -41,14 +41,14 @@ std = [ "scale-info/std", "sp-application-crypto/std", "sp-authority-discovery/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std", - "sp-io/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-session/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 14329367b0905..3dadb1bed3c74 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -28,19 +28,19 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std", - "sp-io/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 34cc6cc09baad..75032fd128d10 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -40,15 +40,19 @@ pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../staking/reward sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", "log/std", "pallet-authorship/std", + "pallet-balances/std", + "pallet-offences/std", "pallet-session/std", + "pallet-staking/std", "pallet-timestamp/std", "scale-info/std", "sp-application-crypto/std", @@ -59,10 +63,6 @@ std = [ "sp-session/std", "sp-staking/std", "sp-std/std", - "frame-election-provider-support/std", - "pallet-balances/std", - "pallet-offences/std", - "pallet-staking/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -74,11 +74,11 @@ runtime-benchmarks = [ "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", @@ -86,5 +86,5 @@ try-runtime = [ "pallet-session/try-runtime", "pallet-staking/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/bags-list/Cargo.toml b/frame/bags-list/Cargo.toml index 222d64dc229f6..aeb0a6c50b922 100644 --- a/frame/bags-list/Cargo.toml +++ b/frame/bags-list/Cargo.toml @@ -46,44 +46,44 @@ frame-election-provider-support = { version = "4.0.0-dev", path = "../election-p frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } [features] -default = ["std"] +default = [ "std" ] std = [ - "sp-tracing?/std", - "sp-io?/std", - "sp-core?/std", - "pallet-balances?/std", - "frame-benchmarking?/std", - "scale-info/std", "codec/std", - "sp-runtime/std", - "sp-std/std", + "frame-benchmarking?/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", - "frame-election-provider-support/std", "log/std", + "pallet-balances?/std", + "scale-info/std", + "sp-core?/std", + "sp-io?/std", + "sp-runtime/std", + "sp-std/std", + "sp-tracing?/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "sp-core", - "sp-io", - "pallet-balances/runtime-benchmarks", - "sp-tracing", "frame-election-provider-support/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "pallet-balances/runtime-benchmarks", + "sp-core", + "sp-io", + "sp-runtime/runtime-benchmarks", + "sp-tracing", ] fuzz = [ + "frame-election-provider-support/fuzz", + "pallet-balances", "sp-core", "sp-io", - "pallet-balances", "sp-tracing", - "frame-election-provider-support/fuzz", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances?/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 549ed3936a9e1..861843b88949a 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -29,19 +29,19 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } paste = "1.0.12" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-transaction-payment/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-transaction-payment/std", - "sp-core/std", - "sp-io/std" ] # Enable support for setting the existential deposit to zero. insecure_zero_ed = [] @@ -49,11 +49,11 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 90bee7d99e121..f94b3230b917b 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -220,11 +220,14 @@ pub mod pallet { pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] impl DefaultConfig for TestDefaultConfig { + #[inject_runtime_type] + type RuntimeEvent = (); + type Balance = u64; type ReserveIdentifier = (); @@ -242,6 +245,7 @@ pub mod pallet { #[pallet::config(with_default)] pub trait Config: frame_system::Config { /// The overarching event type. + #[pallet::no_default_bounds] type RuntimeEvent: From> + IsType<::RuntimeEvent>; diff --git a/frame/balances/src/tests/mod.rs b/frame/balances/src/tests/mod.rs index 45f34110a6e9e..cefc6e9e8f51f 100644 --- a/frame/balances/src/tests/mod.rs +++ b/frame/balances/src/tests/mod.rs @@ -30,7 +30,6 @@ use frame_support::{ StorageMapShim, StoredMap, WhitelistedStorageKeys, }, weights::{IdentityFee, Weight}, - RuntimeDebug, }; use frame_system::{self as system, RawOrigin}; use pallet_transaction_payment::{ChargeTransactionPayment, CurrencyAdapter, Multiplier}; @@ -39,7 +38,8 @@ use sp_core::{hexdisplay::HexDisplay, H256}; use sp_io; use sp_runtime::{ traits::{BadOrigin, IdentityLookup, SignedExtension, Zero}, - ArithmeticError, BuildStorage, DispatchError, DispatchResult, FixedPointNumber, TokenError, + ArithmeticError, BuildStorage, DispatchError, DispatchResult, FixedPointNumber, RuntimeDebug, + TokenError, }; use std::collections::BTreeSet; diff --git a/frame/balances/src/types.rs b/frame/balances/src/types.rs index 389124402a8f1..cd100d0df6c6d 100644 --- a/frame/balances/src/types.rs +++ b/frame/balances/src/types.rs @@ -20,12 +20,9 @@ use crate::{Config, CreditOf, Event, Pallet}; use codec::{Decode, Encode, MaxEncodedLen}; use core::ops::BitOr; -use frame_support::{ - traits::{Imbalance, LockIdentifier, OnUnbalanced, WithdrawReasons}, - RuntimeDebug, -}; +use frame_support::traits::{Imbalance, LockIdentifier, OnUnbalanced, WithdrawReasons}; use scale_info::TypeInfo; -use sp_runtime::Saturating; +use sp_runtime::{RuntimeDebug, Saturating}; /// Simplified reasons for withdrawing balance. #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] diff --git a/frame/beefy-mmr/Cargo.toml b/frame/beefy-mmr/Cargo.toml index 5691a5d735272..af3ecf4d03b9a 100644 --- a/frame/beefy-mmr/Cargo.toml +++ b/frame/beefy-mmr/Cargo.toml @@ -26,13 +26,14 @@ sp-io = { version = "23.0.0", default-features = false, path = "../../primitives sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } +sp-state-machine = { version = "0.28.0", default-features = false, path = "../../primitives/state-machine" } [dev-dependencies] array-bytes = "6.1" sp-staking = { version = "4.0.0-dev", path = "../../primitives/staking" } [features] -default = ["std"] +default = [ "std" ] std = [ "array-bytes", "binary-merkle-tree/std", @@ -45,13 +46,14 @@ std = [ "pallet-session/std", "scale-info/std", "serde", + "sp-api/std", "sp-consensus-beefy/std", "sp-core/std", "sp-io/std", "sp-runtime/std", + "sp-staking/std", + "sp-state-machine/std", "sp-std/std", - "sp-api/std", - "sp-staking/std" ] try-runtime = [ "frame-support/try-runtime", @@ -59,5 +61,5 @@ try-runtime = [ "pallet-beefy/try-runtime", "pallet-mmr/try-runtime", "pallet-session/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/beefy-mmr/src/mock.rs b/frame/beefy-mmr/src/mock.rs index 2c37ad4483f6b..b2d8758a04be6 100644 --- a/frame/beefy-mmr/src/mock.rs +++ b/frame/beefy-mmr/src/mock.rs @@ -20,18 +20,18 @@ use std::vec; use codec::Encode; use frame_support::{ construct_runtime, parameter_types, - sp_io::TestExternalities, traits::{ConstU16, ConstU32, ConstU64}, - BasicExternalities, }; use sp_consensus_beefy::mmr::MmrLeafVersion; use sp_core::H256; +use sp_io::TestExternalities; use sp_runtime::{ app_crypto::ecdsa::Public, impl_opaque_keys, traits::{BlakeTwo256, ConvertInto, IdentityLookup, Keccak256, OpaqueKeys}, BuildStorage, }; +use sp_state_machine::BasicExternalities; use crate as pallet_beefy_mmr; diff --git a/frame/beefy/Cargo.toml b/frame/beefy/Cargo.toml index 9f331f74f778f..7196d8b7d55b1 100644 --- a/frame/beefy/Cargo.toml +++ b/frame/beefy/Cargo.toml @@ -10,6 +10,7 @@ homepage = "https://substrate.io" [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive", "serde"] } serde = { version = "1.0.163", optional = true } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -32,33 +33,36 @@ pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-staking = { version = "4.0.0-dev", path = "../../primitives/staking" } +sp-state-machine = { version = "0.28.0", default-features = false, path = "../../primitives/state-machine" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", + "log/std", "pallet-authorship/std", + "pallet-balances/std", + "pallet-offences/std", "pallet-session/std", + "pallet-staking/std", + "pallet-timestamp/std", "scale-info/std", "serde/std", "sp-consensus-beefy/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-session/std", "sp-staking/std", + "sp-state-machine/std", "sp-std/std", - "frame-election-provider-support/std", - "pallet-balances/std", - "pallet-offences/std", - "pallet-staking/std", - "pallet-timestamp/std", - "sp-core/std", - "sp-io/std" ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", @@ -66,5 +70,5 @@ try-runtime = [ "pallet-session/try-runtime", "pallet-staking/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/beefy/src/equivocation.rs b/frame/beefy/src/equivocation.rs index 84c62fc47f50a..0a7ede327c9e6 100644 --- a/frame/beefy/src/equivocation.rs +++ b/frame/beefy/src/equivocation.rs @@ -35,10 +35,7 @@ //! definition. use codec::{self as codec, Decode, Encode}; -use frame_support::{ - log, - traits::{Get, KeyOwnerProofSystem}, -}; +use frame_support::traits::{Get, KeyOwnerProofSystem}; use frame_system::pallet_prelude::BlockNumberFor; use log::{error, info}; use sp_consensus_beefy::{EquivocationProof, ValidatorSetId, KEY_TYPE as BEEFY_KEY_TYPE}; diff --git a/frame/beefy/src/lib.rs b/frame/beefy/src/lib.rs index 35d3273e1ef76..77e74436dd671 100644 --- a/frame/beefy/src/lib.rs +++ b/frame/beefy/src/lib.rs @@ -21,7 +21,6 @@ use codec::{Encode, MaxEncodedLen}; use frame_support::{ dispatch::{DispatchResultWithPostInfo, Pays}, - log, pallet_prelude::*, traits::{Get, OneSessionHandler}, weights::Weight, @@ -31,6 +30,7 @@ use frame_system::{ ensure_none, ensure_signed, pallet_prelude::{BlockNumberFor, OriginFor}, }; +use log; use sp_runtime::{ generic::DigestItem, traits::{IsMember, Member}, diff --git a/frame/beefy/src/mock.rs b/frame/beefy/src/mock.rs index f2d8415bc01f7..b55a65dbd73af 100644 --- a/frame/beefy/src/mock.rs +++ b/frame/beefy/src/mock.rs @@ -23,12 +23,11 @@ use frame_election_provider_support::{ }; use frame_support::{ construct_runtime, parameter_types, - sp_io::TestExternalities, traits::{ConstU16, ConstU32, ConstU64, KeyOwnerProofSystem, OnFinalize, OnInitialize}, - BasicExternalities, }; use pallet_session::historical as pallet_session_historical; use sp_core::{crypto::KeyTypeId, ConstU128, H256}; +use sp_io::TestExternalities; use sp_runtime::{ app_crypto::ecdsa::Public, curve::PiecewiseLinear, @@ -38,6 +37,7 @@ use sp_runtime::{ BuildStorage, Perbill, }; use sp_staking::{EraIndex, SessionIndex}; +use sp_state_machine::BasicExternalities; use crate as pallet_beefy; diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 414b1b2301429..6a089c230cfd5 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -38,9 +38,10 @@ rusty-fork = { version = "0.3.0", default-features = false } sp-keystore = { version = "0.27.0", path = "../../primitives/keystore" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", + "frame-support-procedural/std", "frame-support/std", "frame-system/std", "linregress", @@ -51,15 +52,14 @@ std = [ "sp-application-crypto/std", "sp-core/std", "sp-io/std", + "sp-keystore/std", "sp-runtime-interface/std", "sp-runtime/std", "sp-std/std", "sp-storage/std", - "frame-support-procedural/std", - "sp-keystore/std" ] runtime-benchmarks = [ - "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] diff --git a/frame/benchmarking/pov/Cargo.toml b/frame/benchmarking/pov/Cargo.toml index c0ba8285519a5..2329565893bee 100644 --- a/frame/benchmarking/pov/Cargo.toml +++ b/frame/benchmarking/pov/Cargo.toml @@ -22,7 +22,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../pr sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking/std", @@ -34,13 +34,13 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ - "frame-system/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/benchmarking/src/baseline.rs b/frame/benchmarking/src/baseline.rs index 94c066269d91b..6cd23ebe028a3 100644 --- a/frame/benchmarking/src/baseline.rs +++ b/frame/benchmarking/src/baseline.rs @@ -20,13 +20,13 @@ #![cfg(feature = "runtime-benchmarks")] -use super::*; use crate::benchmarks; use frame_system::Pallet as System; use sp_runtime::{ traits::{AppVerify, Hash}, RuntimeAppPublic, }; +use sp_std::{vec, vec::Vec}; mod crypto { use sp_application_crypto::{app_crypto, sr25519, KeyTypeId}; @@ -110,7 +110,6 @@ benchmarks! { #[cfg(test)] pub mod mock { - use super::*; use sp_runtime::{testing::H256, BuildStorage}; type AccountId = u64; diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 8864cd1d88ddf..f79582d03e51c 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -28,29 +28,27 @@ mod tests_instance; mod utils; pub mod baseline; +pub mod v1; + +/// Private exports that are being used by macros. +/// +/// The exports are not stable and should not be relied on. +#[doc(hidden)] +pub mod __private { + pub use codec; + pub use frame_support::{storage, traits}; + pub use log; + pub use paste; + pub use sp_core::defer; + pub use sp_io::storage::root as storage_root; + pub use sp_runtime::{traits::Zero, StateVersion}; + pub use sp_std::{self, boxed::Box, str, vec, vec::Vec}; + pub use sp_storage::{well_known_keys, TrackedStorageKey}; +} #[cfg(feature = "std")] pub use analysis::{Analysis, AnalysisChoice, BenchmarkSelector}; -#[doc(hidden)] -pub use frame_support; -#[doc(hidden)] -pub use log; -#[doc(hidden)] -pub use paste; -#[doc(hidden)] -pub use sp_core::defer; -#[doc(hidden)] -pub use sp_io::storage::root as storage_root; -#[doc(hidden)] -pub use sp_runtime::traits::Zero; -#[doc(hidden)] -pub use sp_runtime::StateVersion; -#[doc(hidden)] -pub use sp_std::{self, boxed::Box, prelude::Vec, str, vec}; -pub use sp_storage::{well_known_keys, TrackedStorageKey}; pub use utils::*; - -pub mod v1; pub use v1::*; /// Contains macros, structs, and traits associated with v2 of the pallet benchmarking syntax. diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index 4b8339f65913d..e5bacbdb2361a 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -19,7 +19,6 @@ #![cfg(test)] -use super::*; use frame_support::{parameter_types, traits::ConstU32}; use sp_runtime::{ testing::H256, diff --git a/frame/benchmarking/src/tests_instance.rs b/frame/benchmarking/src/tests_instance.rs index 822efa70a2597..f2c721c8114c4 100644 --- a/frame/benchmarking/src/tests_instance.rs +++ b/frame/benchmarking/src/tests_instance.rs @@ -19,7 +19,6 @@ #![cfg(test)] -use super::*; use frame_support::traits::ConstU32; use sp_runtime::{ testing::H256, diff --git a/frame/benchmarking/src/v1.rs b/frame/benchmarking/src/v1.rs index d9f1c7dde0059..4ad8cc0edd46c 100644 --- a/frame/benchmarking/src/v1.rs +++ b/frame/benchmarking/src/v1.rs @@ -429,7 +429,7 @@ macro_rules! benchmarks_iter { verify $postcode:block $( $rest:tt )* ) => { - $crate::paste::paste! { + $crate::__private::paste::paste! { $crate::benchmarks_iter! { { $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? } { $( $instance: $instance_bound )? } @@ -446,17 +446,17 @@ macro_rules! benchmarks_iter { >:: [< new_call_variant_ $dispatch >] ( $($arg),* ); - let __benchmarked_call_encoded = $crate::frame_support::codec::Encode::encode( + let __benchmarked_call_encoded = $crate::__private::codec::Encode::encode( &__call ); }: { let __call_decoded = < Call - as $crate::frame_support::codec::Decode + as $crate::__private::codec::Decode >::decode(&mut &__benchmarked_call_encoded[..]) .expect("call is encoded above, encoding must be correct"); let __origin = $crate::to_origin!($origin $(, $origin_type)?); - as $crate::frame_support::traits::UnfilteredDispatchable + as $crate::__private::traits::UnfilteredDispatchable >::dispatch_bypass_filter(__call_decoded, __origin)?; } verify $postcode @@ -776,8 +776,8 @@ macro_rules! benchmark_backend { $crate::BenchmarkingSetup for $name where $( $where_clause )* { - fn components(&self) -> $crate::Vec<($crate::BenchmarkParameter, u32, u32)> { - $crate::vec! [ + fn components(&self) -> $crate::__private::Vec<($crate::BenchmarkParameter, u32, u32)> { + $crate::__private::vec! [ $( ($crate::BenchmarkParameter::$param, $param_from, $param_to) ),* @@ -788,7 +788,7 @@ macro_rules! benchmark_backend { &self, components: &[($crate::BenchmarkParameter, u32)], verify: bool - ) -> Result<$crate::Box Result<(), $crate::BenchmarkError>>, $crate::BenchmarkError> { + ) -> Result<$crate::__private::Box Result<(), $crate::BenchmarkError>>, $crate::BenchmarkError> { $( // Prepare instance let $param = components.iter() @@ -802,7 +802,7 @@ macro_rules! benchmark_backend { $( $param_instancer ; )* $( $post )* - Ok($crate::Box::new(move || -> Result<(), $crate::BenchmarkError> { + Ok($crate::__private::Box::new(move || -> Result<(), $crate::BenchmarkError> { $eval; if verify { $postcode; @@ -842,15 +842,15 @@ macro_rules! impl_bench_name_tests { { $( $names_extra:tt )* }, { $name:ident } ) => { - $crate::paste::paste! { + $crate::__private::paste::paste! { #[test] fn [] () { $new_test_exec.$exec_name(|| { // Skip all #[extra] benchmarks if $extra is false. if !($extra) { - let disabled = $crate::vec![ $( stringify!($names_extra).as_ref() ),* ]; + let disabled = $crate::__private::vec![ $( stringify!($names_extra).as_ref() ),* ]; if disabled.contains(&stringify!($name)) { - $crate::log::error!( + $crate::__private::log::error!( "INFO: extra benchmark skipped - {}", stringify!($name), ); @@ -873,21 +873,21 @@ macro_rules! impl_bench_name_tests { }, $crate::BenchmarkError::Override(_) => { // This is still considered a success condition. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark error overrided - {}", stringify!($name), ); }, $crate::BenchmarkError::Skip => { // This is considered a success condition. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark error skipped - {}", stringify!($name), ); }, $crate::BenchmarkError::Weightless => { // This is considered a success condition. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark weightless skipped - {}", stringify!($name), ); @@ -948,7 +948,7 @@ macro_rules! selected_benchmark { $crate::BenchmarkingSetup for SelectedBenchmark where $( $where_clause )* { - fn components(&self) -> $crate::Vec<($crate::BenchmarkParameter, u32, u32)> { + fn components(&self) -> $crate::__private::Vec<($crate::BenchmarkParameter, u32, u32)> { match self { $( Self::$bench => < @@ -962,7 +962,7 @@ macro_rules! selected_benchmark { &self, components: &[($crate::BenchmarkParameter, u32)], verify: bool - ) -> Result<$crate::Box Result<(), $crate::BenchmarkError>>, $crate::BenchmarkError> { + ) -> Result<$crate::__private::Box Result<(), $crate::BenchmarkError>>, $crate::BenchmarkError> { match self { $( Self::$bench => < @@ -992,19 +992,19 @@ macro_rules! impl_benchmark { $crate::Benchmarking for Pallet where T: frame_system::Config, $( $where_clause )* { - fn benchmarks(extra: bool) -> $crate::Vec<$crate::BenchmarkMetadata> { + fn benchmarks(extra: bool) -> $crate::__private::Vec<$crate::BenchmarkMetadata> { $($crate::validate_pov_mode!( $pov_name: $( $storage = $pov_mode )*; );)* - let mut all_names = $crate::vec![ $( stringify!($name).as_ref() ),* ]; + let mut all_names = $crate::__private::vec![ $( stringify!($name).as_ref() ),* ]; if !extra { let extra = [ $( stringify!($name_extra).as_ref() ),* ]; all_names.retain(|x| !extra.contains(x)); } - let pov_modes: $crate::Vec<($crate::Vec, $crate::Vec<($crate::Vec, $crate::Vec)>)> = $crate::vec![ + let pov_modes: $crate::__private::Vec<($crate::__private::Vec, $crate::__private::Vec<($crate::__private::Vec, $crate::__private::Vec)>)> = $crate::__private::vec![ $( (stringify!($pov_name).as_bytes().to_vec(), - $crate::vec![ + $crate::__private::vec![ $( ( stringify!($storage).as_bytes().to_vec(), stringify!($pov_mode).as_bytes().to_vec() ), )* ]), @@ -1025,18 +1025,18 @@ macro_rules! impl_benchmark { components, pov_modes: pov_modes.iter().find(|p| p.0 == name).map(|p| p.1.clone()).unwrap_or_default(), } - }).collect::<$crate::Vec<_>>() + }).collect::<$crate::__private::Vec<_>>() } fn run_benchmark( extrinsic: &[u8], c: &[($crate::BenchmarkParameter, u32)], - whitelist: &[$crate::TrackedStorageKey], + whitelist: &[$crate::__private::TrackedStorageKey], verify: bool, internal_repeats: u32, - ) -> Result<$crate::Vec<$crate::BenchmarkResult>, $crate::BenchmarkError> { + ) -> Result<$crate::__private::Vec<$crate::BenchmarkResult>, $crate::BenchmarkError> { // Map the input to the selected benchmark. - let extrinsic = $crate::str::from_utf8(extrinsic) + let extrinsic = $crate::__private::str::from_utf8(extrinsic) .map_err(|_| "`extrinsic` is not a valid utf8 string!")?; let selected_benchmark = match extrinsic { $( stringify!($name) => SelectedBenchmark::$name, )* @@ -1046,34 +1046,34 @@ macro_rules! impl_benchmark { // Add whitelist to DB including whitelisted caller let mut whitelist = whitelist.to_vec(); let whitelisted_caller_key = - as $crate::frame_support::storage::StorageMap<_,_>>::hashed_key_for( + as $crate::__private::storage::StorageMap<_,_>>::hashed_key_for( $crate::whitelisted_caller::() ); whitelist.push(whitelisted_caller_key.into()); // Whitelist the transactional layer. - let transactional_layer_key = $crate::TrackedStorageKey::new( - $crate::frame_support::storage::transactional::TRANSACTION_LEVEL_KEY.into() + let transactional_layer_key = $crate::__private::TrackedStorageKey::new( + $crate::__private::storage::transactional::TRANSACTION_LEVEL_KEY.into() ); whitelist.push(transactional_layer_key); // Whitelist the `:extrinsic_index`. - let extrinsic_index = $crate::TrackedStorageKey::new( - $crate::well_known_keys::EXTRINSIC_INDEX.into() + let extrinsic_index = $crate::__private::TrackedStorageKey::new( + $crate::__private::well_known_keys::EXTRINSIC_INDEX.into() ); whitelist.push(extrinsic_index); // Whitelist the `:intrablock_entropy`. - let intrablock_entropy = $crate::TrackedStorageKey::new( - $crate::well_known_keys::INTRABLOCK_ENTROPY.into() + let intrablock_entropy = $crate::__private::TrackedStorageKey::new( + $crate::__private::well_known_keys::INTRABLOCK_ENTROPY.into() ); whitelist.push(intrablock_entropy); $crate::benchmarking::set_whitelist(whitelist.clone()); - let mut results: $crate::Vec<$crate::BenchmarkResult> = $crate::Vec::new(); + let mut results: $crate::__private::Vec<$crate::BenchmarkResult> = $crate::__private::Vec::new(); // Always do at least one internal repeat... for _ in 0 .. internal_repeats.max(1) { // Always reset the state after the benchmark. - $crate::defer!($crate::benchmarking::wipe_db()); + $crate::__private::defer!($crate::benchmarking::wipe_db()); // Set up the externalities environment for the setup we want to // benchmark. @@ -1082,7 +1082,7 @@ macro_rules! impl_benchmark { >::instance(&selected_benchmark, c, verify)?; // Set the block number to at least 1 so events are deposited. - if $crate::Zero::is_zero(&frame_system::Pallet::::block_number()) { + if $crate::__private::Zero::is_zero(&frame_system::Pallet::::block_number()) { frame_system::Pallet::::set_block_number(1u32.into()); } @@ -1093,14 +1093,14 @@ macro_rules! impl_benchmark { // Access all whitelisted keys to get them into the proof recorder since the // recorder does now have a whitelist. for key in &whitelist { - $crate::frame_support::storage::unhashed::get_raw(&key.key); + $crate::__private::storage::unhashed::get_raw(&key.key); } // Reset the read/write counter so we don't count operations in the setup process. $crate::benchmarking::reset_read_write_count(); // Time the extrinsic logic. - $crate::log::trace!( + $crate::__private::log::trace!( target: "benchmark", "Start Benchmark: {} ({:?}) verify {}", extrinsic, @@ -1125,29 +1125,29 @@ macro_rules! impl_benchmark { // Commit the changes to get proper write count $crate::benchmarking::commit_db(); - $crate::log::trace!( + $crate::__private::log::trace!( target: "benchmark", "End Benchmark: {} ns", elapsed_extrinsic ); let read_write_count = $crate::benchmarking::read_write_count(); - $crate::log::trace!( + $crate::__private::log::trace!( target: "benchmark", "Read/Write Count {:?}", read_write_count ); - $crate::log::trace!( + $crate::__private::log::trace!( target: "benchmark", "Proof sizes: before {:?} after {:?} diff {}", &start_pov, &end_pov, &diff_pov ); // Time the storage root recalculation. let start_storage_root = $crate::benchmarking::current_time(); - $crate::storage_root($crate::StateVersion::V1); + $crate::__private::storage_root($crate::__private::StateVersion::V1); let finish_storage_root = $crate::benchmarking::current_time(); let elapsed_storage_root = finish_storage_root - start_storage_root; let skip_meta = [ $( stringify!($name_skip_meta).as_ref() ),* ]; let read_and_written_keys = if skip_meta.contains(&extrinsic) { - $crate::vec![(b"Skipped Metadata".to_vec(), 0, 0, false)] + $crate::__private::vec![(b"Skipped Metadata".to_vec(), 0, 0, false)] } else { $crate::benchmarking::get_read_and_written_keys() }; @@ -1185,11 +1185,11 @@ macro_rules! impl_benchmark { /// author chooses not to implement benchmarks. #[allow(unused)] fn test_bench_by_name(name: &[u8]) -> Result<(), $crate::BenchmarkError> { - let name = $crate::str::from_utf8(name) + let name = $crate::__private::str::from_utf8(name) .map_err(|_| -> $crate::BenchmarkError { "`name` is not a valid utf8 string!".into() })?; match name { $( stringify!($name) => { - $crate::paste::paste! { Self::[< test_benchmark_ $name >]() } + $crate::__private::paste::paste! { Self::[< test_benchmark_ $name >]() } } )* _ => Err("Could not find test for requested benchmark.".into()), } @@ -1211,7 +1211,7 @@ macro_rules! impl_benchmark_test { { $( $instance:ident: $instance_bound:tt )? } $name:ident ) => { - $crate::paste::item! { + $crate::__private::paste::item! { #[cfg(test)] impl, $instance: $instance_bound )? > Pallet @@ -1225,10 +1225,10 @@ macro_rules! impl_benchmark_test { >::components(&selected_benchmark); let execute_benchmark = | - c: $crate::Vec<($crate::BenchmarkParameter, u32)> + c: $crate::__private::Vec<($crate::BenchmarkParameter, u32)> | -> Result<(), $crate::BenchmarkError> { // Always reset the state after the benchmark. - $crate::defer!($crate::benchmarking::wipe_db()); + $crate::__private::defer!($crate::benchmarking::wipe_db()); // Set up the benchmark, return execution + verification function. let closure_to_verify = < @@ -1236,7 +1236,7 @@ macro_rules! impl_benchmark_test { >::instance(&selected_benchmark, &c, true)?; // Set the block number to at least 1 so events are deposited. - if $crate::Zero::is_zero(&frame_system::Pallet::::block_number()) { + if $crate::__private::Zero::is_zero(&frame_system::Pallet::::block_number()) { frame_system::Pallet::::set_block_number(1u32.into()); } @@ -1266,7 +1266,7 @@ macro_rules! impl_benchmark_test { // and up to num_values-2 more equidistant values in between. // For 0..10 and num_values=6 this would mean: [0, 2, 4, 6, 8, 10] - let mut values = $crate::vec![low]; + let mut values = $crate::__private::vec![low]; let diff = (high - low).min(num_values - 1); let slope = (high - low) as f32 / diff as f32; @@ -1278,7 +1278,7 @@ macro_rules! impl_benchmark_test { for component_value in values { // Select the max value for all the other components. - let c: $crate::Vec<($crate::BenchmarkParameter, u32)> = components + let c: $crate::__private::Vec<($crate::BenchmarkParameter, u32)> = components .iter() .map(|(n, _, h)| if *n == name { @@ -1684,7 +1684,7 @@ macro_rules! impl_test_function { Err(err) => { println!( "{}: {:?}", - $crate::str::from_utf8(benchmark_name) + $crate::__private::str::from_utf8(benchmark_name) .expect("benchmark name is always a valid string!"), err, ); @@ -1695,7 +1695,7 @@ macro_rules! impl_test_function { $crate::BenchmarkError::Stop(err) => { println!( "{}: {:?}", - $crate::str::from_utf8(benchmark_name) + $crate::__private::str::from_utf8(benchmark_name) .expect("benchmark name is always a valid string!"), err, ); @@ -1703,25 +1703,25 @@ macro_rules! impl_test_function { }, $crate::BenchmarkError::Override(_) => { // This is still considered a success condition. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark error overrided - {}", - $crate::str::from_utf8(benchmark_name) + $crate::__private::str::from_utf8(benchmark_name) .expect("benchmark name is always a valid string!"), ); }, $crate::BenchmarkError::Skip => { // This is considered a success condition. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark error skipped - {}", - $crate::str::from_utf8(benchmark_name) + $crate::__private::str::from_utf8(benchmark_name) .expect("benchmark name is always a valid string!"), ); } $crate::BenchmarkError::Weightless => { // This is considered a success condition. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark weightless skipped - {}", - $crate::str::from_utf8(benchmark_name) + $crate::__private::str::from_utf8(benchmark_name) .expect("benchmark name is always a valid string!"), ); } @@ -1777,7 +1777,7 @@ pub fn show_benchmark_debug_info( /// For values that should be skipped entirely, we can just pass `key.into()`. For example: /// /// ``` -/// use frame_benchmarking::TrackedStorageKey; +/// use sp_storage::TrackedStorageKey; /// let whitelist: Vec = vec![ /// // Block Number /// array_bytes::hex_into_unchecked("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac"), @@ -1850,13 +1850,13 @@ macro_rules! add_benchmark { Ok(results) => Some(results), Err($crate::BenchmarkError::Override(mut result)) => { // Insert override warning as the first storage key. - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark error overrided - {}", - $crate::str::from_utf8(benchmark) + $crate::__private::str::from_utf8(benchmark) .expect("benchmark name is always a valid string!") ); result.keys.insert(0, (b"Benchmark Override".to_vec(), 0, 0, false)); - Some($crate::vec![result]) + Some($crate::__private::vec![result]) }, Err($crate::BenchmarkError::Stop(e)) => { $crate::show_benchmark_debug_info( @@ -1869,20 +1869,20 @@ macro_rules! add_benchmark { return Err(e.into()) }, Err($crate::BenchmarkError::Skip) => { - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark error skipped - {}", - $crate::str::from_utf8(benchmark) + $crate::__private::str::from_utf8(benchmark) .expect("benchmark name is always a valid string!") ); None }, Err($crate::BenchmarkError::Weightless) => { - $crate::log::error!( + $crate::__private::log::error!( "WARNING: benchmark weightless skipped - {}", - $crate::str::from_utf8(benchmark) + $crate::__private::str::from_utf8(benchmark) .expect("benchmark name is always a valid string!") ); - Some(vec![$crate::BenchmarkResult { + Some($crate::__private::vec![$crate::BenchmarkResult { components: selected_components.clone(), ..Default::default() }]) diff --git a/frame/bounties/Cargo.toml b/frame/bounties/Cargo.toml index 950284e26824e..38a7216e8ddf7 100644 --- a/frame/bounties/Cargo.toml +++ b/frame/bounties/Cargo.toml @@ -31,20 +31,20 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "pallet-treasury/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -52,12 +52,12 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-treasury/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/broker/Cargo.toml b/frame/broker/Cargo.toml new file mode 100644 index 0000000000000..daa2426b2c34a --- /dev/null +++ b/frame/broker/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-broker" +version = "0.1.0" +description = "Brokerage tool for managing Polkadot Core scheduling" +authors = ["Parity Technologies "] +homepage = "https://substrate.io" +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/paritytech/substrate" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ "derive"] } +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } +bitvec = "1" +sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } +sp-arithmetic = { version = "16.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-core = { version = "21.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } + +[dev-dependencies] +sp-io = { version = "23.0.0", path = "../../primitives/io" } + +[features] +default = [ "std" ] + +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] + +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] + +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/frame/broker/README.md b/frame/broker/README.md new file mode 100644 index 0000000000000..65b6179863e3d --- /dev/null +++ b/frame/broker/README.md @@ -0,0 +1,26 @@ +# Pallet Broker + +Brokerage tool for managing Polkadot Core scheduling. + +Properly described in RFC-0001 Agile Coretime. + +## Implemnentation Specifics + +### Core Mask Bits + +This is 1/80th of a Polkadot Core per timeslice. Assuming timeslices are 80 blocks, then this +indicates usage of a single core one time over a timeslice. + +### The Sale + +```nocompile + 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 +-------------------------------------------------------- +< interlude > + < sale > + ... of which ... + < descending-price >< fixed-price > + | <-------\ +price fixed, unsold assigned to instapool, system cores reserved -/ +``` diff --git a/frame/broker/src/adapt_price.rs b/frame/broker/src/adapt_price.rs new file mode 100644 index 0000000000000..8266625687a23 --- /dev/null +++ b/frame/broker/src/adapt_price.rs @@ -0,0 +1,84 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![deny(missing_docs)] + +use crate::CoreIndex; +use sp_arithmetic::{traits::One, FixedU64}; + +/// Type for determining how to set price. +pub trait AdaptPrice { + /// Return the factor by which the regular price must be multiplied during the leadin period. + /// + /// - `when`: The amount through the leadin period; between zero and one. + fn leadin_factor_at(when: FixedU64) -> FixedU64; + /// Return the correction factor by which the regular price must be multiplied based on market + /// performance. + /// + /// - `sold`: The number of cores sold. + /// - `target`: The target number of cores to be sold (must be larger than zero). + /// - `limit`: The maximum number of cores to be sold. + fn adapt_price(sold: CoreIndex, target: CoreIndex, limit: CoreIndex) -> FixedU64; +} + +impl AdaptPrice for () { + fn leadin_factor_at(_: FixedU64) -> FixedU64 { + FixedU64::one() + } + fn adapt_price(_: CoreIndex, _: CoreIndex, _: CoreIndex) -> FixedU64 { + FixedU64::one() + } +} + +/// Simple implementation of `AdaptPrice` giving a monotonic leadin and a linear price change based +/// on cores sold. +pub struct Linear; +impl AdaptPrice for Linear { + fn leadin_factor_at(when: FixedU64) -> FixedU64 { + FixedU64::from(2) - when + } + fn adapt_price(sold: CoreIndex, target: CoreIndex, limit: CoreIndex) -> FixedU64 { + if sold <= target { + FixedU64::from_rational(sold.into(), target.into()) + } else { + FixedU64::one() + + FixedU64::from_rational((sold - target).into(), (limit - target).into()) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn linear_no_panic() { + for limit in 0..10 { + for target in 1..10 { + for sold in 0..=limit { + let price = Linear::adapt_price(sold, target, limit); + + if sold > target { + assert!(price > FixedU64::one()); + } else { + assert!(price <= FixedU64::one()); + } + } + } + } + } +} diff --git a/frame/broker/src/benchmarking.rs b/frame/broker/src/benchmarking.rs new file mode 100644 index 0000000000000..663bf2f466cf3 --- /dev/null +++ b/frame/broker/src/benchmarking.rs @@ -0,0 +1,858 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use crate::{CoreAssignment::Task, Pallet as Broker}; +use frame_benchmarking::v2::*; +use frame_support::{ + storage::bounded_vec::BoundedVec, + traits::{ + fungible::{Inspect, Mutate}, + EnsureOrigin, Hooks, + }, +}; +use frame_system::{Pallet as System, RawOrigin}; +use sp_arithmetic::{traits::Zero, Perbill}; +use sp_core::Get; +use sp_runtime::Saturating; +use sp_std::{vec, vec::Vec}; + +const SEED: u32 = 0; +const MAX_CORE_COUNT: u16 = 1_000; + +fn assert_last_event(generic_event: ::RuntimeEvent) { + frame_system::Pallet::::assert_last_event(generic_event.into()); +} + +fn new_config_record() -> ConfigRecordOf { + ConfigRecord { + advance_notice: 2u32.into(), + interlude_length: 1u32.into(), + leadin_length: 1u32.into(), + ideal_bulk_proportion: Default::default(), + limit_cores_offered: None, + region_length: 3, + renewal_bump: Perbill::from_percent(10), + contribution_timeout: 5, + } +} + +fn new_schedule() -> Schedule { + // Max items for worst case + let mut items = Vec::new(); + for i in 0..CORE_MASK_BITS { + items.push(ScheduleItem { + assignment: Task(i.try_into().unwrap()), + mask: CoreMask::complete(), + }); + } + Schedule::truncate_from(items) +} + +fn setup_reservations(n: u32) { + let schedule = new_schedule(); + + Reservations::::put(BoundedVec::try_from(vec![schedule.clone(); n as usize]).unwrap()); +} + +fn setup_leases(n: u32, task: u32, until: u32) { + Leases::::put( + BoundedVec::try_from(vec![LeaseRecordItem { task, until: until.into() }; n as usize]) + .unwrap(), + ); +} + +fn advance_to(b: u32) { + while System::::block_number() < b.into() { + System::::set_block_number(System::::block_number().saturating_add(1u32.into())); + Broker::::on_initialize(System::::block_number()); + } +} + +fn setup_and_start_sale() -> Result { + Configuration::::put(new_config_record::()); + + // Assume Reservations to be filled for worst case + setup_reservations::(T::MaxReservedCores::get()); + + // Assume Leases to be filled for worst case + setup_leases::(T::MaxLeasedCores::get(), 1, 10); + + Broker::::do_start_sales(10u32.into(), MAX_CORE_COUNT.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + Ok(T::MaxReservedCores::get() + .saturating_add(T::MaxLeasedCores::get()) + .try_into() + .unwrap()) +} + +#[benchmarks] +mod benches { + use super::*; + use crate::Finality::*; + + #[benchmark] + fn configure() -> Result<(), BenchmarkError> { + let config = new_config_record::(); + + let origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, config.clone()); + + assert_eq!(Configuration::::get(), Some(config)); + + Ok(()) + } + + #[benchmark] + fn reserve() -> Result<(), BenchmarkError> { + let schedule = new_schedule(); + + // Assume Reservations to be almost filled for worst case + setup_reservations::(T::MaxReservedCores::get().saturating_sub(1)); + + let origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, schedule); + + assert_eq!(Reservations::::get().len(), T::MaxReservedCores::get() as usize); + + Ok(()) + } + + #[benchmark] + fn unreserve() -> Result<(), BenchmarkError> { + // Assume Reservations to be filled for worst case + setup_reservations::(T::MaxReservedCores::get()); + + let origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, 0); + + assert_eq!( + Reservations::::get().len(), + T::MaxReservedCores::get().saturating_sub(1) as usize + ); + + Ok(()) + } + + #[benchmark] + fn set_lease() -> Result<(), BenchmarkError> { + let task = 1u32; + let until = 10u32.into(); + + // Assume Leases to be almost filled for worst case + setup_leases::(T::MaxLeasedCores::get().saturating_sub(1), task, until); + + let origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, task, until); + + assert_eq!(Leases::::get().len(), T::MaxLeasedCores::get() as usize); + + Ok(()) + } + + #[benchmark] + fn start_sales(n: Linear<0, { MAX_CORE_COUNT.into() }>) -> Result<(), BenchmarkError> { + Configuration::::put(new_config_record::()); + + // Assume Reservations to be filled for worst case + setup_reservations::(T::MaxReservedCores::get()); + + // Assume Leases to be filled for worst case + setup_leases::(T::MaxLeasedCores::get(), 1, 10); + + let initial_price = 10u32.into(); + + let origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, initial_price, n.try_into().unwrap()); + + assert!(SaleInfo::::get().is_some()); + assert_last_event::( + Event::SaleInitialized { + sale_start: 2u32.into(), + leadin_length: 1u32.into(), + start_price: 20u32.into(), + regular_price: 10u32.into(), + region_begin: 4, + region_end: 7, + ideal_cores_sold: 0, + cores_offered: n + .saturating_sub(T::MaxReservedCores::get()) + .saturating_sub(T::MaxLeasedCores::get()) + .try_into() + .unwrap(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn purchase() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), 10u32.into()); + + assert_eq!(SaleInfo::::get().unwrap().sellout_price, Some(10u32.into())); + assert_last_event::( + Event::Purchased { + who: caller, + region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + price: 10u32.into(), + duration: 3u32.into(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn renew() -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(20u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + Broker::::do_assign(region, None, 1001, Final) + .map_err(|_| BenchmarkError::Weightless)?; + + advance_to::(6); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region.core); + + let id = AllowedRenewalId { core: region.core, when: 10 }; + assert!(AllowedRenewals::::get(id).is_some()); + + Ok(()) + } + + #[benchmark] + fn transfer() -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + let recipient: T::AccountId = account("recipient", 0, SEED); + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), region, recipient.clone()); + + assert_last_event::( + Event::Transferred { + region_id: region, + old_owner: caller, + owner: recipient, + duration: 3u32.into(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn partition() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region, 2); + + assert_last_event::( + Event::Partitioned { + old_region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + new_region_ids: ( + RegionId { begin: 4, core, mask: CoreMask::complete() }, + RegionId { begin: 6, core, mask: CoreMask::complete() }, + ), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn interlace() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region, 0x00000_fffff_fffff_00000.into()); + + assert_last_event::( + Event::Interlaced { + old_region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + new_region_ids: ( + RegionId { begin: 4, core, mask: 0x00000_fffff_fffff_00000.into() }, + RegionId { + begin: 4, + core, + mask: CoreMask::complete() ^ 0x00000_fffff_fffff_00000.into(), + }, + ), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn assign() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region, 1000, Provisional); + + let workplan_key = (region.begin, region.core); + assert!(Workplan::::get(workplan_key).is_some()); + + assert!(Regions::::get(region).is_some()); + + assert_last_event::( + Event::Assigned { + region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + task: 1000, + duration: 3u32.into(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn pool() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + let recipient: T::AccountId = account("recipient", 0, SEED); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region, recipient, Final); + + let workplan_key = (region.begin, region.core); + assert!(Workplan::::get(workplan_key).is_some()); + + assert_last_event::( + Event::Pooled { + region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + duration: 3u32.into(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn claim_revenue( + m: Linear<1, { new_config_record::().region_length }>, + ) -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + T::Currency::set_balance( + &Broker::::account_id(), + T::Currency::minimum_balance().saturating_add(200u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + let recipient: T::AccountId = account("recipient", 0, SEED); + T::Currency::set_balance(&recipient.clone(), T::Currency::minimum_balance()); + + Broker::::do_pool(region, None, recipient.clone(), Final) + .map_err(|_| BenchmarkError::Weightless)?; + + let revenue = 10u32.into(); + InstaPoolHistory::::insert( + region.begin, + InstaPoolHistoryRecord { + private_contributions: 4u32.into(), + system_contributions: 3u32.into(), + maybe_payout: Some(revenue), + }, + ); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region, m); + + assert!(InstaPoolHistory::::get(region.begin).is_none()); + assert_last_event::( + Event::RevenueClaimPaid { + who: recipient, + amount: 200u32.into(), + next: if m < new_config_record::().region_length { + Some(RegionId { begin: 4.saturating_add(m), core, mask: CoreMask::complete() }) + } else { + None + }, + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn purchase_credit() -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(30u32.into()), + ); + T::Currency::set_balance(&Broker::::account_id(), T::Currency::minimum_balance()); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + let recipient: T::AccountId = account("recipient", 0, SEED); + + Broker::::do_pool(region, None, recipient, Final) + .map_err(|_| BenchmarkError::Weightless)?; + + let beneficiary: RelayAccountIdOf = account("beneficiary", 0, SEED); + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), 20u32.into(), beneficiary.clone()); + + assert_last_event::( + Event::CreditPurchased { who: caller, beneficiary, amount: 20u32.into() }.into(), + ); + + Ok(()) + } + + #[benchmark] + fn drop_region() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + advance_to::(12); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region); + + assert_last_event::( + Event::RegionDropped { + region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + duration: 3u32.into(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn drop_contribution() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(10u32.into()), + ); + + let region = Broker::::do_purchase(caller.clone(), 10u32.into()) + .map_err(|_| BenchmarkError::Weightless)?; + + let recipient: T::AccountId = account("recipient", 0, SEED); + + Broker::::do_pool(region, None, recipient, Final) + .map_err(|_| BenchmarkError::Weightless)?; + + advance_to::(26); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), region); + + assert_last_event::( + Event::ContributionDropped { + region_id: RegionId { begin: 4, core, mask: CoreMask::complete() }, + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn drop_history() -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + let when = 5u32.into(); + let revenue = 10u32.into(); + + advance_to::(25); + + let caller: T::AccountId = whitelisted_caller(); + InstaPoolHistory::::insert( + when, + InstaPoolHistoryRecord { + private_contributions: 4u32.into(), + system_contributions: 3u32.into(), + maybe_payout: Some(revenue), + }, + ); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), when); + + assert!(InstaPoolHistory::::get(when).is_none()); + assert_last_event::(Event::HistoryDropped { when, revenue }.into()); + + Ok(()) + } + + #[benchmark] + fn drop_renewal() -> Result<(), BenchmarkError> { + let core = setup_and_start_sale::()?; + let when = 5u32.into(); + + advance_to::(10); + + let id = AllowedRenewalId { core, when }; + let record = AllowedRenewalRecord { + price: 1u32.into(), + completion: CompletionStatus::Complete(new_schedule()), + }; + AllowedRenewals::::insert(id, record); + + let caller: T::AccountId = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), core, when); + + assert!(AllowedRenewals::::get(id).is_none()); + assert_last_event::(Event::AllowedRenewalDropped { core, when }.into()); + + Ok(()) + } + + #[benchmark] + fn request_core_count(n: Linear<0, { MAX_CORE_COUNT.into() }>) -> Result<(), BenchmarkError> { + let admin_origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + #[extrinsic_call] + _(admin_origin as T::RuntimeOrigin, n.try_into().unwrap()); + + assert_last_event::( + Event::CoreCountRequested { core_count: n.try_into().unwrap() }.into(), + ); + + Ok(()) + } + + #[benchmark] + fn process_core_count(n: Linear<0, { MAX_CORE_COUNT.into() }>) -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + + let core_count = n.try_into().unwrap(); + + ::ensure_notify_core_count(core_count); + + let mut status = Status::::get().ok_or(BenchmarkError::Weightless)?; + + #[block] + { + Broker::::process_core_count(&mut status); + } + + assert_last_event::(Event::CoreCountChanged { core_count }.into()); + + Ok(()) + } + + #[benchmark] + fn process_revenue() -> Result<(), BenchmarkError> { + setup_and_start_sale::()?; + + advance_to::(2); + + let caller: T::AccountId = whitelisted_caller(); + T::Currency::set_balance( + &caller.clone(), + T::Currency::minimum_balance().saturating_add(30u32.into()), + ); + T::Currency::set_balance(&Broker::::account_id(), T::Currency::minimum_balance()); + + ::ensure_notify_revenue_info(10u32.into(), 10u32.into()); + + InstaPoolHistory::::insert( + 4u32, + InstaPoolHistoryRecord { + private_contributions: 1u32.into(), + system_contributions: 9u32.into(), + maybe_payout: None, + }, + ); + + #[block] + { + Broker::::process_revenue(); + } + + assert_last_event::( + Event::ClaimsReady { + when: 4u32.into(), + system_payout: 9u32.into(), + private_payout: 1u32.into(), + } + .into(), + ); + + Ok(()) + } + + #[benchmark] + fn rotate_sale(n: Linear<0, { MAX_CORE_COUNT.into() }>) { + let core_count = n.try_into().unwrap(); + let config = new_config_record::(); + + let now = frame_system::Pallet::::block_number(); + let price = 10u32.into(); + let commit_timeslice = Broker::::latest_timeslice_ready_to_commit(&config); + let sale = SaleInfoRecordOf:: { + sale_start: now, + leadin_length: Zero::zero(), + price, + sellout_price: None, + region_begin: commit_timeslice, + region_end: commit_timeslice.saturating_add(config.region_length), + first_core: 0, + ideal_cores_sold: 0, + cores_offered: 0, + cores_sold: 0, + }; + + let status = StatusRecord { + core_count, + private_pool_size: 0, + system_pool_size: 0, + last_committed_timeslice: commit_timeslice.saturating_sub(1), + last_timeslice: Broker::::current_timeslice(), + }; + + // Assume Reservations to be filled for worst case + setup_reservations::(T::MaxReservedCores::get()); + + // Assume Leases to be filled for worst case + setup_leases::(T::MaxLeasedCores::get(), 1, 10); + + #[block] + { + Broker::::rotate_sale(sale, &config, &status); + } + + assert!(SaleInfo::::get().is_some()); + assert_last_event::( + Event::SaleInitialized { + sale_start: 2u32.into(), + leadin_length: 1u32.into(), + start_price: 20u32.into(), + regular_price: 10u32.into(), + region_begin: 4, + region_end: 7, + ideal_cores_sold: 0, + cores_offered: n + .saturating_sub(T::MaxReservedCores::get()) + .saturating_sub(T::MaxLeasedCores::get()) + .try_into() + .unwrap(), + } + .into(), + ); + } + + #[benchmark] + fn process_pool() { + let when = 10u32.into(); + let private_pool_size = 5u32.into(); + let system_pool_size = 4u32.into(); + + let config = new_config_record::(); + let commit_timeslice = Broker::::latest_timeslice_ready_to_commit(&config); + let mut status = StatusRecord { + core_count: 5u16.into(), + private_pool_size, + system_pool_size, + last_committed_timeslice: commit_timeslice.saturating_sub(1), + last_timeslice: Broker::::current_timeslice(), + }; + + #[block] + { + Broker::::process_pool(when, &mut status); + } + + assert!(InstaPoolHistory::::get(when).is_some()); + assert_last_event::( + Event::HistoryInitialized { when, private_pool_size, system_pool_size }.into(), + ); + } + + #[benchmark] + fn process_core_schedule() { + let timeslice = 10u32.into(); + let core = 5u16.into(); + let rc_begin = 1u32.into(); + + Workplan::::insert((timeslice, core), new_schedule()); + + #[block] + { + Broker::::process_core_schedule(timeslice, rc_begin, core); + } + + assert_eq!(Workload::::get(core).len(), CORE_MASK_BITS); + + let mut assignment: Vec<(CoreAssignment, PartsOf57600)> = vec![]; + for i in 0..CORE_MASK_BITS { + assignment.push((CoreAssignment::Task(i.try_into().unwrap()), 57600)); + } + assert_last_event::(Event::CoreAssigned { core, when: rc_begin, assignment }.into()); + } + + #[benchmark] + fn request_revenue_info_at() { + let current_timeslice = Broker::::current_timeslice(); + let rc_block = T::TimeslicePeriod::get() * current_timeslice.into(); + + #[block] + { + T::Coretime::request_revenue_info_at(rc_block); + } + } + + // Implements a test for each benchmark. Execute with: + // `cargo test -p pallet-broker --features runtime-benchmarks`. + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/broker/src/core_mask.rs b/frame/broker/src/core_mask.rs new file mode 100644 index 0000000000000..b8d045077d828 --- /dev/null +++ b/frame/broker/src/core_mask.rs @@ -0,0 +1,227 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Decode, Encode, MaxEncodedLen}; +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not}; +use scale_info::TypeInfo; +use sp_core::RuntimeDebug; + +/// The number of bits in the `CoreMask`. +pub const CORE_MASK_BITS: usize = 80; + +// TODO: Use BitArr instead; for this, we'll need to ensure Codec is impl'ed for `BitArr`. +#[derive( + Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen, +)] +pub struct CoreMask([u8; 10]); +impl CoreMask { + pub fn void() -> Self { + Self([0u8; 10]) + } + pub fn complete() -> Self { + Self([255u8; 10]) + } + pub fn is_void(&self) -> bool { + &self.0 == &[0u8; 10] + } + pub fn is_complete(&self) -> bool { + &self.0 == &[255u8; 10] + } + pub fn set(&mut self, i: u32) -> Self { + if i < 80 { + self.0[(i / 8) as usize] |= 128 >> (i % 8); + } + *self + } + pub fn clear(&mut self, i: u32) -> Self { + if i < 80 { + self.0[(i / 8) as usize] &= !(128 >> (i % 8)); + } + *self + } + pub fn count_zeros(&self) -> u32 { + self.0.iter().map(|i| i.count_zeros()).sum() + } + pub fn count_ones(&self) -> u32 { + self.0.iter().map(|i| i.count_ones()).sum() + } + pub fn from_chunk(from: u32, to: u32) -> Self { + let mut v = [0u8; 10]; + for i in (from.min(80) as usize)..(to.min(80) as usize) { + v[i / 8] |= 128 >> (i % 8); + } + Self(v) + } +} +impl From for CoreMask { + fn from(x: u128) -> Self { + let mut v = [0u8; 10]; + v.iter_mut().rev().fold(x, |a, i| { + *i = a as u8; + a >> 8 + }); + Self(v) + } +} +impl From for u128 { + fn from(x: CoreMask) -> Self { + x.0.into_iter().fold(0u128, |a, i| a << 8 | i as u128) + } +} +impl BitAnd for CoreMask { + type Output = Self; + fn bitand(mut self, rhs: Self) -> Self { + self.bitand_assign(rhs); + self + } +} +impl BitAndAssign for CoreMask { + fn bitand_assign(&mut self, rhs: Self) { + for i in 0..10 { + self.0[i].bitand_assign(rhs.0[i]); + } + } +} +impl BitOr for CoreMask { + type Output = Self; + fn bitor(mut self, rhs: Self) -> Self { + self.bitor_assign(rhs); + self + } +} +impl BitOrAssign for CoreMask { + fn bitor_assign(&mut self, rhs: Self) { + for i in 0..10 { + self.0[i].bitor_assign(rhs.0[i]); + } + } +} +impl BitXor for CoreMask { + type Output = Self; + fn bitxor(mut self, rhs: Self) -> Self { + self.bitxor_assign(rhs); + self + } +} +impl BitXorAssign for CoreMask { + fn bitxor_assign(&mut self, rhs: Self) { + for i in 0..10 { + self.0[i].bitxor_assign(rhs.0[i]); + } + } +} +impl Not for CoreMask { + type Output = Self; + fn not(self) -> Self { + let mut result = [0u8; 10]; + for i in 0..10 { + result[i] = self.0[i].not(); + } + Self(result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn complete_works() { + assert_eq!(CoreMask::complete(), CoreMask([0xff; 10])); + assert!(CoreMask([0xff; 10]).is_complete()); + for i in 0..80 { + assert!(!CoreMask([0xff; 10]).clear(i).is_complete()); + } + } + + #[test] + fn void_works() { + assert_eq!(CoreMask::void(), CoreMask([0; 10])); + assert!(CoreMask([0; 10]).is_void()); + for i in 0..80 { + assert!(!(CoreMask([0; 10]).set(i).is_void())); + } + } + + #[test] + fn from_works() { + assert!(CoreMask::from(0xfffff_fffff_fffff_fffff).is_complete()); + assert_eq!( + CoreMask::from(0x12345_67890_abcde_f0123), + CoreMask([0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x01, 0x23]), + ); + } + + #[test] + fn into_works() { + assert_eq!(u128::from(CoreMask::complete()), 0xfffff_fffff_fffff_fffff); + assert_eq!( + 0x12345_67890_abcde_f0123u128, + CoreMask([0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x01, 0x23]).into(), + ); + } + + #[test] + fn chunk_works() { + assert_eq!(CoreMask::from_chunk(40, 60), CoreMask::from(0x00000_00000_fffff_00000),); + } + + #[test] + fn bit_or_works() { + assert_eq!( + CoreMask::from(0x02040_a0c0e_d0a0b_0ffff) | CoreMask::from(0x10305_0b0d0_0e0d0_e0000), + CoreMask::from(0x12345_abcde_deadb_effff), + ); + } + + #[test] + fn bit_or_assign_works() { + let mut a = CoreMask::from(0x02040_a0c0e_d0a0b_0ffff); + a |= CoreMask::from(0x10305_0b0d0_0e0d0_e0000); + assert_eq!(a, CoreMask::from(0x12345_abcde_deadb_effff)); + } + + #[test] + fn bit_and_works() { + assert_eq!( + CoreMask::from(0x00000_abcde_deadb_efff0) & CoreMask::from(0x02040_00000_d0a0b_0ff0f), + CoreMask::from(0x00000_00000_d0a0b_0ff00), + ); + } + + #[test] + fn bit_and_assign_works() { + let mut a = CoreMask::from(0x00000_abcde_deadb_efff0); + a &= CoreMask::from(0x02040_00000_d0a0b_0ff0f); + assert_eq!(a, CoreMask::from(0x00000_00000_d0a0b_0ff00)); + } + + #[test] + fn bit_xor_works() { + assert_eq!( + CoreMask::from(0x10010_10010_10010_10010) ^ CoreMask::from(0x01110_01110_01110_01110), + CoreMask::from(0x11100_11100_11100_11100), + ); + } + + #[test] + fn bit_xor_assign_works() { + let mut a = CoreMask::from(0x10010_10010_10010_10010); + a ^= CoreMask::from(0x01110_01110_01110_01110); + assert_eq!(a, CoreMask::from(0x11100_11100_11100_11100)); + } +} diff --git a/frame/broker/src/coretime_interface.rs b/frame/broker/src/coretime_interface.rs new file mode 100644 index 0000000000000..fec40b9fdd7b3 --- /dev/null +++ b/frame/broker/src/coretime_interface.rs @@ -0,0 +1,168 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![deny(missing_docs)] + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::Parameter; +use scale_info::TypeInfo; +use sp_arithmetic::traits::AtLeast32BitUnsigned; +use sp_core::RuntimeDebug; +use sp_std::{fmt::Debug, vec::Vec}; + +/// Index of a Polkadot Core. +pub type CoreIndex = u16; + +/// A Task Id. In general this is called a ParachainId. +pub type TaskId = u32; + +/// Fraction expressed as a nominator with an assumed denominator of 57,600. +pub type PartsOf57600 = u16; + +/// An element to which a core can be assigned. +#[derive( + Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo, MaxEncodedLen, +)] +pub enum CoreAssignment { + /// Core need not be used for anything. + Idle, + /// Core should be used for the Instantaneous Coretime Pool. + Pool, + /// Core should be used to process the given task. + Task(TaskId), +} + +/// Type able to accept Coretime scheduling instructions and provide certain usage information. +/// Generally implemented by the Relay-chain or some means of communicating with it. +/// +/// The trait representation of RFC#5 ``. +pub trait CoretimeInterface { + /// A (Relay-chain-side) account ID. + type AccountId: Parameter; + + /// A (Relay-chain-side) balance. + type Balance: AtLeast32BitUnsigned; + + /// A (Relay-chain-side) block number. + type BlockNumber: AtLeast32BitUnsigned + + Copy + + TypeInfo + + Encode + + Decode + + MaxEncodedLen + + Debug; + + /// Return the latest block number on the Relay-chain. + fn latest() -> Self::BlockNumber; + + /// Requests the Relay-chain to alter the number of schedulable cores to `count`. Under normal + /// operation, the Relay-chain SHOULD send a `notify_core_count(count)` message back. + fn request_core_count(count: CoreIndex); + + /// Requests that the Relay-chain send a `notify_revenue` message back at or soon after + /// Relay-chain block number `when` whose `until` parameter is equal to `when`. + /// + /// `when` may never be greater than the result of `Self::latest()`. + /// The period in to the past which `when` is allowed to be may be limited; if so the limit + /// should be understood on a channel outside of this proposal. In the case that the request + /// cannot be serviced because `when` is too old a block then a `notify_revenue` message must + /// still be returned, but its `revenue` field may be `None`. + fn request_revenue_info_at(when: Self::BlockNumber); + + /// Instructs the Relay-chain to add the `amount` of DOT to the Instantaneous Coretime Market + /// Credit account of `who`. + /// + /// It is expected that Instantaneous Coretime Market Credit on the Relay-chain is NOT + /// transferrable and only redeemable when used to assign cores in the Instantaneous Coretime + /// Pool. + fn credit_account(who: Self::AccountId, amount: Self::Balance); + + /// Instructs the Relay-chain to ensure that the core indexed as `core` is utilised for a number + /// of assignments in specific ratios given by `assignment` starting as soon after `begin` as + /// possible. Core assignments take the form of a `CoreAssignment` value which can either task + /// the core to a `ParaId` value or indicate that the core should be used in the Instantaneous + /// Pool. Each assignment comes with a ratio value, represented as the numerator of the fraction + /// with a denominator of 57,600. + /// + /// If `end_hint` is `Some` and the inner is greater than the current block number, then the + /// Relay-chain should optimize in the expectation of receiving a new `assign_core(core, ...)` + /// message at or prior to the block number of the inner value. Specific functionality should + /// remain unchanged regardless of the `end_hint` value. + fn assign_core( + core: CoreIndex, + begin: Self::BlockNumber, + assignment: Vec<(CoreAssignment, PartsOf57600)>, + end_hint: Option, + ); + + /// Indicate that from this block onwards, the range of acceptable values of the `core` + /// parameter of `assign_core` message is `[0, count)`. `assign_core` will be a no-op if + /// provided with a value for `core` outside of this range. + fn check_notify_core_count() -> Option; + + /// Provide the amount of revenue accumulated from Instantaneous Coretime Sales from Relay-chain + /// block number `last_until` to `until`, not including `until` itself. `last_until` is defined + /// as being the `until` argument of the last `notify_revenue` message sent, or zero for the + /// first call. If `revenue` is `None`, this indicates that the information is no longer + /// available. + /// + /// This explicitly disregards the possibility of multiple parachains requesting and being + /// notified of revenue information. The Relay-chain must be configured to ensure that only a + /// single revenue information destination exists. + fn check_notify_revenue_info() -> Option<(Self::BlockNumber, Self::Balance)>; + + /// Ensure that core count is updated to the provided value. + /// + /// This is only used for benchmarking. + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_core_count(count: u16); + + /// Ensure that revenue information is updated to the provided value. + /// + /// This is only used for benchmarking. + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_revenue_info(when: Self::BlockNumber, revenue: Self::Balance); +} + +impl CoretimeInterface for () { + type AccountId = (); + type Balance = u64; + type BlockNumber = u32; + fn latest() -> Self::BlockNumber { + 0 + } + fn request_core_count(_count: CoreIndex) {} + fn request_revenue_info_at(_when: Self::BlockNumber) {} + fn credit_account(_who: Self::AccountId, _amount: Self::Balance) {} + fn assign_core( + _core: CoreIndex, + _begin: Self::BlockNumber, + _assignment: Vec<(CoreAssignment, PartsOf57600)>, + _end_hint: Option, + ) { + } + fn check_notify_core_count() -> Option { + None + } + fn check_notify_revenue_info() -> Option<(Self::BlockNumber, Self::Balance)> { + None + } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_core_count(_count: u16) {} + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_revenue_info(_when: Self::BlockNumber, _revenue: Self::Balance) {} +} diff --git a/frame/broker/src/dispatchable_impls.rs b/frame/broker/src/dispatchable_impls.rs new file mode 100644 index 0000000000000..7c1d5a786b7cf --- /dev/null +++ b/frame/broker/src/dispatchable_impls.rs @@ -0,0 +1,436 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use frame_support::{ + pallet_prelude::{DispatchResult, *}, + traits::{fungible::Mutate, tokens::Preservation::Expendable, DefensiveResult}, +}; +use sp_arithmetic::traits::{CheckedDiv, Saturating, Zero}; +use sp_runtime::traits::Convert; +use CompletionStatus::{Complete, Partial}; + +impl Pallet { + pub(crate) fn do_configure(config: ConfigRecordOf) -> DispatchResult { + config.validate().map_err(|()| Error::::InvalidConfig)?; + Configuration::::put(config); + Ok(()) + } + + pub(crate) fn do_request_core_count(core_count: CoreIndex) -> DispatchResult { + T::Coretime::request_core_count(core_count); + Self::deposit_event(Event::::CoreCountRequested { core_count }); + Ok(()) + } + + pub(crate) fn do_reserve(workload: Schedule) -> DispatchResult { + let mut r = Reservations::::get(); + let index = r.len() as u32; + r.try_push(workload.clone()).map_err(|_| Error::::TooManyReservations)?; + Reservations::::put(r); + Self::deposit_event(Event::::ReservationMade { index, workload }); + Ok(()) + } + + pub(crate) fn do_unreserve(index: u32) -> DispatchResult { + let mut r = Reservations::::get(); + ensure!(index < r.len() as u32, Error::::UnknownReservation); + let workload = r.remove(index as usize); + Reservations::::put(r); + Self::deposit_event(Event::::ReservationCancelled { index, workload }); + Ok(()) + } + + pub(crate) fn do_set_lease(task: TaskId, until: Timeslice) -> DispatchResult { + let mut r = Leases::::get(); + ensure!(until > Self::current_timeslice(), Error::::AlreadyExpired); + r.try_push(LeaseRecordItem { until, task }) + .map_err(|_| Error::::TooManyLeases)?; + Leases::::put(r); + Self::deposit_event(Event::::Leased { until, task }); + Ok(()) + } + + pub(crate) fn do_start_sales(price: BalanceOf, core_count: CoreIndex) -> DispatchResult { + let config = Configuration::::get().ok_or(Error::::Uninitialized)?; + let commit_timeslice = Self::latest_timeslice_ready_to_commit(&config); + let status = StatusRecord { + core_count, + private_pool_size: 0, + system_pool_size: 0, + last_committed_timeslice: commit_timeslice.saturating_sub(1), + last_timeslice: Self::current_timeslice(), + }; + let now = frame_system::Pallet::::block_number(); + let dummy_sale = SaleInfoRecord { + sale_start: now, + leadin_length: Zero::zero(), + price, + sellout_price: None, + region_begin: commit_timeslice, + region_end: commit_timeslice.saturating_add(config.region_length), + first_core: 0, + ideal_cores_sold: 0, + cores_offered: 0, + cores_sold: 0, + }; + Self::deposit_event(Event::::SalesStarted { price, core_count }); + Self::rotate_sale(dummy_sale, &config, &status); + Status::::put(&status); + Ok(()) + } + + pub(crate) fn do_purchase( + who: T::AccountId, + price_limit: BalanceOf, + ) -> Result { + let status = Status::::get().ok_or(Error::::Uninitialized)?; + let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?; + ensure!(sale.first_core < status.core_count, Error::::Unavailable); + ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut); + let now = frame_system::Pallet::::block_number(); + ensure!(now > sale.sale_start, Error::::TooEarly); + let price = Self::sale_price(&sale, now); + ensure!(price_limit >= price, Error::::Overpriced); + + Self::charge(&who, price)?; + let core = sale.first_core.saturating_add(sale.cores_sold); + sale.cores_sold.saturating_inc(); + if sale.cores_sold <= sale.ideal_cores_sold || sale.sellout_price.is_none() { + sale.sellout_price = Some(price); + } + SaleInfo::::put(&sale); + let id = Self::issue(core, sale.region_begin, sale.region_end, who.clone(), Some(price)); + let duration = sale.region_end.saturating_sub(sale.region_begin); + Self::deposit_event(Event::Purchased { who, region_id: id, price, duration }); + Ok(id) + } + + /// Must be called on a core in `AllowedRenewals` whose value is a timeslice equal to the + /// current sale status's `region_end`. + pub(crate) fn do_renew(who: T::AccountId, core: CoreIndex) -> Result { + let config = Configuration::::get().ok_or(Error::::Uninitialized)?; + let status = Status::::get().ok_or(Error::::Uninitialized)?; + let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?; + ensure!(sale.first_core < status.core_count, Error::::Unavailable); + ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut); + + let renewal_id = AllowedRenewalId { core, when: sale.region_begin }; + let record = AllowedRenewals::::get(renewal_id).ok_or(Error::::NotAllowed)?; + let workload = + record.completion.drain_complete().ok_or(Error::::IncompleteAssignment)?; + + let old_core = core; + let core = sale.first_core.saturating_add(sale.cores_sold); + Self::charge(&who, record.price)?; + Self::deposit_event(Event::Renewed { + who, + old_core, + core, + price: record.price, + begin: sale.region_begin, + duration: sale.region_end.saturating_sub(sale.region_begin), + workload: workload.clone(), + }); + + sale.cores_sold.saturating_inc(); + + Workplan::::insert((sale.region_begin, core), &workload); + + let begin = sale.region_end; + let price_cap = record.price + config.renewal_bump * record.price; + let now = frame_system::Pallet::::block_number(); + let price = Self::sale_price(&sale, now).min(price_cap); + let new_record = AllowedRenewalRecord { price, completion: Complete(workload) }; + AllowedRenewals::::remove(renewal_id); + AllowedRenewals::::insert(AllowedRenewalId { core, when: begin }, &new_record); + SaleInfo::::put(&sale); + if let Some(workload) = new_record.completion.drain_complete() { + Self::deposit_event(Event::Renewable { core, price, begin, workload }); + } + Ok(core) + } + + pub(crate) fn do_transfer( + region_id: RegionId, + maybe_check_owner: Option, + new_owner: T::AccountId, + ) -> Result<(), Error> { + let mut region = Regions::::get(®ion_id).ok_or(Error::::UnknownRegion)?; + + if let Some(check_owner) = maybe_check_owner { + ensure!(check_owner == region.owner, Error::::NotOwner); + } + + let old_owner = region.owner; + region.owner = new_owner; + Regions::::insert(®ion_id, ®ion); + let duration = region.end.saturating_sub(region_id.begin); + Self::deposit_event(Event::Transferred { + region_id, + old_owner, + owner: region.owner, + duration, + }); + + Ok(()) + } + + pub(crate) fn do_partition( + region_id: RegionId, + maybe_check_owner: Option, + pivot_offset: Timeslice, + ) -> Result<(RegionId, RegionId), Error> { + let mut region = Regions::::get(®ion_id).ok_or(Error::::UnknownRegion)?; + + if let Some(check_owner) = maybe_check_owner { + ensure!(check_owner == region.owner, Error::::NotOwner); + } + let pivot = region_id.begin.saturating_add(pivot_offset); + ensure!(pivot < region.end, Error::::PivotTooLate); + ensure!(pivot > region_id.begin, Error::::PivotTooEarly); + + region.paid = None; + let new_region_ids = (region_id, RegionId { begin: pivot, ..region_id }); + + Regions::::insert(&new_region_ids.0, &RegionRecord { end: pivot, ..region.clone() }); + Regions::::insert(&new_region_ids.1, ®ion); + Self::deposit_event(Event::Partitioned { old_region_id: region_id, new_region_ids }); + + Ok(new_region_ids) + } + + pub(crate) fn do_interlace( + region_id: RegionId, + maybe_check_owner: Option, + pivot: CoreMask, + ) -> Result<(RegionId, RegionId), Error> { + let region = Regions::::get(®ion_id).ok_or(Error::::UnknownRegion)?; + + if let Some(check_owner) = maybe_check_owner { + ensure!(check_owner == region.owner, Error::::NotOwner); + } + + ensure!((pivot & !region_id.mask).is_void(), Error::::ExteriorPivot); + ensure!(!pivot.is_void(), Error::::VoidPivot); + ensure!(pivot != region_id.mask, Error::::CompletePivot); + + let one = RegionId { mask: pivot, ..region_id }; + Regions::::insert(&one, ®ion); + let other = RegionId { mask: region_id.mask ^ pivot, ..region_id }; + Regions::::insert(&other, ®ion); + + let new_region_ids = (one, other); + Self::deposit_event(Event::Interlaced { old_region_id: region_id, new_region_ids }); + Ok(new_region_ids) + } + + pub(crate) fn do_assign( + region_id: RegionId, + maybe_check_owner: Option, + target: TaskId, + finality: Finality, + ) -> Result<(), Error> { + let config = Configuration::::get().ok_or(Error::::Uninitialized)?; + if let Some((region_id, region)) = Self::utilize(region_id, maybe_check_owner, finality)? { + let workplan_key = (region_id.begin, region_id.core); + let mut workplan = Workplan::::get(&workplan_key).unwrap_or_default(); + // Ensure no previous allocations exist. + workplan.retain(|i| (i.mask & region_id.mask).is_void()); + if workplan + .try_push(ScheduleItem { + mask: region_id.mask, + assignment: CoreAssignment::Task(target), + }) + .is_ok() + { + Workplan::::insert(&workplan_key, &workplan); + } + + let duration = region.end.saturating_sub(region_id.begin); + if duration == config.region_length && finality == Finality::Final { + if let Some(price) = region.paid { + let renewal_id = AllowedRenewalId { core: region_id.core, when: region.end }; + let assigned = match AllowedRenewals::::get(renewal_id) { + Some(AllowedRenewalRecord { completion: Partial(w), price: p }) + if price == p => + w, + _ => CoreMask::void(), + } | region_id.mask; + let workload = + if assigned.is_complete() { Complete(workplan) } else { Partial(assigned) }; + let record = AllowedRenewalRecord { price, completion: workload }; + AllowedRenewals::::insert(&renewal_id, &record); + if let Some(workload) = record.completion.drain_complete() { + Self::deposit_event(Event::Renewable { + core: region_id.core, + price, + begin: region.end, + workload, + }); + } + } + } + Self::deposit_event(Event::Assigned { region_id, task: target, duration }); + } + Ok(()) + } + + pub(crate) fn do_pool( + region_id: RegionId, + maybe_check_owner: Option, + payee: T::AccountId, + finality: Finality, + ) -> Result<(), Error> { + if let Some((region_id, region)) = Self::utilize(region_id, maybe_check_owner, finality)? { + let workplan_key = (region_id.begin, region_id.core); + let mut workplan = Workplan::::get(&workplan_key).unwrap_or_default(); + let duration = region.end.saturating_sub(region_id.begin); + if workplan + .try_push(ScheduleItem { mask: region_id.mask, assignment: CoreAssignment::Pool }) + .is_ok() + { + Workplan::::insert(&workplan_key, &workplan); + let size = region_id.mask.count_ones() as i32; + InstaPoolIo::::mutate(region_id.begin, |a| a.private.saturating_accrue(size)); + InstaPoolIo::::mutate(region.end, |a| a.private.saturating_reduce(size)); + let record = ContributionRecord { length: duration, payee }; + InstaPoolContribution::::insert(®ion_id, record); + } + + Self::deposit_event(Event::Pooled { region_id, duration }); + } + Ok(()) + } + + pub(crate) fn do_claim_revenue( + mut region: RegionId, + max_timeslices: Timeslice, + ) -> DispatchResult { + let mut contribution = + InstaPoolContribution::::take(region).ok_or(Error::::UnknownContribution)?; + let contributed_parts = region.mask.count_ones(); + + Self::deposit_event(Event::RevenueClaimBegun { region, max_timeslices }); + + let mut payout = BalanceOf::::zero(); + let last = region.begin + contribution.length.min(max_timeslices); + for r in region.begin..last { + region.begin = r + 1; + contribution.length.saturating_dec(); + + let Some(mut pool_record) = InstaPoolHistory::::get(r) else { + continue; + }; + let Some(total_payout) = pool_record.maybe_payout else { + break; + }; + let p = total_payout + .saturating_mul(contributed_parts.into()) + .checked_div(&pool_record.private_contributions.into()) + .unwrap_or_default(); + + payout.saturating_accrue(p); + pool_record.private_contributions.saturating_reduce(contributed_parts); + + let remaining_payout = total_payout.saturating_sub(p); + if !remaining_payout.is_zero() && pool_record.private_contributions > 0 { + pool_record.maybe_payout = Some(remaining_payout); + InstaPoolHistory::::insert(r, &pool_record); + } else { + InstaPoolHistory::::remove(r); + } + if !p.is_zero() { + Self::deposit_event(Event::RevenueClaimItem { when: r, amount: p }); + } + } + + if contribution.length > 0 { + InstaPoolContribution::::insert(region, &contribution); + } + T::Currency::transfer(&Self::account_id(), &contribution.payee, payout, Expendable) + .defensive_ok(); + let next = if last < region.begin + contribution.length { Some(region) } else { None }; + Self::deposit_event(Event::RevenueClaimPaid { + who: contribution.payee, + amount: payout, + next, + }); + Ok(()) + } + + pub(crate) fn do_purchase_credit( + who: T::AccountId, + amount: BalanceOf, + beneficiary: RelayAccountIdOf, + ) -> DispatchResult { + T::Currency::transfer(&who, &Self::account_id(), amount, Expendable)?; + let rc_amount = T::ConvertBalance::convert(amount); + T::Coretime::credit_account(beneficiary.clone(), rc_amount); + Self::deposit_event(Event::::CreditPurchased { who, beneficiary, amount }); + Ok(()) + } + + pub(crate) fn do_drop_region(region_id: RegionId) -> DispatchResult { + let status = Status::::get().ok_or(Error::::Uninitialized)?; + let region = Regions::::get(®ion_id).ok_or(Error::::UnknownRegion)?; + ensure!(status.last_committed_timeslice >= region.end, Error::::StillValid); + + Regions::::remove(®ion_id); + let duration = region.end.saturating_sub(region_id.begin); + Self::deposit_event(Event::RegionDropped { region_id, duration }); + Ok(()) + } + + pub(crate) fn do_drop_contribution(region_id: RegionId) -> DispatchResult { + let config = Configuration::::get().ok_or(Error::::Uninitialized)?; + let status = Status::::get().ok_or(Error::::Uninitialized)?; + let contrib = + InstaPoolContribution::::get(®ion_id).ok_or(Error::::UnknownContribution)?; + let end = region_id.begin.saturating_add(contrib.length); + ensure!( + status.last_timeslice >= end.saturating_add(config.contribution_timeout), + Error::::StillValid + ); + InstaPoolContribution::::remove(region_id); + Self::deposit_event(Event::ContributionDropped { region_id }); + Ok(()) + } + + pub(crate) fn do_drop_history(when: Timeslice) -> DispatchResult { + let config = Configuration::::get().ok_or(Error::::Uninitialized)?; + let status = Status::::get().ok_or(Error::::Uninitialized)?; + ensure!(status.last_timeslice > when + config.contribution_timeout, Error::::StillValid); + let record = InstaPoolHistory::::take(when).ok_or(Error::::NoHistory)?; + if let Some(payout) = record.maybe_payout { + let _ = Self::charge(&Self::account_id(), payout); + } + let revenue = record.maybe_payout.unwrap_or_default(); + Self::deposit_event(Event::HistoryDropped { when, revenue }); + Ok(()) + } + + pub(crate) fn do_drop_renewal(core: CoreIndex, when: Timeslice) -> DispatchResult { + let status = Status::::get().ok_or(Error::::Uninitialized)?; + ensure!(status.last_committed_timeslice >= when, Error::::StillValid); + let id = AllowedRenewalId { core, when }; + ensure!(AllowedRenewals::::contains_key(id), Error::::UnknownRenewal); + AllowedRenewals::::remove(id); + Self::deposit_event(Event::AllowedRenewalDropped { core, when }); + Ok(()) + } +} diff --git a/frame/broker/src/lib.rs b/frame/broker/src/lib.rs new file mode 100644 index 0000000000000..4abd041f5f397 --- /dev/null +++ b/frame/broker/src/lib.rs @@ -0,0 +1,784 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] +#![doc = include_str!("../README.md")] + +pub use pallet::*; + +mod adapt_price; +mod benchmarking; +mod core_mask; +mod coretime_interface; +mod dispatchable_impls; +#[cfg(test)] +mod mock; +mod nonfungible_impl; +#[cfg(test)] +mod test_fungibles; +#[cfg(test)] +mod tests; +mod tick_impls; +mod types; +mod utility_impls; + +pub mod weights; +pub use weights::WeightInfo; + +pub use adapt_price::*; +pub use core_mask::*; +pub use coretime_interface::*; +pub use nonfungible_impl::*; +pub use types::*; +pub use utility_impls::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{ + pallet_prelude::{DispatchResult, DispatchResultWithPostInfo, *}, + traits::{ + fungible::{Balanced, Credit, Mutate}, + EnsureOrigin, OnUnbalanced, + }, + PalletId, + }; + use frame_system::pallet_prelude::*; + use sp_runtime::traits::{Convert, ConvertBack}; + use sp_std::vec::Vec; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Weight information for all calls of this pallet. + type WeightInfo: WeightInfo; + + /// Currency used to pay for Coretime. + type Currency: Mutate + Balanced; + + /// The origin test needed for administrating this pallet. + type AdminOrigin: EnsureOrigin; + + /// What to do with any revenues collected from the sale of Coretime. + type OnRevenue: OnUnbalanced>; + + /// Relay chain's Coretime API used to interact with and instruct the low-level scheduling + /// system. + type Coretime: CoretimeInterface; + + /// The algorithm to determine the next price on the basis of market performance. + type PriceAdapter: AdaptPrice; + + /// Reversible conversion from local balance to Relay-chain balance. This will typically be + /// the `Identity`, but provided just in case the chains use different representations. + type ConvertBalance: Convert, RelayBalanceOf> + + ConvertBack, RelayBalanceOf>; + + /// Identifier from which the internal Pot is generated. + #[pallet::constant] + type PalletId: Get; + + /// Number of Relay-chain blocks per timeslice. + #[pallet::constant] + type TimeslicePeriod: Get>; + + /// Maximum number of legacy leases. + #[pallet::constant] + type MaxLeasedCores: Get; + + /// Maximum number of system cores. + #[pallet::constant] + type MaxReservedCores: Get; + } + + /// The current configuration of this pallet. + #[pallet::storage] + pub type Configuration = StorageValue<_, ConfigRecordOf, OptionQuery>; + + /// The Polkadot Core reservations (generally tasked with the maintenance of System Chains). + #[pallet::storage] + pub type Reservations = StorageValue<_, ReservationsRecordOf, ValueQuery>; + + /// The Polkadot Core legacy leases. + #[pallet::storage] + pub type Leases = StorageValue<_, LeasesRecordOf, ValueQuery>; + + /// The current status of miscellaneous subsystems of this pallet. + #[pallet::storage] + pub type Status = StorageValue<_, StatusRecord, OptionQuery>; + + /// The details of the current sale, including its properties and status. + #[pallet::storage] + pub type SaleInfo = StorageValue<_, SaleInfoRecordOf, OptionQuery>; + + /// Records of allowed renewals. + #[pallet::storage] + pub type AllowedRenewals = + StorageMap<_, Twox64Concat, AllowedRenewalId, AllowedRenewalRecordOf, OptionQuery>; + + /// The current (unassigned) Regions. + #[pallet::storage] + pub type Regions = StorageMap<_, Blake2_128Concat, RegionId, RegionRecordOf, OptionQuery>; + + /// The work we plan on having each core do at a particular time in the future. + #[pallet::storage] + pub type Workplan = + StorageMap<_, Twox64Concat, (Timeslice, CoreIndex), Schedule, OptionQuery>; + + /// The current workload of each core. This gets updated with workplan as timeslices pass. + #[pallet::storage] + pub type Workload = StorageMap<_, Twox64Concat, CoreIndex, Schedule, ValueQuery>; + + /// Record of a single contribution to the Instantaneous Coretime Pool. + #[pallet::storage] + pub type InstaPoolContribution = + StorageMap<_, Blake2_128Concat, RegionId, ContributionRecordOf, OptionQuery>; + + /// Record of Coretime entering or leaving the Instantaneous Coretime Pool. + #[pallet::storage] + pub type InstaPoolIo = StorageMap<_, Blake2_128Concat, Timeslice, PoolIoRecord, ValueQuery>; + + /// Total InstaPool rewards for each Timeslice and the number of core parts which contributed. + #[pallet::storage] + pub type InstaPoolHistory = + StorageMap<_, Blake2_128Concat, Timeslice, InstaPoolHistoryRecordOf>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A Region of Bulk Coretime has been purchased. + Purchased { + /// The identity of the purchaser. + who: T::AccountId, + /// The identity of the Region. + region_id: RegionId, + /// The price paid for this Region. + price: BalanceOf, + /// The duration of the Region. + duration: Timeslice, + }, + /// The workload of a core has become renewable. + Renewable { + /// The core whose workload can be renewed. + core: CoreIndex, + /// The price at which the workload can be renewed. + price: BalanceOf, + /// The time at which the workload would recommence of this renewal. The call to renew + /// cannot happen before the beginning of the interlude prior to the sale for regions + /// which begin at this time. + begin: Timeslice, + /// The actual workload which can be renewed. + workload: Schedule, + }, + /// A workload has been renewed. + Renewed { + /// The identity of the renewer. + who: T::AccountId, + /// The price paid for this renewal. + price: BalanceOf, + /// The index of the core on which the `workload` was previously scheduled. + old_core: CoreIndex, + /// The index of the core on which the renewed `workload` has been scheduled. + core: CoreIndex, + /// The time at which the `workload` will begin on the `core`. + begin: Timeslice, + /// The number of timeslices for which this `workload` is newly scheduled. + duration: Timeslice, + /// The workload which was renewed. + workload: Schedule, + }, + /// Ownership of a Region has been transferred. + Transferred { + /// The Region which has been transferred. + region_id: RegionId, + /// The duration of the Region. + duration: Timeslice, + /// The old owner of the Region. + old_owner: T::AccountId, + /// The new owner of the Region. + owner: T::AccountId, + }, + /// A Region has been split into two non-overlapping Regions. + Partitioned { + /// The Region which was split. + old_region_id: RegionId, + /// The new Regions into which it became. + new_region_ids: (RegionId, RegionId), + }, + /// A Region has been converted into two overlapping Regions each of lesser regularity. + Interlaced { + /// The Region which was interlaced. + old_region_id: RegionId, + /// The new Regions into which it became. + new_region_ids: (RegionId, RegionId), + }, + /// A Region has been assigned to a particular task. + Assigned { + /// The Region which was assigned. + region_id: RegionId, + /// The duration of the assignment. + duration: Timeslice, + /// The task to which the Region was assigned. + task: TaskId, + }, + /// A Region has been added to the Instantaneous Coretime Pool. + Pooled { + /// The Region which was added to the Instantaneous Coretime Pool. + region_id: RegionId, + /// The duration of the Region. + duration: Timeslice, + }, + /// A new number of cores has been requested. + CoreCountRequested { + /// The number of cores requested. + core_count: CoreIndex, + }, + /// The number of cores available for scheduling has changed. + CoreCountChanged { + /// The new number of cores available for scheduling. + core_count: CoreIndex, + }, + /// There is a new reservation for a workload. + ReservationMade { + /// The index of the reservation. + index: u32, + /// The workload of the reservation. + workload: Schedule, + }, + /// A reservation for a workload has been cancelled. + ReservationCancelled { + /// The index of the reservation which was cancelled. + index: u32, + /// The workload of the now cancelled reservation. + workload: Schedule, + }, + /// A new sale has been initialized. + SaleInitialized { + /// The local block number at which the sale will/did start. + sale_start: BlockNumberFor, + /// The length in blocks of the Leadin Period (where the price is decreasing). + leadin_length: BlockNumberFor, + /// The price of Bulk Coretime at the beginning of the Leadin Period. + start_price: BalanceOf, + /// The price of Bulk Coretime after the Leadin Period. + regular_price: BalanceOf, + /// The first timeslice of the Regions which are being sold in this sale. + region_begin: Timeslice, + /// The timeslice on which the Regions which are being sold in the sale terminate. + /// (i.e. One after the last timeslice which the Regions control.) + region_end: Timeslice, + /// The number of cores we want to sell, ideally. Selling this amount would result in + /// no change to the price for the next sale. + ideal_cores_sold: CoreIndex, + /// Number of cores which are/have been offered for sale. + cores_offered: CoreIndex, + }, + /// A new lease has been created. + Leased { + /// The task to which a core will be assigned. + task: TaskId, + /// The timeslice contained in the sale period after which this lease will + /// self-terminate (and therefore the earliest timeslice at which the lease may no + /// longer apply). + until: Timeslice, + }, + /// A lease is about to end. + LeaseEnding { + /// The task to which a core was assigned. + task: TaskId, + /// The timeslice at which the task will no longer be scheduled. + when: Timeslice, + }, + /// The sale rotation has been started and a new sale is imminent. + SalesStarted { + /// The nominal price of an Region of Bulk Coretime. + price: BalanceOf, + /// The maximum number of cores which this pallet will attempt to assign. + core_count: CoreIndex, + }, + /// The act of claiming revenue has begun. + RevenueClaimBegun { + /// The region to be claimed for. + region: RegionId, + /// The maximum number of timeslices which should be searched for claimed. + max_timeslices: Timeslice, + }, + /// A particular timeslice has a non-zero claim. + RevenueClaimItem { + /// The timeslice whose claim is being processed. + when: Timeslice, + /// The amount which was claimed at this timeslice. + amount: BalanceOf, + }, + /// A revenue claim has (possibly only in part) been paid. + RevenueClaimPaid { + /// The account to whom revenue has been paid. + who: T::AccountId, + /// The total amount of revenue claimed and paid. + amount: BalanceOf, + /// The next region which should be claimed for the continuation of this contribution. + next: Option, + }, + /// Some Instantaneous Coretime Pool credit has been purchased. + CreditPurchased { + /// The account which purchased the credit. + who: T::AccountId, + /// The Relay-chain account to which the credit will be made. + beneficiary: RelayAccountIdOf, + /// The amount of credit purchased. + amount: BalanceOf, + }, + /// A Region has been dropped due to being out of date. + RegionDropped { + /// The Region which no longer exists. + region_id: RegionId, + /// The duration of the Region. + duration: Timeslice, + }, + /// Some historical Instantaneous Core Pool contribution record has been dropped. + ContributionDropped { + /// The Region whose contribution is no longer exists. + region_id: RegionId, + }, + /// Some historical Instantaneous Core Pool payment record has been initialized. + HistoryInitialized { + /// The timeslice whose history has been initialized. + when: Timeslice, + /// The amount of privately contributed Coretime to the Instantaneous Coretime Pool. + private_pool_size: CoreMaskBitCount, + /// The amount of Coretime contributed to the Instantaneous Coretime Pool by the + /// Polkadot System. + system_pool_size: CoreMaskBitCount, + }, + /// Some historical Instantaneous Core Pool payment record has been dropped. + HistoryDropped { + /// The timeslice whose history is no longer available. + when: Timeslice, + /// The amount of revenue the system has taken. + revenue: BalanceOf, + }, + /// Some historical Instantaneous Core Pool payment record has been ignored because the + /// timeslice was already known. Governance may need to intervene. + HistoryIgnored { + /// The timeslice whose history is was ignored. + when: Timeslice, + /// The amount of revenue which was ignored. + revenue: BalanceOf, + }, + /// Some historical Instantaneous Core Pool Revenue is ready for payout claims. + ClaimsReady { + /// The timeslice whose history is available. + when: Timeslice, + /// The amount of revenue the Polkadot System has already taken. + system_payout: BalanceOf, + /// The total amount of revenue remaining to be claimed. + private_payout: BalanceOf, + }, + /// A Core has been assigned to one or more tasks and/or the Pool on the Relay-chain. + CoreAssigned { + /// The index of the Core which has been assigned. + core: CoreIndex, + /// The Relay-chain block at which this assignment should take effect. + when: RelayBlockNumberOf, + /// The workload to be done on the Core. + assignment: Vec<(CoreAssignment, PartsOf57600)>, + }, + /// Some historical Instantaneous Core Pool payment record has been dropped. + AllowedRenewalDropped { + /// The timeslice whose renewal is no longer available. + when: Timeslice, + /// The core whose workload is no longer available to be renewed for `when`. + core: CoreIndex, + }, + } + + #[pallet::error] + #[derive(PartialEq)] + pub enum Error { + /// The given region identity is not known. + UnknownRegion, + /// The owner of the region is not the origin. + NotOwner, + /// The pivot point of the partition at or after the end of the region. + PivotTooLate, + /// The pivot point of the partition at the beginning of the region. + PivotTooEarly, + /// The pivot mask for the interlacing is not contained within the region's interlace mask. + ExteriorPivot, + /// The pivot mask for the interlacing is void (and therefore unschedulable). + VoidPivot, + /// The pivot mask for the interlacing is complete (and therefore not a strict subset). + CompletePivot, + /// The workplan of the pallet's state is invalid. This indicates a state corruption. + CorruptWorkplan, + /// There is no sale happening currently. + NoSales, + /// The price limit is exceeded. + Overpriced, + /// There are no cores available. + Unavailable, + /// The sale limit has been reached. + SoldOut, + /// The renewal operation is not valid at the current time (it may become valid in the next + /// sale). + WrongTime, + /// Invalid attempt to renew. + NotAllowed, + /// This pallet has not yet been initialized. + Uninitialized, + /// The purchase cannot happen yet as the sale period is yet to begin. + TooEarly, + /// There is no work to be done. + NothingToDo, + /// The maximum amount of reservations has already been reached. + TooManyReservations, + /// The maximum amount of leases has already been reached. + TooManyLeases, + /// The revenue for the Instantaneous Core Sales of this period is not (yet) known and thus + /// this operation cannot proceed. + UnknownRevenue, + /// The identified contribution to the Instantaneous Core Pool is unknown. + UnknownContribution, + /// The workload assigned for renewal is incomplete. This is unexpected and indicates a + /// logic error. + IncompleteAssignment, + /// An item cannot be dropped because it is still valid. + StillValid, + /// The history item does not exist. + NoHistory, + /// No reservation of the given index exists. + UnknownReservation, + /// The renewal record cannot be found. + UnknownRenewal, + /// The lease expiry time has already passed. + AlreadyExpired, + /// The configuration could not be applied because it is invalid. + InvalidConfig, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_now: BlockNumberFor) -> Weight { + Self::do_tick() + } + } + + #[pallet::call(weight(::WeightInfo))] + impl Pallet { + /// Configure the pallet. + /// + /// - `origin`: Must be Root or pass `AdminOrigin`. + /// - `config`: The configuration for this pallet. + #[pallet::call_index(0)] + pub fn configure( + origin: OriginFor, + config: ConfigRecordOf, + ) -> DispatchResultWithPostInfo { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_configure(config)?; + Ok(Pays::No.into()) + } + + /// Reserve a core for a workload. + /// + /// - `origin`: Must be Root or pass `AdminOrigin`. + /// - `workload`: The workload which should be permanently placed on a core. + #[pallet::call_index(1)] + pub fn reserve(origin: OriginFor, workload: Schedule) -> DispatchResultWithPostInfo { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_reserve(workload)?; + Ok(Pays::No.into()) + } + + /// Cancel a reservation for a workload. + /// + /// - `origin`: Must be Root or pass `AdminOrigin`. + /// - `item_index`: The index of the reservation. Usually this will also be the index of the + /// core on which the reservation has been scheduled. However, it is possible that if + /// other cores are reserved or unreserved in the same sale rotation that they won't + /// correspond, so it's better to look up the core properly in the `Reservations` storage. + #[pallet::call_index(2)] + pub fn unreserve(origin: OriginFor, item_index: u32) -> DispatchResultWithPostInfo { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_unreserve(item_index)?; + Ok(Pays::No.into()) + } + + /// Reserve a core for a single task workload for a limited period. + /// + /// In the interlude and sale period where Bulk Coretime is sold for the period immediately + /// after `until`, then the same workload may be renewed. + /// + /// - `origin`: Must be Root or pass `AdminOrigin`. + /// - `task`: The workload which should be placed on a core. + /// - `until`: The timeslice now earlier than which `task` should be placed as a workload on + /// a core. + #[pallet::call_index(3)] + pub fn set_lease( + origin: OriginFor, + task: TaskId, + until: Timeslice, + ) -> DispatchResultWithPostInfo { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_set_lease(task, until)?; + Ok(Pays::No.into()) + } + + /// Begin the Bulk Coretime sales rotation. + /// + /// - `origin`: Must be Root or pass `AdminOrigin`. + /// - `initial_price`: The price of Bulk Coretime in the first sale. + /// - `core_count`: The number of cores which can be allocated. + #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::start_sales((*core_count).into()))] + pub fn start_sales( + origin: OriginFor, + initial_price: BalanceOf, + core_count: CoreIndex, + ) -> DispatchResultWithPostInfo { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_start_sales(initial_price, core_count)?; + Ok(Pays::No.into()) + } + + /// Purchase Bulk Coretime in the ongoing Sale. + /// + /// - `origin`: Must be a Signed origin with at least enough funds to pay the current price + /// of Bulk Coretime. + /// - `price_limit`: An amount no more than which should be paid. + #[pallet::call_index(5)] + pub fn purchase( + origin: OriginFor, + price_limit: BalanceOf, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + Self::do_purchase(who, price_limit)?; + Ok(Pays::No.into()) + } + + /// Renew Bulk Coretime in the ongoing Sale or its prior Interlude Period. + /// + /// - `origin`: Must be a Signed origin with at least enough funds to pay the renewal price + /// of the core. + /// - `core`: The core which should be renewed. + #[pallet::call_index(6)] + pub fn renew(origin: OriginFor, core: CoreIndex) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + Self::do_renew(who, core)?; + Ok(Pays::No.into()) + } + + /// Transfer a Bulk Coretime Region to a new owner. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `region_id`: The Region whose ownership should change. + /// - `new_owner`: The new owner for the Region. + #[pallet::call_index(7)] + pub fn transfer( + origin: OriginFor, + region_id: RegionId, + new_owner: T::AccountId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_transfer(region_id, Some(who), new_owner)?; + Ok(()) + } + + /// Split a Bulk Coretime Region into two non-overlapping Regions at a particular time into + /// the region. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `region_id`: The Region which should be partitioned into two non-overlapping Regions. + /// - `pivot`: The offset in time into the Region at which to make the split. + #[pallet::call_index(8)] + pub fn partition( + origin: OriginFor, + region_id: RegionId, + pivot: Timeslice, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_partition(region_id, Some(who), pivot)?; + Ok(()) + } + + /// Split a Bulk Coretime Region into two wholly-overlapping Regions with complementary + /// interlace masks which together make up the original Region's interlace mask. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `region_id`: The Region which should become two interlaced Regions of incomplete + /// regularity. + /// - `pivot`: The interlace mask of on of the two new regions (the other it its partial + /// complement). + #[pallet::call_index(9)] + pub fn interlace( + origin: OriginFor, + region_id: RegionId, + pivot: CoreMask, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_interlace(region_id, Some(who), pivot)?; + Ok(()) + } + + /// Assign a Bulk Coretime Region to a task. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `region_id`: The Region which should be assigned to the task. + /// - `task`: The task to assign. + /// - `finality`: Indication of whether this assignment is final (in which case it may be + /// eligible for renewal) or provisional (in which case it may be manipulated and/or + /// reassigned at a later stage). + #[pallet::call_index(10)] + pub fn assign( + origin: OriginFor, + region_id: RegionId, + task: TaskId, + finality: Finality, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + Self::do_assign(region_id, Some(who), task, finality)?; + Ok(if finality == Finality::Final { Pays::No } else { Pays::Yes }.into()) + } + + /// Place a Bulk Coretime Region into the Instantaneous Coretime Pool. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `region_id`: The Region which should be assigned to the Pool. + /// - `payee`: The account which is able to collect any revenue due for the usage of this + /// Coretime. + #[pallet::call_index(11)] + pub fn pool( + origin: OriginFor, + region_id: RegionId, + payee: T::AccountId, + finality: Finality, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + Self::do_pool(region_id, Some(who), payee, finality)?; + Ok(if finality == Finality::Final { Pays::No } else { Pays::Yes }.into()) + } + + /// Claim the revenue owed from inclusion in the Instantaneous Coretime Pool. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `region_id`: The Region which was assigned to the Pool. + /// - `max_timeslices`: The maximum number of timeslices which should be processed. This may + /// effect the weight of the call but should be ideally made equivalant to the length of + /// the Region `region_id`. If it is less than this, then further dispatches will be + /// required with the `region_id` which makes up any remainders of the region to be + /// collected. + #[pallet::call_index(12)] + #[pallet::weight(T::WeightInfo::claim_revenue(*max_timeslices))] + pub fn claim_revenue( + origin: OriginFor, + region_id: RegionId, + max_timeslices: Timeslice, + ) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin)?; + Self::do_claim_revenue(region_id, max_timeslices)?; + Ok(Pays::No.into()) + } + + /// Purchase credit for use in the Instantaneous Coretime Pool. + /// + /// - `origin`: Must be a Signed origin able to pay at least `amount`. + /// - `amount`: The amount of credit to purchase. + /// - `beneficiary`: The account on the Relay-chain which controls the credit (generally + /// this will be the collator's hot wallet). + #[pallet::call_index(13)] + pub fn purchase_credit( + origin: OriginFor, + amount: BalanceOf, + beneficiary: RelayAccountIdOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_purchase_credit(who, amount, beneficiary)?; + Ok(()) + } + + /// Drop an expired Region from the chain. + /// + /// - `origin`: Must be a Signed origin. + /// - `region_id`: The Region which has expired. + #[pallet::call_index(14)] + pub fn drop_region( + origin: OriginFor, + region_id: RegionId, + ) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin)?; + Self::do_drop_region(region_id)?; + Ok(Pays::No.into()) + } + + /// Drop an expired Instantaneous Pool Contribution record from the chain. + /// + /// - `origin`: Must be a Signed origin. + /// - `region_id`: The Region identifying the Pool Contribution which has expired. + #[pallet::call_index(15)] + pub fn drop_contribution( + origin: OriginFor, + region_id: RegionId, + ) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin)?; + Self::do_drop_contribution(region_id)?; + Ok(Pays::No.into()) + } + + /// Drop an expired Instantaneous Pool History record from the chain. + /// + /// - `origin`: Must be a Signed origin. + /// - `region_id`: The time of the Pool History record which has expired. + #[pallet::call_index(16)] + pub fn drop_history(origin: OriginFor, when: Timeslice) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin)?; + Self::do_drop_history(when)?; + Ok(Pays::No.into()) + } + + /// Drop an expired Allowed Renewal record from the chain. + /// + /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. + /// - `core`: The core to which the expired renewal refers. + /// - `when`: The timeslice to which the expired renewal refers. This must have passed. + #[pallet::call_index(17)] + pub fn drop_renewal( + origin: OriginFor, + core: CoreIndex, + when: Timeslice, + ) -> DispatchResultWithPostInfo { + let _ = ensure_signed(origin)?; + Self::do_drop_renewal(core, when)?; + Ok(Pays::No.into()) + } + + /// Request a change to the number of cores available for scheduling work. + /// + /// - `origin`: Must be Root or pass `AdminOrigin`. + /// - `core_count`: The desired number of cores to be made available. + #[pallet::call_index(18)] + #[pallet::weight(T::WeightInfo::request_core_count((*core_count).into()))] + pub fn request_core_count(origin: OriginFor, core_count: CoreIndex) -> DispatchResult { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_request_core_count(core_count)?; + Ok(()) + } + } +} diff --git a/frame/broker/src/mock.rs b/frame/broker/src/mock.rs new file mode 100644 index 0000000000000..cab6b7389c064 --- /dev/null +++ b/frame/broker/src/mock.rs @@ -0,0 +1,322 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(test)] + +use crate::{test_fungibles::TestFungibles, *}; +use frame_support::{ + assert_ok, ensure, ord_parameter_types, parameter_types, + traits::{ + fungible::{Balanced, Credit, Inspect, ItemOf, Mutate}, + nonfungible::Inspect as NftInspect, + EitherOfDiverse, Hooks, OnUnbalanced, + }, + PalletId, +}; +use frame_system::{EnsureRoot, EnsureSignedBy}; +use sp_arithmetic::Perbill; +use sp_core::{ConstU16, ConstU32, ConstU64, H256}; +use sp_runtime::{ + traits::{BlakeTwo256, Identity, IdentityLookup}, + BuildStorage, Saturating, +}; +use sp_std::collections::btree_map::BTreeMap; + +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + Broker: crate, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum CoretimeTraceItem { + AssignCore { + core: CoreIndex, + begin: u32, + assignment: Vec<(CoreAssignment, PartsOf57600)>, + end_hint: Option, + }, +} +use CoretimeTraceItem::*; + +parameter_types! { + pub static CoretimeTrace: Vec<(u32, CoretimeTraceItem)> = Default::default(); + pub static CoretimeCredit: BTreeMap = Default::default(); + pub static CoretimeSpending: Vec<(u32, u64)> = Default::default(); + pub static CoretimeWorkplan: BTreeMap<(u32, CoreIndex), Vec<(CoreAssignment, PartsOf57600)>> = Default::default(); + pub static CoretimeUsage: BTreeMap> = Default::default(); + pub static CoretimeInPool: CoreMaskBitCount = 0; + pub static NotifyCoreCount: Vec = Default::default(); + pub static NotifyRevenueInfo: Vec<(u32, u64)> = Default::default(); +} + +pub struct TestCoretimeProvider; +impl CoretimeInterface for TestCoretimeProvider { + type AccountId = u64; + type Balance = u64; + type BlockNumber = u32; + fn latest() -> Self::BlockNumber { + System::block_number() as u32 + } + fn request_core_count(count: CoreIndex) { + NotifyCoreCount::mutate(|s| s.insert(0, count)); + } + fn request_revenue_info_at(when: Self::BlockNumber) { + if when > Self::latest() { + panic!("Asking for revenue info in the future {:?} {:?}", when, Self::latest()); + } + + let mut total = 0; + CoretimeSpending::mutate(|s| { + s.retain(|(n, a)| { + if *n < when { + total += a; + false + } else { + true + } + }) + }); + NotifyRevenueInfo::mutate(|s| s.insert(0, (when, total))); + } + fn credit_account(who: Self::AccountId, amount: Self::Balance) { + CoretimeCredit::mutate(|c| c.entry(who).or_default().saturating_accrue(amount)); + } + fn assign_core( + core: CoreIndex, + begin: Self::BlockNumber, + assignment: Vec<(CoreAssignment, PartsOf57600)>, + end_hint: Option, + ) { + CoretimeWorkplan::mutate(|p| p.insert((begin, core), assignment.clone())); + let item = (Self::latest(), AssignCore { core, begin, assignment, end_hint }); + CoretimeTrace::mutate(|v| v.push(item)); + } + fn check_notify_core_count() -> Option { + NotifyCoreCount::mutate(|s| s.pop()) + } + fn check_notify_revenue_info() -> Option<(Self::BlockNumber, Self::Balance)> { + NotifyRevenueInfo::mutate(|s| s.pop()) + } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_core_count(count: u16) { + NotifyCoreCount::mutate(|s| s.insert(0, count)); + } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_notify_revenue_info(when: Self::BlockNumber, revenue: Self::Balance) { + NotifyRevenueInfo::mutate(|s| s.push((when, revenue))); + } +} +impl TestCoretimeProvider { + pub fn spend_instantaneous(who: u64, price: u64) -> Result<(), ()> { + let mut c = CoretimeCredit::get(); + ensure!(CoretimeInPool::get() > 0, ()); + c.insert(who, c.get(&who).ok_or(())?.checked_sub(price).ok_or(())?); + CoretimeCredit::set(c); + CoretimeSpending::mutate(|v| v.push((Self::latest(), price))); + Ok(()) + } + pub fn bump() { + let mut pool_size = CoretimeInPool::get(); + let mut workplan = CoretimeWorkplan::get(); + let mut usage = CoretimeUsage::get(); + let now = Self::latest(); + workplan.retain(|(when, core), assignment| { + if *when <= now { + if let Some(old_assignment) = usage.get(core) { + if let Some(a) = old_assignment.iter().find(|i| i.0 == CoreAssignment::Pool) { + pool_size -= (a.1 / 720) as CoreMaskBitCount; + } + } + if let Some(a) = assignment.iter().find(|i| i.0 == CoreAssignment::Pool) { + pool_size += (a.1 / 720) as CoreMaskBitCount; + } + usage.insert(*core, assignment.clone()); + false + } else { + true + } + }); + CoretimeInPool::set(pool_size); + CoretimeWorkplan::set(workplan); + CoretimeUsage::set(usage); + } +} + +parameter_types! { + pub const TestBrokerId: PalletId = PalletId(*b"TsBroker"); +} + +pub struct IntoZero; +impl OnUnbalanced::Currency>> for IntoZero { + fn on_nonzero_unbalanced(credit: Credit::Currency>) { + let _ = <::Currency as Balanced<_>>::resolve(&0, credit); + } +} + +ord_parameter_types! { + pub const One: u64 = 1; +} +type EnsureOneOrRoot = EitherOfDiverse, EnsureSignedBy>; + +impl crate::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = ItemOf, ()>, (), u64>; + type OnRevenue = IntoZero; + type TimeslicePeriod = ConstU32<2>; + type MaxLeasedCores = ConstU32<5>; + type MaxReservedCores = ConstU32<5>; + type Coretime = TestCoretimeProvider; + type ConvertBalance = Identity; + type WeightInfo = (); + type PalletId = TestBrokerId; + type AdminOrigin = EnsureOneOrRoot; + type PriceAdapter = Linear; +} + +pub fn advance_to(b: u64) { + while System::block_number() < b { + System::set_block_number(System::block_number() + 1); + TestCoretimeProvider::bump(); + Broker::on_initialize(System::block_number()); + } +} + +pub fn pot() -> u64 { + balance(Broker::account_id()) +} + +pub fn revenue() -> u64 { + balance(0) +} + +pub fn balance(who: u64) -> u64 { + <::Currency as Inspect<_>>::total_balance(&who) +} + +pub fn attribute(nft: RegionId, attribute: impl codec::Encode) -> T { + >::typed_attribute::<_, T>(&nft.into(), &attribute).unwrap() +} + +pub fn new_config() -> ConfigRecordOf { + ConfigRecord { + advance_notice: 2, + interlude_length: 1, + leadin_length: 1, + ideal_bulk_proportion: Default::default(), + limit_cores_offered: None, + region_length: 3, + renewal_bump: Perbill::from_percent(10), + contribution_timeout: 5, + } +} + +pub struct TestExt(ConfigRecordOf); +#[allow(dead_code)] +impl TestExt { + pub fn new() -> Self { + Self(new_config()) + } + + pub fn advance_notice(mut self, advance_notice: Timeslice) -> Self { + self.0.advance_notice = advance_notice; + self + } + + pub fn interlude_length(mut self, interlude_length: u64) -> Self { + self.0.interlude_length = interlude_length; + self + } + + pub fn leadin_length(mut self, leadin_length: u64) -> Self { + self.0.leadin_length = leadin_length; + self + } + + pub fn region_length(mut self, region_length: Timeslice) -> Self { + self.0.region_length = region_length; + self + } + + pub fn ideal_bulk_proportion(mut self, ideal_bulk_proportion: Perbill) -> Self { + self.0.ideal_bulk_proportion = ideal_bulk_proportion; + self + } + + pub fn limit_cores_offered(mut self, limit_cores_offered: Option) -> Self { + self.0.limit_cores_offered = limit_cores_offered; + self + } + + pub fn renewal_bump(mut self, renewal_bump: Perbill) -> Self { + self.0.renewal_bump = renewal_bump; + self + } + + pub fn contribution_timeout(mut self, contribution_timeout: Timeslice) -> Self { + self.0.contribution_timeout = contribution_timeout; + self + } + + pub fn endow(self, who: u64, amount: u64) -> Self { + assert_ok!(<::Currency as Mutate<_>>::mint_into(&who, amount)); + self + } + + pub fn execute_with(self, f: impl Fn() -> R) -> R { + new_test_ext().execute_with(|| { + assert_ok!(Broker::do_configure(self.0)); + f() + }) + } +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let c = frame_system::GenesisConfig::::default().build_storage().unwrap(); + sp_io::TestExternalities::from(c) +} diff --git a/frame/broker/src/nonfungible_impl.rs b/frame/broker/src/nonfungible_impl.rs new file mode 100644 index 0000000000000..fe95438cb1afa --- /dev/null +++ b/frame/broker/src/nonfungible_impl.rs @@ -0,0 +1,52 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use frame_support::{ + pallet_prelude::{DispatchResult, *}, + traits::nonfungible::{Inspect, Transfer}, +}; +use sp_std::vec::Vec; + +impl Inspect for Pallet { + type ItemId = u128; + + fn owner(index: &Self::ItemId) -> Option { + Regions::::get(RegionId::from(*index)).map(|r| r.owner) + } + + fn attribute(index: &Self::ItemId, key: &[u8]) -> Option> { + let id = RegionId::from(*index); + let item = Regions::::get(id)?; + match key { + b"begin" => Some(id.begin.encode()), + b"end" => Some(item.end.encode()), + b"length" => Some(item.end.saturating_sub(id.begin).encode()), + b"core" => Some(id.core.encode()), + b"part" => Some(id.mask.encode()), + b"owner" => Some(item.owner.encode()), + b"paid" => Some(item.paid.encode()), + _ => None, + } + } +} + +impl Transfer for Pallet { + fn transfer(index: &Self::ItemId, dest: &T::AccountId) -> DispatchResult { + Self::do_transfer((*index).into(), None, dest.clone()).map_err(Into::into) + } +} diff --git a/frame/broker/src/test_fungibles.rs b/frame/broker/src/test_fungibles.rs new file mode 100644 index 0000000000000..f6ac5a49dedd2 --- /dev/null +++ b/frame/broker/src/test_fungibles.rs @@ -0,0 +1,283 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Decode, Encode}; +use frame_support::{ + parameter_types, + traits::{ + fungibles::{self, Dust}, + tokens::{ + self, DepositConsequence, Fortitude, Preservation, Provenance, WithdrawConsequence, + }, + }, +}; +use scale_info::TypeInfo; +use sp_arithmetic::traits::Zero; +use sp_core::{Get, TypedGet}; +use sp_runtime::{DispatchError, DispatchResult}; +use sp_std::collections::btree_map::BTreeMap; + +parameter_types! { + static TestAssetOf: BTreeMap<(u32, Vec), Vec> = Default::default(); + static TestBalanceOf: BTreeMap<(u32, Vec, Vec), Vec> = Default::default(); + static TestHoldOf: BTreeMap<(u32, Vec, Vec, Vec), Vec> = Default::default(); +} + +pub struct TestFungibles( + core::marker::PhantomData<(Instance, AccountId, AssetId, MinimumBalance, HoldReason)>, +); +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason, + > fungibles::Inspect + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ + type AssetId = AssetId; + type Balance = MinimumBalance::Type; + + fn total_issuance(asset: Self::AssetId) -> Self::Balance { + TestAssetOf::get() + .get(&(Instance::get(), asset.encode())) + .and_then(|data| Decode::decode(&mut &data[..]).ok()) + .unwrap_or_default() + } + + fn active_issuance(asset: Self::AssetId) -> Self::Balance { + Self::total_issuance(asset) + } + + /// The minimum balance any single account may have. + fn minimum_balance(_asset: Self::AssetId) -> Self::Balance { + MinimumBalance::get() + } + + fn total_balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance { + TestBalanceOf::get() + .get(&(Instance::get(), asset.encode(), who.encode())) + .and_then(|data| Decode::decode(&mut &data[..]).ok()) + .unwrap_or_default() + } + + fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance { + Self::total_balance(asset, who) + } + + fn reducible_balance( + asset: Self::AssetId, + who: &AccountId, + _preservation: Preservation, + _force: Fortitude, + ) -> Self::Balance { + Self::total_balance(asset, who) + } + + fn can_deposit( + asset: Self::AssetId, + who: &AccountId, + amount: Self::Balance, + _provenance: Provenance, + ) -> DepositConsequence { + if !Self::asset_exists(asset) { + return DepositConsequence::UnknownAsset + } + if amount + Self::balance(asset, who) < Self::minimum_balance(asset) { + return DepositConsequence::BelowMinimum + } + DepositConsequence::Success + } + + fn can_withdraw( + asset: Self::AssetId, + who: &AccountId, + amount: Self::Balance, + ) -> WithdrawConsequence { + if Self::reducible_balance(asset, who, Preservation::Expendable, Fortitude::Polite) < amount + { + return WithdrawConsequence::BalanceLow + } + if Self::total_balance(asset, who) < Self::minimum_balance(asset) + amount { + return WithdrawConsequence::WouldDie + } + WithdrawConsequence::Success + } + + fn asset_exists(asset: Self::AssetId) -> bool { + TestAssetOf::get().contains_key(&(Instance::get(), asset.encode())) + } +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason, + > fungibles::Unbalanced + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ + fn handle_dust(_dust: Dust) {} + + fn write_balance( + asset: Self::AssetId, + who: &AccountId, + amount: Self::Balance, + ) -> Result, DispatchError> { + let mut tb = TestBalanceOf::get(); + let maybe_dust = if amount < MinimumBalance::get() { + tb.remove(&(Instance::get(), asset.encode(), who.encode())); + if amount.is_zero() { + None + } else { + Some(amount) + } + } else { + tb.insert((Instance::get(), asset.encode(), who.encode()), amount.encode()); + None + }; + TestBalanceOf::set(tb); + Ok(maybe_dust) + } + + fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) { + let mut ta = TestAssetOf::get(); + ta.insert((Instance::get(), asset.encode()), amount.encode()); + TestAssetOf::set(ta); + } +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason, + > fungibles::Mutate + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason, + > fungibles::Balanced + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ + type OnDropCredit = fungibles::DecreaseIssuance; + type OnDropDebt = fungibles::IncreaseIssuance; +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason: Encode + Decode + TypeInfo + 'static, + > fungibles::InspectHold + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ + type Reason = HoldReason; + + fn total_balance_on_hold(asset: Self::AssetId, who: &AccountId) -> Self::Balance { + let asset = asset.encode(); + let who = who.encode(); + TestHoldOf::get() + .iter() + .filter(|(k, _)| k.0 == Instance::get() && k.1 == asset && k.2 == who) + .filter_map(|(_, b)| Self::Balance::decode(&mut &b[..]).ok()) + .fold(Zero::zero(), |a, i| a + i) + } + + fn balance_on_hold( + asset: Self::AssetId, + reason: &Self::Reason, + who: &AccountId, + ) -> Self::Balance { + TestHoldOf::get() + .get(&(Instance::get(), asset.encode(), who.encode(), reason.encode())) + .and_then(|data| Decode::decode(&mut &data[..]).ok()) + .unwrap_or_default() + } +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason: Encode + Decode + TypeInfo + 'static, + > fungibles::UnbalancedHold + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ + fn set_balance_on_hold( + asset: Self::AssetId, + reason: &Self::Reason, + who: &AccountId, + amount: Self::Balance, + ) -> DispatchResult { + let mut th = TestHoldOf::get(); + th.insert( + (Instance::get(), asset.encode(), who.encode(), reason.encode()), + amount.encode(), + ); + TestHoldOf::set(th); + Ok(()) + } +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason: Encode + Decode + TypeInfo + 'static, + > fungibles::MutateHold + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ +} + +impl< + Instance: Get, + AccountId: Encode, + AssetId: tokens::AssetId + Copy, + MinimumBalance: TypedGet, + HoldReason: Encode + Decode + TypeInfo + 'static, + > fungibles::BalancedHold + for TestFungibles +where + MinimumBalance::Type: tokens::Balance, +{ +} diff --git a/frame/broker/src/tests.rs b/frame/broker/src/tests.rs new file mode 100644 index 0000000000000..3c326010dddfc --- /dev/null +++ b/frame/broker/src/tests.rs @@ -0,0 +1,896 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(test)] + +use crate::{core_mask::*, mock::*, *}; +use frame_support::{ + assert_noop, assert_ok, + traits::nonfungible::{Inspect as NftInspect, Transfer}, + BoundedVec, +}; +use frame_system::RawOrigin::Root; +use sp_runtime::traits::Get; +use CoreAssignment::*; +use CoretimeTraceItem::*; +use Finality::*; + +#[test] +fn basic_initialize_works() { + TestExt::new().execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + assert_eq!(CoretimeTrace::get(), vec![]); + assert_eq!(Broker::current_timeslice(), 0); + }); +} + +#[test] +fn drop_region_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(Broker::do_assign(region, Some(1), 1001, Provisional)); + advance_to(11); + assert_noop!(Broker::do_drop_region(region), Error::::StillValid); + advance_to(12); + // assignment worked. + let just_1001 = vec![(Task(1001), 57600)]; + let just_pool = vec![(Pool, 57600)]; + assert_eq!( + CoretimeTrace::get(), + vec![ + (6, AssignCore { core: 0, begin: 8, assignment: just_1001, end_hint: None }), + (12, AssignCore { core: 0, begin: 14, assignment: just_pool, end_hint: None }), + ] + ); + // `region` still exists as it was never finalized. + assert_eq!(Regions::::iter().count(), 1); + assert_ok!(Broker::do_drop_region(region)); + assert_eq!(Regions::::iter().count(), 0); + assert_noop!(Broker::do_drop_region(region), Error::::UnknownRegion); + }); +} + +#[test] +fn drop_renewal_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(Broker::do_assign(region, Some(1), 1001, Final)); + advance_to(11); + let e = Error::::StillValid; + assert_noop!(Broker::do_drop_renewal(region.core, region.begin + 3), e); + advance_to(12); + assert_ok!(Broker::do_drop_renewal(region.core, region.begin + 3)); + let e = Error::::UnknownRenewal; + assert_noop!(Broker::do_drop_renewal(region.core, region.begin + 3), e); + }); +} + +#[test] +fn drop_contribution_works() { + TestExt::new().contribution_timeout(3).endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + // Place region in pool. Active in pool timeslices 4, 5, 6 = rcblocks 8, 10, 12; we + // expect the contribution record to timeout 3 timeslices following 7 = 10 + assert_ok!(Broker::do_pool(region, Some(1), 1, Final)); + assert_eq!(InstaPoolContribution::::iter().count(), 1); + advance_to(19); + assert_noop!(Broker::do_drop_contribution(region), Error::::StillValid); + advance_to(20); + assert_ok!(Broker::do_drop_contribution(region)); + assert_eq!(InstaPoolContribution::::iter().count(), 0); + assert_noop!(Broker::do_drop_contribution(region), Error::::UnknownContribution); + }); +} + +#[test] +fn drop_history_works() { + TestExt::new() + .contribution_timeout(4) + .endow(1, 1000) + .endow(2, 30) + .execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let mut region = Broker::do_purchase(1, u64::max_value()).unwrap(); + // Place region in pool. Active in pool timeslices 4, 5, 6 = rcblocks 8, 10, 12; we + // expect to make/receive revenue reports on blocks 10, 12, 14. + assert_ok!(Broker::do_pool(region, Some(1), 1, Final)); + assert_ok!(Broker::do_purchase_credit(2, 30, 2)); + advance_to(6); + // In the stable state with no pending payouts, we expect to see 3 items in + // InstaPoolHistory here since there is a latency of 1 timeslice (for generating the + // revenue report), the forward notice period (equivalent to another timeslice) and a + // block between the revenue report being requested and the response being processed. + assert_eq!(InstaPoolHistory::::iter().count(), 3); + advance_to(7); + // One block later, the most recent report will have been processed, so the effective + // queue drops to 2 items. + assert_eq!(InstaPoolHistory::::iter().count(), 2); + advance_to(8); + assert_eq!(InstaPoolHistory::::iter().count(), 3); + assert_ok!(TestCoretimeProvider::spend_instantaneous(2, 10)); + advance_to(10); + assert_eq!(InstaPoolHistory::::iter().count(), 3); + assert_ok!(TestCoretimeProvider::spend_instantaneous(2, 10)); + advance_to(12); + assert_eq!(InstaPoolHistory::::iter().count(), 4); + assert_ok!(TestCoretimeProvider::spend_instantaneous(2, 10)); + advance_to(14); + assert_eq!(InstaPoolHistory::::iter().count(), 5); + advance_to(16); + assert_eq!(InstaPoolHistory::::iter().count(), 6); + advance_to(17); + assert_noop!(Broker::do_drop_history(region.begin), Error::::StillValid); + advance_to(18); + assert_eq!(InstaPoolHistory::::iter().count(), 6); + // Block 18 is 8 blocks ()= 4 timeslices = contribution timeout) after first region. + // Its revenue should now be droppable. + assert_ok!(Broker::do_drop_history(region.begin)); + assert_eq!(InstaPoolHistory::::iter().count(), 5); + assert_noop!(Broker::do_drop_history(region.begin), Error::::NoHistory); + advance_to(19); + region.begin += 1; + assert_noop!(Broker::do_drop_history(region.begin), Error::::StillValid); + advance_to(20); + assert_ok!(Broker::do_drop_history(region.begin)); + assert_eq!(InstaPoolHistory::::iter().count(), 4); + assert_noop!(Broker::do_drop_history(region.begin), Error::::NoHistory); + advance_to(21); + region.begin += 1; + assert_noop!(Broker::do_drop_history(region.begin), Error::::StillValid); + advance_to(22); + assert_ok!(Broker::do_drop_history(region.begin)); + assert_eq!(InstaPoolHistory::::iter().count(), 3); + assert_noop!(Broker::do_drop_history(region.begin), Error::::NoHistory); + }); +} + +#[test] +fn request_core_count_works() { + TestExt::new().execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 0)); + assert_ok!(Broker::request_core_count(RuntimeOrigin::root(), 1)); + advance_to(12); + let assignment = vec![(Pool, 57600)]; + assert_eq!( + CoretimeTrace::get(), + vec![(12, AssignCore { core: 0, begin: 14, assignment, end_hint: None })], + ); + }); +} + +#[test] +fn transfer_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(>::transfer(®ion.into(), &2)); + assert_eq!(>::owner(®ion.into()), Some(2)); + assert_noop!(Broker::do_assign(region, Some(1), 1001, Final), Error::::NotOwner); + assert_ok!(Broker::do_assign(region, Some(2), 1002, Final)); + }); +} + +#[test] +fn permanent_is_not_reassignable() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(Broker::do_assign(region, Some(1), 1001, Final)); + assert_noop!(Broker::do_assign(region, Some(1), 1002, Final), Error::::UnknownRegion); + assert_noop!(Broker::do_pool(region, Some(1), 1002, Final), Error::::UnknownRegion); + assert_noop!(Broker::do_partition(region, Some(1), 1), Error::::UnknownRegion); + assert_noop!( + Broker::do_interlace(region, Some(1), CoreMask::from_chunk(0, 40)), + Error::::UnknownRegion + ); + }); +} + +#[test] +fn provisional_is_reassignable() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(Broker::do_assign(region, Some(1), 1001, Provisional)); + let (region1, region) = Broker::do_partition(region, Some(1), 1).unwrap(); + let (region2, region3) = + Broker::do_interlace(region, Some(1), CoreMask::from_chunk(0, 40)).unwrap(); + assert_ok!(Broker::do_pool(region1, Some(1), 1, Provisional)); + assert_ok!(Broker::do_assign(region2, Some(1), 1002, Provisional)); + assert_ok!(Broker::do_assign(region3, Some(1), 1003, Provisional)); + advance_to(8); + assert_eq!( + CoretimeTrace::get(), + vec![ + ( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Pool, 57600),], + end_hint: None + } + ), + ( + 8, + AssignCore { + core: 0, + begin: 10, + assignment: vec![(Task(1002), 28800), (Task(1003), 28800),], + end_hint: None + } + ), + ] + ); + }); +} + +#[test] +fn nft_metadata_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_eq!(attribute::(region, b"begin"), 4); + assert_eq!(attribute::(region, b"length"), 3); + assert_eq!(attribute::(region, b"end"), 7); + assert_eq!(attribute::(region, b"owner"), 1); + assert_eq!(attribute::(region, b"part"), 0xfffff_fffff_fffff_fffff.into()); + assert_eq!(attribute::(region, b"core"), 0); + assert_eq!(attribute::>(region, b"paid"), Some(100)); + + assert_ok!(Broker::do_transfer(region, None, 42)); + let (_, region) = Broker::do_partition(region, None, 2).unwrap(); + let (region, _) = + Broker::do_interlace(region, None, 0x00000_fffff_fffff_00000.into()).unwrap(); + assert_eq!(attribute::(region, b"begin"), 6); + assert_eq!(attribute::(region, b"length"), 1); + assert_eq!(attribute::(region, b"end"), 7); + assert_eq!(attribute::(region, b"owner"), 42); + assert_eq!(attribute::(region, b"part"), 0x00000_fffff_fffff_00000.into()); + assert_eq!(attribute::(region, b"core"), 0); + assert_eq!(attribute::>(region, b"paid"), None); + }); +} + +#[test] +fn migration_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_set_lease(1000, 8)); + assert_ok!(Broker::do_start_sales(100, 2)); + + // Sale is for regions from TS4..7 + // Not ending in this sale period. + assert_noop!(Broker::do_renew(1, 0), Error::::NotAllowed); + + advance_to(12); + // Sale is now for regions from TS10..13 + // Ending in this sale period. + // Should now be renewable. + assert_ok!(Broker::do_renew(1, 0)); + assert_eq!(balance(1), 900); + advance_to(18); + + let just_pool = || vec![(Pool, 57600)]; + let just_1000 = || vec![(Task(1000), 57600)]; + assert_eq!( + CoretimeTrace::get(), + vec![ + (6, AssignCore { core: 0, begin: 8, assignment: just_1000(), end_hint: None }), + (6, AssignCore { core: 1, begin: 8, assignment: just_pool(), end_hint: None }), + (12, AssignCore { core: 0, begin: 14, assignment: just_1000(), end_hint: None }), + (12, AssignCore { core: 1, begin: 14, assignment: just_pool(), end_hint: None }), + (18, AssignCore { core: 0, begin: 20, assignment: just_1000(), end_hint: None }), + (18, AssignCore { core: 1, begin: 20, assignment: just_pool(), end_hint: None }), + ] + ); + }); +} + +#[test] +fn renewal_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_eq!(balance(1), 900); + assert_ok!(Broker::do_assign(region, None, 1001, Final)); + // Should now be renewable. + advance_to(6); + assert_noop!(Broker::do_purchase(1, u64::max_value()), Error::::TooEarly); + let core = Broker::do_renew(1, region.core).unwrap(); + assert_eq!(balance(1), 800); + advance_to(8); + assert_noop!(Broker::do_purchase(1, u64::max_value()), Error::::SoldOut); + advance_to(12); + assert_ok!(Broker::do_renew(1, core)); + assert_eq!(balance(1), 690); + }); +} + +#[test] +fn instapool_payouts_work() { + TestExt::new().endow(1, 1000).execute_with(|| { + let item = ScheduleItem { assignment: Pool, mask: CoreMask::complete() }; + assert_ok!(Broker::do_reserve(Schedule::truncate_from(vec![item]))); + assert_ok!(Broker::do_start_sales(100, 3)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(Broker::do_pool(region, None, 2, Final)); + assert_ok!(Broker::do_purchase_credit(1, 20, 1)); + advance_to(8); + assert_ok!(TestCoretimeProvider::spend_instantaneous(1, 10)); + advance_to(11); + assert_eq!(pot(), 14); + assert_eq!(revenue(), 106); + assert_ok!(Broker::do_claim_revenue(region, 100)); + assert_eq!(pot(), 10); + assert_eq!(balance(2), 4); + }); +} + +#[test] +fn instapool_partial_core_payouts_work() { + TestExt::new().endow(1, 1000).execute_with(|| { + let item = ScheduleItem { assignment: Pool, mask: CoreMask::complete() }; + assert_ok!(Broker::do_reserve(Schedule::truncate_from(vec![item]))); + assert_ok!(Broker::do_start_sales(100, 2)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + let (region1, region2) = + Broker::do_interlace(region, None, CoreMask::from_chunk(0, 20)).unwrap(); + assert_ok!(Broker::do_pool(region1, None, 2, Final)); + assert_ok!(Broker::do_pool(region2, None, 3, Final)); + assert_ok!(Broker::do_purchase_credit(1, 40, 1)); + advance_to(8); + assert_ok!(TestCoretimeProvider::spend_instantaneous(1, 40)); + advance_to(11); + assert_ok!(Broker::do_claim_revenue(region1, 100)); + assert_ok!(Broker::do_claim_revenue(region2, 100)); + assert_eq!(revenue(), 120); + assert_eq!(balance(2), 5); + assert_eq!(balance(3), 15); + assert_eq!(pot(), 0); + }); +} + +#[test] +fn initialize_with_system_paras_works() { + TestExt::new().execute_with(|| { + let item = ScheduleItem { assignment: Task(1u32), mask: CoreMask::complete() }; + assert_ok!(Broker::do_reserve(Schedule::truncate_from(vec![item]))); + let items = vec![ + ScheduleItem { assignment: Task(2u32), mask: 0xfffff_fffff_00000_00000.into() }, + ScheduleItem { assignment: Task(3u32), mask: 0x00000_00000_fffff_00000.into() }, + ScheduleItem { assignment: Task(4u32), mask: 0x00000_00000_00000_fffff.into() }, + ]; + assert_ok!(Broker::do_reserve(Schedule::truncate_from(items))); + assert_ok!(Broker::do_start_sales(100, 2)); + advance_to(10); + assert_eq!( + CoretimeTrace::get(), + vec![ + ( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1), 57600),], + end_hint: None + } + ), + ( + 6, + AssignCore { + core: 1, + begin: 8, + assignment: vec![(Task(2), 28800), (Task(3), 14400), (Task(4), 14400),], + end_hint: None + } + ), + ] + ); + }); +} + +#[test] +fn initialize_with_leased_slots_works() { + TestExt::new().execute_with(|| { + assert_ok!(Broker::do_set_lease(1000, 6)); + assert_ok!(Broker::do_set_lease(1001, 7)); + assert_ok!(Broker::do_start_sales(100, 2)); + advance_to(18); + let end_hint = None; + assert_eq!( + CoretimeTrace::get(), + vec![ + ( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1000), 57600),], + end_hint + } + ), + ( + 6, + AssignCore { + core: 1, + begin: 8, + assignment: vec![(Task(1001), 57600),], + end_hint + } + ), + ( + 12, + AssignCore { + core: 0, + begin: 14, + assignment: vec![(Task(1001), 57600),], + end_hint + } + ), + (12, AssignCore { core: 1, begin: 14, assignment: vec![(Pool, 57600),], end_hint }), + (18, AssignCore { core: 0, begin: 20, assignment: vec![(Pool, 57600),], end_hint }), + (18, AssignCore { core: 1, begin: 20, assignment: vec![(Pool, 57600),], end_hint }), + ] + ); + }); +} + +#[test] +fn purchase_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_ok!(Broker::do_assign(region, None, 1000, Final)); + advance_to(6); + assert_eq!( + CoretimeTrace::get(), + vec![( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1000), 57600),], + end_hint: None + } + ),] + ); + }); +} + +#[test] +fn partition_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + let (region1, region) = Broker::do_partition(region, None, 1).unwrap(); + let (region2, region3) = Broker::do_partition(region, None, 1).unwrap(); + assert_ok!(Broker::do_assign(region1, None, 1001, Final)); + assert_ok!(Broker::do_assign(region2, None, 1002, Final)); + assert_ok!(Broker::do_assign(region3, None, 1003, Final)); + advance_to(10); + assert_eq!( + CoretimeTrace::get(), + vec![ + ( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1001), 57600),], + end_hint: None + } + ), + ( + 8, + AssignCore { + core: 0, + begin: 10, + assignment: vec![(Task(1002), 57600),], + end_hint: None + } + ), + ( + 10, + AssignCore { + core: 0, + begin: 12, + assignment: vec![(Task(1003), 57600),], + end_hint: None + } + ), + ] + ); + }); +} + +#[test] +fn interlace_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + let (region1, region) = + Broker::do_interlace(region, None, CoreMask::from_chunk(0, 30)).unwrap(); + let (region2, region3) = + Broker::do_interlace(region, None, CoreMask::from_chunk(30, 60)).unwrap(); + assert_ok!(Broker::do_assign(region1, None, 1001, Final)); + assert_ok!(Broker::do_assign(region2, None, 1002, Final)); + assert_ok!(Broker::do_assign(region3, None, 1003, Final)); + advance_to(10); + assert_eq!( + CoretimeTrace::get(), + vec![( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1001), 21600), (Task(1002), 21600), (Task(1003), 14400),], + end_hint: None + } + ),] + ); + }); +} + +#[test] +fn interlace_then_partition_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + let (region1, region2) = + Broker::do_interlace(region, None, CoreMask::from_chunk(0, 20)).unwrap(); + let (region1, region3) = Broker::do_partition(region1, None, 1).unwrap(); + let (region2, region4) = Broker::do_partition(region2, None, 2).unwrap(); + assert_ok!(Broker::do_assign(region1, None, 1001, Final)); + assert_ok!(Broker::do_assign(region2, None, 1002, Final)); + assert_ok!(Broker::do_assign(region3, None, 1003, Final)); + assert_ok!(Broker::do_assign(region4, None, 1004, Final)); + advance_to(10); + assert_eq!( + CoretimeTrace::get(), + vec![ + ( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1001), 14400), (Task(1002), 43200),], + end_hint: None + } + ), + ( + 8, + AssignCore { + core: 0, + begin: 10, + assignment: vec![(Task(1002), 43200), (Task(1003), 14400),], + end_hint: None + } + ), + ( + 10, + AssignCore { + core: 0, + begin: 12, + assignment: vec![(Task(1003), 14400), (Task(1004), 43200),], + end_hint: None + } + ), + ] + ); + }); +} + +#[test] +fn partition_then_interlace_works() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + let (region1, region2) = Broker::do_partition(region, None, 1).unwrap(); + let (region1, region3) = + Broker::do_interlace(region1, None, CoreMask::from_chunk(0, 20)).unwrap(); + let (region2, region4) = + Broker::do_interlace(region2, None, CoreMask::from_chunk(0, 30)).unwrap(); + assert_ok!(Broker::do_assign(region1, None, 1001, Final)); + assert_ok!(Broker::do_assign(region2, None, 1002, Final)); + assert_ok!(Broker::do_assign(region3, None, 1003, Final)); + assert_ok!(Broker::do_assign(region4, None, 1004, Final)); + advance_to(10); + assert_eq!( + CoretimeTrace::get(), + vec![ + ( + 6, + AssignCore { + core: 0, + begin: 8, + assignment: vec![(Task(1001), 14400), (Task(1003), 43200),], + end_hint: None + } + ), + ( + 8, + AssignCore { + core: 0, + begin: 10, + assignment: vec![(Task(1002), 21600), (Task(1004), 36000),], + end_hint: None + } + ), + ] + ); + }); +} + +#[test] +fn reservations_are_limited() { + TestExt::new().execute_with(|| { + let schedule = Schedule::truncate_from(vec![ScheduleItem { + assignment: Pool, + mask: CoreMask::complete(), + }]); + let max_cores: u32 = ::MaxReservedCores::get(); + Reservations::::put( + BoundedVec::try_from(vec![schedule.clone(); max_cores as usize]).unwrap(), + ); + assert_noop!(Broker::do_reserve(schedule), Error::::TooManyReservations); + }); +} + +#[test] +fn cannot_unreserve_unknown() { + TestExt::new().execute_with(|| { + let schedule = Schedule::truncate_from(vec![ScheduleItem { + assignment: Pool, + mask: CoreMask::complete(), + }]); + Reservations::::put(BoundedVec::try_from(vec![schedule.clone(); 1usize]).unwrap()); + assert_noop!(Broker::do_unreserve(2), Error::::UnknownReservation); + }); +} + +#[test] +fn cannot_set_expired_lease() { + TestExt::new().execute_with(|| { + advance_to(2); + let current_timeslice = Broker::current_timeslice(); + assert_noop!( + Broker::do_set_lease(1000, current_timeslice.saturating_sub(1)), + Error::::AlreadyExpired + ); + }); +} + +#[test] +fn leases_are_limited() { + TestExt::new().execute_with(|| { + let max_leases: u32 = ::MaxLeasedCores::get(); + Leases::::put( + BoundedVec::try_from(vec![ + LeaseRecordItem { task: 1u32, until: 10u32 }; + max_leases as usize + ]) + .unwrap(), + ); + assert_noop!(Broker::do_set_lease(1000, 10), Error::::TooManyLeases); + }); +} + +#[test] +fn purchase_requires_valid_status_and_sale_info() { + TestExt::new().execute_with(|| { + assert_noop!(Broker::do_purchase(1, 100), Error::::Uninitialized); + + let status = StatusRecord { + core_count: 2, + private_pool_size: 0, + system_pool_size: 0, + last_committed_timeslice: 0, + last_timeslice: 1, + }; + Status::::put(&status); + assert_noop!(Broker::do_purchase(1, 100), Error::::NoSales); + + let mut dummy_sale = SaleInfoRecord { + sale_start: 0, + leadin_length: 0, + price: 200, + sellout_price: None, + region_begin: 0, + region_end: 3, + first_core: 3, + ideal_cores_sold: 0, + cores_offered: 1, + cores_sold: 2, + }; + SaleInfo::::put(&dummy_sale); + assert_noop!(Broker::do_purchase(1, 100), Error::::Unavailable); + + dummy_sale.first_core = 1; + SaleInfo::::put(&dummy_sale); + assert_noop!(Broker::do_purchase(1, 100), Error::::SoldOut); + + assert_ok!(Broker::do_start_sales(200, 1)); + assert_noop!(Broker::do_purchase(1, 100), Error::::TooEarly); + + advance_to(2); + assert_noop!(Broker::do_purchase(1, 100), Error::::Overpriced); + }); +} + +#[test] +fn renewal_requires_valid_status_and_sale_info() { + TestExt::new().execute_with(|| { + assert_noop!(Broker::do_renew(1, 1), Error::::Uninitialized); + + let status = StatusRecord { + core_count: 2, + private_pool_size: 0, + system_pool_size: 0, + last_committed_timeslice: 0, + last_timeslice: 1, + }; + Status::::put(&status); + assert_noop!(Broker::do_renew(1, 1), Error::::NoSales); + + let mut dummy_sale = SaleInfoRecord { + sale_start: 0, + leadin_length: 0, + price: 200, + sellout_price: None, + region_begin: 0, + region_end: 3, + first_core: 3, + ideal_cores_sold: 0, + cores_offered: 1, + cores_sold: 2, + }; + SaleInfo::::put(&dummy_sale); + assert_noop!(Broker::do_renew(1, 1), Error::::Unavailable); + + dummy_sale.first_core = 1; + SaleInfo::::put(&dummy_sale); + assert_noop!(Broker::do_renew(1, 1), Error::::SoldOut); + + assert_ok!(Broker::do_start_sales(200, 1)); + assert_noop!(Broker::do_renew(1, 1), Error::::NotAllowed); + + let record = AllowedRenewalRecord { + price: 100, + completion: CompletionStatus::Partial(CoreMask::from_chunk(0, 20)), + }; + AllowedRenewals::::insert(AllowedRenewalId { core: 1, when: 4 }, &record); + assert_noop!(Broker::do_renew(1, 1), Error::::IncompleteAssignment); + }); +} + +#[test] +fn cannot_transfer_or_partition_or_interlace_unknown() { + TestExt::new().execute_with(|| { + let region_id = RegionId { begin: 0, core: 0, mask: CoreMask::complete() }; + assert_noop!(Broker::do_transfer(region_id, None, 2), Error::::UnknownRegion); + assert_noop!(Broker::do_partition(region_id, None, 2), Error::::UnknownRegion); + assert_noop!( + Broker::do_interlace(region_id, None, CoreMask::from_chunk(0, 20)), + Error::::UnknownRegion + ); + }); +} + +#[test] +fn check_ownership_for_transfer_or_partition_or_interlace() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_noop!(Broker::do_transfer(region, Some(2), 2), Error::::NotOwner); + assert_noop!(Broker::do_partition(region, Some(2), 2), Error::::NotOwner); + assert_noop!( + Broker::do_interlace(region, Some(2), CoreMask::from_chunk(0, 20)), + Error::::NotOwner + ); + }); +} + +#[test] +fn cannot_partition_invalid_offset() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + assert_noop!(Broker::do_partition(region, None, 0), Error::::PivotTooEarly); + assert_noop!(Broker::do_partition(region, None, 5), Error::::PivotTooLate); + }); +} + +#[test] +fn cannot_interlace_invalid_pivot() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let region = Broker::do_purchase(1, u64::max_value()).unwrap(); + let (region1, _) = Broker::do_interlace(region, None, CoreMask::from_chunk(0, 20)).unwrap(); + assert_noop!( + Broker::do_interlace(region1, None, CoreMask::from_chunk(20, 40)), + Error::::ExteriorPivot + ); + assert_noop!( + Broker::do_interlace(region1, None, CoreMask::void()), + Error::::VoidPivot + ); + assert_noop!( + Broker::do_interlace(region1, None, CoreMask::from_chunk(0, 20)), + Error::::CompletePivot + ); + }); +} + +#[test] +fn assign_should_drop_invalid_region() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let mut region = Broker::do_purchase(1, u64::max_value()).unwrap(); + advance_to(10); + assert_ok!(Broker::do_assign(region, Some(1), 1001, Provisional)); + region.begin = 7; + System::assert_last_event(Event::RegionDropped { region_id: region, duration: 0 }.into()); + }); +} + +#[test] +fn pool_should_drop_invalid_region() { + TestExt::new().endow(1, 1000).execute_with(|| { + assert_ok!(Broker::do_start_sales(100, 1)); + advance_to(2); + let mut region = Broker::do_purchase(1, u64::max_value()).unwrap(); + advance_to(10); + assert_ok!(Broker::do_pool(region, Some(1), 1001, Provisional)); + region.begin = 7; + System::assert_last_event(Event::RegionDropped { region_id: region, duration: 0 }.into()); + }); +} + +#[test] +fn config_works() { + TestExt::new().execute_with(|| { + let mut cfg = new_config(); + // Good config works: + assert_ok!(Broker::configure(Root.into(), cfg.clone())); + // Bad config is a noop: + cfg.leadin_length = 0; + assert_noop!(Broker::configure(Root.into(), cfg), Error::::InvalidConfig); + }); +} diff --git a/frame/broker/src/tick_impls.rs b/frame/broker/src/tick_impls.rs new file mode 100644 index 0000000000000..0677d2793e21a --- /dev/null +++ b/frame/broker/src/tick_impls.rs @@ -0,0 +1,326 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use frame_support::{pallet_prelude::*, weights::WeightMeter}; +use sp_arithmetic::{ + traits::{One, SaturatedConversion, Saturating, Zero}, + FixedPointNumber, +}; +use sp_runtime::traits::ConvertBack; +use sp_std::{vec, vec::Vec}; +use CompletionStatus::Complete; + +impl Pallet { + /// Attempt to tick things along. + /// + /// This may do several things: + /// - Processes notifications of the core count changing + /// - Processes reports of Instantaneous Core Market Revenue + /// - Commit a timeslice + /// - Rotate the sale period + /// - Request revenue information for a previous timeslice + /// - Initialize an instantaneous core pool historical revenue record + pub(crate) fn do_tick() -> Weight { + let (mut status, config) = match (Status::::get(), Configuration::::get()) { + (Some(s), Some(c)) => (s, c), + _ => return Weight::zero(), + }; + + let mut meter = WeightMeter::max_limit(); + + if Self::process_core_count(&mut status) { + meter.consume(T::WeightInfo::process_core_count(status.core_count.into())); + } + + if Self::process_revenue() { + meter.consume(T::WeightInfo::process_revenue()); + } + + if let Some(commit_timeslice) = Self::next_timeslice_to_commit(&config, &status) { + status.last_committed_timeslice = commit_timeslice; + if let Some(sale) = SaleInfo::::get() { + if commit_timeslice >= sale.region_begin { + // Sale can be rotated. + Self::rotate_sale(sale, &config, &status); + meter.consume(T::WeightInfo::rotate_sale(status.core_count.into())); + } + } + + Self::process_pool(commit_timeslice, &mut status); + meter.consume(T::WeightInfo::process_pool()); + + let timeslice_period = T::TimeslicePeriod::get(); + let rc_begin = RelayBlockNumberOf::::from(commit_timeslice) * timeslice_period; + for core in 0..status.core_count { + Self::process_core_schedule(commit_timeslice, rc_begin, core); + meter.consume(T::WeightInfo::process_core_schedule()); + } + } + + let current_timeslice = Self::current_timeslice(); + if status.last_timeslice < current_timeslice { + status.last_timeslice.saturating_inc(); + let rc_block = T::TimeslicePeriod::get() * status.last_timeslice.into(); + T::Coretime::request_revenue_info_at(rc_block); + meter.consume(T::WeightInfo::request_revenue_info_at()); + } + + Status::::put(&status); + + meter.consumed() + } + + pub(crate) fn process_core_count(status: &mut StatusRecord) -> bool { + if let Some(core_count) = T::Coretime::check_notify_core_count() { + status.core_count = core_count; + Self::deposit_event(Event::::CoreCountChanged { core_count }); + return true + } + false + } + + pub(crate) fn process_revenue() -> bool { + let Some((until, amount)) = T::Coretime::check_notify_revenue_info() else { + return false; + }; + let when: Timeslice = + (until / T::TimeslicePeriod::get()).saturating_sub(One::one()).saturated_into(); + let mut revenue = T::ConvertBalance::convert_back(amount); + if revenue.is_zero() { + Self::deposit_event(Event::::HistoryDropped { when, revenue }); + InstaPoolHistory::::remove(when); + return true + } + let mut r = InstaPoolHistory::::get(when).unwrap_or_default(); + if r.maybe_payout.is_some() { + Self::deposit_event(Event::::HistoryIgnored { when, revenue }); + return true + } + // Payout system InstaPool Cores. + let total_contrib = r.system_contributions.saturating_add(r.private_contributions); + let system_payout = + revenue.saturating_mul(r.system_contributions.into()) / total_contrib.into(); + let _ = Self::charge(&Self::account_id(), system_payout); + revenue.saturating_reduce(system_payout); + + if !revenue.is_zero() && r.private_contributions > 0 { + r.maybe_payout = Some(revenue); + InstaPoolHistory::::insert(when, &r); + Self::deposit_event(Event::::ClaimsReady { + when, + system_payout, + private_payout: revenue, + }); + } else { + InstaPoolHistory::::remove(when); + Self::deposit_event(Event::::HistoryDropped { when, revenue }); + } + true + } + + /// Begin selling for the next sale period. + /// + /// Triggered by Relay-chain block number/timeslice. + pub(crate) fn rotate_sale( + old_sale: SaleInfoRecordOf, + config: &ConfigRecordOf, + status: &StatusRecord, + ) -> Option<()> { + let now = frame_system::Pallet::::block_number(); + + let pool_item = + ScheduleItem { assignment: CoreAssignment::Pool, mask: CoreMask::complete() }; + let just_pool = Schedule::truncate_from(vec![pool_item]); + + // Clean up the old sale - we need to use up any unused cores by putting them into the + // InstaPool. + let mut old_pooled: SignedCoreMaskBitCount = 0; + for i in old_sale.cores_sold..old_sale.cores_offered { + old_pooled.saturating_accrue(80); + Workplan::::insert((old_sale.region_begin, old_sale.first_core + i), &just_pool); + } + InstaPoolIo::::mutate(old_sale.region_begin, |r| r.system.saturating_accrue(old_pooled)); + InstaPoolIo::::mutate(old_sale.region_end, |r| r.system.saturating_reduce(old_pooled)); + + // Calculate the start price for the upcoming sale. + let price = { + let offered = old_sale.cores_offered; + let ideal = old_sale.ideal_cores_sold; + let sold = old_sale.cores_sold; + + let maybe_purchase_price = if offered == 0 { + // No cores offered for sale - no purchase price. + None + } else if sold >= ideal { + // Sold more than the ideal amount. We should look for the last purchase price + // before the sell-out. If there was no purchase at all, then we avoid having a + // price here so that we make no alterations to it (since otherwise we would + // increase it). + old_sale.sellout_price + } else { + // Sold less than the ideal - we fall back to the regular price. + Some(old_sale.price) + }; + if let Some(purchase_price) = maybe_purchase_price { + T::PriceAdapter::adapt_price(sold.min(offered), ideal, offered) + .saturating_mul_int(purchase_price) + } else { + old_sale.price + } + }; + + // Set workload for the reserved (system, probably) workloads. + let region_begin = old_sale.region_end; + let region_end = region_begin + config.region_length; + + let mut first_core = 0; + let mut total_pooled: SignedCoreMaskBitCount = 0; + for schedule in Reservations::::get().into_iter() { + let parts: u32 = schedule + .iter() + .filter(|i| matches!(i.assignment, CoreAssignment::Pool)) + .map(|i| i.mask.count_ones()) + .sum(); + total_pooled.saturating_accrue(parts as i32); + + Workplan::::insert((region_begin, first_core), &schedule); + first_core.saturating_inc(); + } + InstaPoolIo::::mutate(region_begin, |r| r.system.saturating_accrue(total_pooled)); + InstaPoolIo::::mutate(region_end, |r| r.system.saturating_reduce(total_pooled)); + + let mut leases = Leases::::get(); + // Can morph to a renewable as long as it's >=begin and ::insert((region_begin, first_core), &schedule); + let expiring = until >= region_begin && until < region_end; + if expiring { + // last time for this one - make it renewable. + let renewal_id = AllowedRenewalId { core: first_core, when: region_end }; + let record = AllowedRenewalRecord { price, completion: Complete(schedule) }; + AllowedRenewals::::insert(renewal_id, &record); + Self::deposit_event(Event::Renewable { + core: first_core, + price, + begin: region_end, + workload: record.completion.drain_complete().unwrap_or_default(), + }); + Self::deposit_event(Event::LeaseEnding { when: region_end, task }); + } + first_core.saturating_inc(); + !expiring + }); + Leases::::put(&leases); + + let max_possible_sales = status.core_count.saturating_sub(first_core); + let limit_cores_offered = config.limit_cores_offered.unwrap_or(CoreIndex::max_value()); + let cores_offered = limit_cores_offered.min(max_possible_sales); + let sale_start = now.saturating_add(config.interlude_length); + let leadin_length = config.leadin_length; + let ideal_cores_sold = (config.ideal_bulk_proportion * cores_offered as u32) as u16; + // Update SaleInfo + let new_sale = SaleInfoRecord { + sale_start, + leadin_length, + price, + sellout_price: None, + region_begin, + region_end, + first_core, + ideal_cores_sold, + cores_offered, + cores_sold: 0, + }; + SaleInfo::::put(&new_sale); + Self::deposit_event(Event::SaleInitialized { + sale_start, + leadin_length, + start_price: Self::sale_price(&new_sale, now), + regular_price: price, + region_begin, + region_end, + ideal_cores_sold, + cores_offered, + }); + + Some(()) + } + + pub(crate) fn process_pool(when: Timeslice, status: &mut StatusRecord) { + let pool_io = InstaPoolIo::::take(when); + status.private_pool_size = (status.private_pool_size as SignedCoreMaskBitCount) + .saturating_add(pool_io.private) as CoreMaskBitCount; + status.system_pool_size = (status.system_pool_size as SignedCoreMaskBitCount) + .saturating_add(pool_io.system) as CoreMaskBitCount; + let record = InstaPoolHistoryRecord { + private_contributions: status.private_pool_size, + system_contributions: status.system_pool_size, + maybe_payout: None, + }; + InstaPoolHistory::::insert(when, record); + Self::deposit_event(Event::::HistoryInitialized { + when, + private_pool_size: status.private_pool_size, + system_pool_size: status.system_pool_size, + }); + } + + /// Schedule cores for the given `timeslice`. + pub(crate) fn process_core_schedule( + timeslice: Timeslice, + rc_begin: RelayBlockNumberOf, + core: CoreIndex, + ) { + let Some(workplan) = Workplan::::take((timeslice, core)) else { + return; + }; + let workload = Workload::::get(core); + let parts_used = workplan.iter().map(|i| i.mask).fold(CoreMask::void(), |a, i| a | i); + let mut workplan = workplan.into_inner(); + workplan.extend(workload.into_iter().filter(|i| (i.mask & parts_used).is_void())); + let workplan = Schedule::truncate_from(workplan); + Workload::::insert(core, &workplan); + + let mut total_used = 0; + let mut intermediate = workplan + .into_iter() + .map(|i| (i.assignment, i.mask.count_ones() as u16 * (57_600 / 80))) + .inspect(|i| total_used.saturating_accrue(i.1)) + .collect::>(); + if total_used < 57_600 { + intermediate.push((CoreAssignment::Idle, 57_600 - total_used)); + } + intermediate.sort(); + let mut assignment: Vec<(CoreAssignment, PartsOf57600)> = + Vec::with_capacity(intermediate.len()); + for i in intermediate.into_iter() { + if let Some(ref mut last) = assignment.last_mut() { + if last.0 == i.0 { + last.1 += i.1; + continue + } + } + assignment.push(i); + } + T::Coretime::assign_core(core, rc_begin, assignment.clone(), None); + Self::deposit_event(Event::::CoreAssigned { core, when: rc_begin, assignment }); + } +} diff --git a/frame/broker/src/types.rs b/frame/broker/src/types.rs new file mode 100644 index 0000000000000..89222ca8e9527 --- /dev/null +++ b/frame/broker/src/types.rs @@ -0,0 +1,290 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + Config, CoreAssignment, CoreIndex, CoreMask, CoretimeInterface, TaskId, CORE_MASK_BITS, +}; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::fungible::Inspect; +use frame_system::{pallet_prelude::BlockNumberFor, Config as SConfig}; +use scale_info::TypeInfo; +use sp_arithmetic::Perbill; +use sp_core::{ConstU32, RuntimeDebug}; +use sp_runtime::BoundedVec; + +pub type BalanceOf = <::Currency as Inspect<::AccountId>>::Balance; +pub type RelayBalanceOf = <::Coretime as CoretimeInterface>::Balance; +pub type RelayBlockNumberOf = <::Coretime as CoretimeInterface>::BlockNumber; +pub type RelayAccountIdOf = <::Coretime as CoretimeInterface>::AccountId; + +/// Relay-chain block number with a fixed divisor of Config::TimeslicePeriod. +pub type Timeslice = u32; +/// Counter for the total number of set bits over every core's `CoreMask`. `u32` so we don't +/// ever get an overflow. This is 1/80th of a Polkadot Core per timeslice. Assuming timeslices are +/// 80 blocks, then this indicates usage of a single core one time over a timeslice. +pub type CoreMaskBitCount = u32; +/// The same as `CoreMaskBitCount` but signed. +pub type SignedCoreMaskBitCount = i32; + +/// Whether a core assignment is revokable or not. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum Finality { + /// The region remains with the same owner allowing the assignment to be altered. + Provisional, + /// The region is removed; the assignment may be eligible for renewal. + Final, +} + +/// Self-describing identity for a Region of Bulk Coretime. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct RegionId { + /// The timeslice at which this Region begins. + pub begin: Timeslice, + /// The index of the Polakdot Core on which this Region will be scheduled. + pub core: CoreIndex, + /// The regularity parts in which this Region will be scheduled. + pub mask: CoreMask, +} +impl From for RegionId { + fn from(x: u128) -> Self { + Self { begin: (x >> 96) as u32, core: (x >> 80) as u16, mask: x.into() } + } +} +impl From for u128 { + fn from(x: RegionId) -> Self { + (x.begin as u128) << 96 | (x.core as u128) << 80 | u128::from(x.mask) + } +} +#[test] +fn region_id_converts_u128() { + let r = RegionId { begin: 0x12345678u32, core: 0xabcdu16, mask: 0xdeadbeefcafef00d0123.into() }; + let u = 0x12345678_abcd_deadbeefcafef00d0123u128; + assert_eq!(RegionId::from(u), r); + assert_eq!(u128::from(r), u); +} + +/// The rest of the information describing a Region. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct RegionRecord { + /// The end of the Region. + pub end: Timeslice, + /// The owner of the Region. + pub owner: AccountId, + /// The amount paid to Polkadot for this Region, or `None` if renewal is not allowed. + pub paid: Option, +} +pub type RegionRecordOf = RegionRecord<::AccountId, BalanceOf>; + +/// An distinct item which can be scheduled on a Polkadot Core. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ScheduleItem { + /// The regularity parts in which this Item will be scheduled on the Core. + pub mask: CoreMask, + /// The job that the Core should be doing. + pub assignment: CoreAssignment, +} +pub type Schedule = BoundedVec>; + +/// The record body of a Region which was contributed to the Instantaneous Coretime Pool. This helps +/// with making pro rata payments to contributors. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ContributionRecord { + /// The end of the Region contributed. + pub length: Timeslice, + /// The identity of the contributor. + pub payee: AccountId, +} +pub type ContributionRecordOf = ContributionRecord<::AccountId>; + +/// A per-timeslice bookkeeping record for tracking Instantaneous Coretime Pool activity and +/// making proper payments to contributors. +#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct InstaPoolHistoryRecord { + /// The total amount of Coretime (measured in Core Mask Bits minus any contributions which have + /// already been paid out. + pub private_contributions: CoreMaskBitCount, + /// The total amount of Coretime (measured in Core Mask Bits contributed by the Polkadot System + /// in this timeslice. + pub system_contributions: CoreMaskBitCount, + /// The payout remaining for the `private_contributions`, or `None` if the revenue is not yet + /// known. + pub maybe_payout: Option, +} +pub type InstaPoolHistoryRecordOf = InstaPoolHistoryRecord>; + +/// How much of a core has been assigned or, if completely assigned, the workload itself. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum CompletionStatus { + /// The core is not fully assigned; the inner is the parts which have. + Partial(CoreMask), + /// The core is fully assigned; the inner is the workload which has been assigned. + Complete(Schedule), +} +impl CompletionStatus { + /// Return reference to the complete workload, or `None` if incomplete. + pub fn complete(&self) -> Option<&Schedule> { + match self { + Self::Complete(s) => Some(s), + Self::Partial(_) => None, + } + } + /// Return the complete workload, or `None` if incomplete. + pub fn drain_complete(self) -> Option { + match self { + Self::Complete(s) => Some(s), + Self::Partial(_) => None, + } + } +} + +/// The identity of a possible Core workload renewal. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct AllowedRenewalId { + /// The core whose workload at the sale ending with `when` may be renewed to begin at `when`. + pub core: CoreIndex, + /// The point in time that the renewable workload on `core` ends and a fresh renewal may begin. + pub when: Timeslice, +} + +/// A record of an allowed renewal. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct AllowedRenewalRecord { + /// The price for which the next renewal can be made. + pub price: Balance, + /// The workload which will be scheduled on the Core in the case a renewal is made, or if + /// incomplete, then the parts of the core which have been scheduled. + pub completion: CompletionStatus, +} +pub type AllowedRenewalRecordOf = AllowedRenewalRecord>; + +/// General status of the system. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct StatusRecord { + /// The total number of cores which can be assigned (one plus the maximum index which can + /// be used in `Coretime::assign`). + pub core_count: CoreIndex, + /// The current size of the Instantaneous Coretime Pool, measured in + /// Core Mask Bits. + pub private_pool_size: CoreMaskBitCount, + /// The current amount of the Instantaneous Coretime Pool which is provided by the Polkadot + /// System, rather than provided as a result of privately operated Coretime. + pub system_pool_size: CoreMaskBitCount, + /// The last (Relay-chain) timeslice which we committed to the Relay-chain. + pub last_committed_timeslice: Timeslice, + /// The timeslice of the last time we ticked. + pub last_timeslice: Timeslice, +} + +/// A record of flux in the InstaPool. +#[derive( + Encode, Decode, Clone, Copy, Default, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen, +)] +pub struct PoolIoRecord { + /// The total change of the portion of the pool supplied by purchased Bulk Coretime, measured + /// in Core Mask Bits. + pub private: SignedCoreMaskBitCount, + /// The total change of the portion of the pool supplied by the Polkaot System, measured in + /// Core Mask Bits. + pub system: SignedCoreMaskBitCount, +} + +/// The status of a Bulk Coretime Sale. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct SaleInfoRecord { + /// The local block number at which the sale will/did start. + pub sale_start: BlockNumber, + /// The length in blocks of the Leadin Period (where the price is decreasing). + pub leadin_length: BlockNumber, + /// The price of Bulk Coretime after the Leadin Period. + pub price: Balance, + /// The first timeslice of the Regions which are being sold in this sale. + pub region_begin: Timeslice, + /// The timeslice on which the Regions which are being sold in the sale terminate. (i.e. One + /// after the last timeslice which the Regions control.) + pub region_end: Timeslice, + /// The number of cores we want to sell, ideally. Selling this amount would result in no + /// change to the price for the next sale. + pub ideal_cores_sold: CoreIndex, + /// Number of cores which are/have been offered for sale. + pub cores_offered: CoreIndex, + /// The index of the first core which is for sale. Core of Regions which are sold have + /// incrementing indices from this. + pub first_core: CoreIndex, + /// The latest price at which Bulk Coretime was purchased until surpassing the ideal number of + /// cores were sold. + pub sellout_price: Option, + /// Number of cores which have been sold; never more than cores_offered. + pub cores_sold: CoreIndex, +} +pub type SaleInfoRecordOf = SaleInfoRecord, BlockNumberFor>; + +/// Record for Polkadot Core reservations (generally tasked with the maintenance of System +/// Chains). +pub type ReservationsRecord = BoundedVec; +pub type ReservationsRecordOf = ReservationsRecord<::MaxReservedCores>; + +/// Information on a single legacy lease. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct LeaseRecordItem { + /// The timeslice until the lease is valid. + pub until: Timeslice, + /// The task which the lease is for. + pub task: TaskId, +} + +/// Record for Polkadot Core legacy leases. +pub type LeasesRecord = BoundedVec; +pub type LeasesRecordOf = LeasesRecord<::MaxLeasedCores>; + +/// Configuration of this pallet. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ConfigRecord { + /// The number of Relay-chain blocks in advance which scheduling should be fixed and the + /// `Coretime::assign` API used to inform the Relay-chain. + pub advance_notice: RelayBlockNumber, + /// The length in blocks of the Interlude Period for forthcoming sales. + pub interlude_length: BlockNumber, + /// The length in blocks of the Leadin Period for forthcoming sales. + pub leadin_length: BlockNumber, + /// The length in timeslices of Regions which are up for sale in forthcoming sales. + pub region_length: Timeslice, + /// The proportion of cores available for sale which should be sold in order for the price + /// to remain the same in the next sale. + pub ideal_bulk_proportion: Perbill, + /// An artificial limit to the number of cores which are allowed to be sold. If `Some` then + /// no more cores will be sold than this. + pub limit_cores_offered: Option, + /// The amount by which the renewal price increases each sale period. + pub renewal_bump: Perbill, + /// The duration by which rewards for contributions to the InstaPool must be collected. + pub contribution_timeout: Timeslice, +} +pub type ConfigRecordOf = ConfigRecord, RelayBlockNumberOf>; + +impl ConfigRecord +where + BlockNumber: sp_arithmetic::traits::Zero, +{ + /// Check the config for basic validity constraints. + pub(crate) fn validate(&self) -> Result<(), ()> { + if self.leadin_length.is_zero() { + return Err(()) + } + + Ok(()) + } +} diff --git a/frame/broker/src/utility_impls.rs b/frame/broker/src/utility_impls.rs new file mode 100644 index 0000000000000..99c4de32f7767 --- /dev/null +++ b/frame/broker/src/utility_impls.rs @@ -0,0 +1,121 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use frame_support::{ + pallet_prelude::{DispatchResult, *}, + traits::{ + fungible::Balanced, + tokens::{Fortitude::Polite, Precision::Exact, Preservation::Expendable}, + OnUnbalanced, + }, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use sp_arithmetic::{ + traits::{SaturatedConversion, Saturating}, + FixedPointNumber, FixedU64, +}; +use sp_runtime::traits::AccountIdConversion; + +impl Pallet { + pub fn current_timeslice() -> Timeslice { + let latest = T::Coretime::latest(); + let timeslice_period = T::TimeslicePeriod::get(); + (latest / timeslice_period).saturated_into() + } + + pub fn latest_timeslice_ready_to_commit(config: &ConfigRecordOf) -> Timeslice { + let latest = T::Coretime::latest(); + let advanced = latest.saturating_add(config.advance_notice); + let timeslice_period = T::TimeslicePeriod::get(); + (advanced / timeslice_period).saturated_into() + } + + pub fn next_timeslice_to_commit( + config: &ConfigRecordOf, + status: &StatusRecord, + ) -> Option { + if status.last_committed_timeslice < Self::latest_timeslice_ready_to_commit(config) { + Some(status.last_committed_timeslice + 1) + } else { + None + } + } + + pub fn account_id() -> T::AccountId { + T::PalletId::get().into_account_truncating() + } + + pub fn sale_price(sale: &SaleInfoRecordOf, now: BlockNumberFor) -> BalanceOf { + let num = now.saturating_sub(sale.sale_start).min(sale.leadin_length).saturated_into(); + let through = FixedU64::from_rational(num, sale.leadin_length.saturated_into()); + T::PriceAdapter::leadin_factor_at(through).saturating_mul_int(sale.price) + } + + pub(crate) fn charge(who: &T::AccountId, amount: BalanceOf) -> DispatchResult { + let credit = T::Currency::withdraw(&who, amount, Exact, Expendable, Polite)?; + T::OnRevenue::on_unbalanced(credit); + Ok(()) + } + + pub(crate) fn issue( + core: CoreIndex, + begin: Timeslice, + end: Timeslice, + owner: T::AccountId, + paid: Option>, + ) -> RegionId { + let id = RegionId { begin, core, mask: CoreMask::complete() }; + let record = RegionRecord { end, owner, paid }; + Regions::::insert(&id, &record); + id + } + + pub(crate) fn utilize( + mut region_id: RegionId, + maybe_check_owner: Option, + finality: Finality, + ) -> Result)>, Error> { + let status = Status::::get().ok_or(Error::::Uninitialized)?; + let region = Regions::::get(®ion_id).ok_or(Error::::UnknownRegion)?; + + if let Some(check_owner) = maybe_check_owner { + ensure!(check_owner == region.owner, Error::::NotOwner); + } + + Regions::::remove(®ion_id); + + let last_committed_timeslice = status.last_committed_timeslice; + if region_id.begin <= last_committed_timeslice { + region_id.begin = last_committed_timeslice + 1; + if region_id.begin >= region.end { + let duration = region.end.saturating_sub(region_id.begin); + Self::deposit_event(Event::RegionDropped { region_id, duration }); + return Ok(None) + } + } else { + Workplan::::mutate_extant((region_id.begin, region_id.core), |p| { + p.retain(|i| (i.mask & region_id.mask).is_void()) + }); + } + if finality == Finality::Provisional { + Regions::::insert(®ion_id, ®ion); + } + + Ok(Some((region_id, region))) + } +} diff --git a/frame/broker/src/weights.rs b/frame/broker/src/weights.rs new file mode 100644 index 0000000000000..93b568bf2a035 --- /dev/null +++ b/frame/broker/src/weights.rs @@ -0,0 +1,794 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for `pallet_broker` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-ynta1nyy-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// target/production/substrate-node +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_broker +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/broker/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_broker`. +pub trait WeightInfo { + fn configure() -> Weight; + fn reserve() -> Weight; + fn unreserve() -> Weight; + fn set_lease() -> Weight; + fn start_sales(n: u32, ) -> Weight; + fn purchase() -> Weight; + fn renew() -> Weight; + fn transfer() -> Weight; + fn partition() -> Weight; + fn interlace() -> Weight; + fn assign() -> Weight; + fn pool() -> Weight; + fn claim_revenue(m: u32, ) -> Weight; + fn purchase_credit() -> Weight; + fn drop_region() -> Weight; + fn drop_contribution() -> Weight; + fn drop_history() -> Weight; + fn drop_renewal() -> Weight; + fn request_core_count(n: u32, ) -> Weight; + fn process_core_count(n: u32, ) -> Weight; + fn process_revenue() -> Weight; + fn rotate_sale(n: u32, ) -> Weight; + fn process_pool() -> Weight; + fn process_core_schedule() -> Weight; + fn request_revenue_info_at() -> Weight; +} + +/// Weights for `pallet_broker` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Broker::Configuration` (r:0 w:1) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + fn configure() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_448_000 picoseconds. + Weight::from_parts(3_729_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Reservations` (r:1 w:1) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + fn reserve() -> Weight { + // Proof Size summary in bytes: + // Measured: `5016` + // Estimated: `7496` + // Minimum execution time: 22_537_000 picoseconds. + Weight::from_parts(23_335_000, 7496) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Reservations` (r:1 w:1) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + fn unreserve() -> Weight { + // Proof Size summary in bytes: + // Measured: `6218` + // Estimated: `7496` + // Minimum execution time: 21_668_000 picoseconds. + Weight::from_parts(22_442_000, 7496) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + fn set_lease() -> Weight { + // Proof Size summary in bytes: + // Measured: `239` + // Estimated: `1526` + // Minimum execution time: 13_606_000 picoseconds. + Weight::from_parts(14_104_000, 1526) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolIo` (r:3 w:3) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::Reservations` (r:1 w:0) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:0 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:0 w:1) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:0 w:10) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn start_sales(_n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `6330` + // Estimated: `8499` + // Minimum execution time: 64_012_000 picoseconds. + Weight::from_parts(67_819_922, 8499) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(16_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:1 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Broker::Regions` (r:0 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn purchase() -> Weight { + // Proof Size summary in bytes: + // Measured: `568` + // Estimated: `2053` + // Minimum execution time: 48_110_000 picoseconds. + Weight::from_parts(49_234_000, 2053) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:1 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Broker::AllowedRenewals` (r:1 w:2) + /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Broker::Workplan` (r:0 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + fn renew() -> Weight { + // Proof Size summary in bytes: + // Measured: `686` + // Estimated: `4698` + // Minimum execution time: 69_580_000 picoseconds. + Weight::from_parts(70_914_000, 4698) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `495` + // Estimated: `3550` + // Minimum execution time: 17_687_000 picoseconds. + Weight::from_parts(18_573_000, 3550) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Regions` (r:1 w:2) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn partition() -> Weight { + // Proof Size summary in bytes: + // Measured: `495` + // Estimated: `3550` + // Minimum execution time: 19_675_000 picoseconds. + Weight::from_parts(20_234_000, 3550) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Regions` (r:1 w:2) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn interlace() -> Weight { + // Proof Size summary in bytes: + // Measured: `495` + // Estimated: `3550` + // Minimum execution time: 19_426_000 picoseconds. + Weight::from_parts(20_414_000, 3550) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:1 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + fn assign() -> Weight { + // Proof Size summary in bytes: + // Measured: `740` + // Estimated: `4681` + // Minimum execution time: 31_751_000 picoseconds. + Weight::from_parts(32_966_000, 4681) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:1 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolIo` (r:2 w:2) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolContribution` (r:0 w:1) + /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `775` + // Estimated: `5996` + // Minimum execution time: 36_709_000 picoseconds. + Weight::from_parts(38_930_000, 5996) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Broker::InstaPoolContribution` (r:1 w:1) + /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolHistory` (r:3 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `m` is `[1, 3]`. + fn claim_revenue(m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `720` + // Estimated: `6196 + m * (2520 ±0)` + // Minimum execution time: 55_510_000 picoseconds. + Weight::from_parts(56_665_061, 6196) + // Standard Error: 61_729 + .saturating_add(Weight::from_parts(1_724_824, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(Weight::from_parts(0, 2520).saturating_mul(m.into())) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn purchase_credit() -> Weight { + // Proof Size summary in bytes: + // Measured: `103` + // Estimated: `3593` + // Minimum execution time: 44_992_000 picoseconds. + Weight::from_parts(46_225_000, 3593) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn drop_region() -> Weight { + // Proof Size summary in bytes: + // Measured: `603` + // Estimated: `3550` + // Minimum execution time: 28_207_000 picoseconds. + Weight::from_parts(28_707_000, 3550) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolContribution` (r:1 w:1) + /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn drop_contribution() -> Weight { + // Proof Size summary in bytes: + // Measured: `601` + // Estimated: `3533` + // Minimum execution time: 31_813_000 picoseconds. + Weight::from_parts(32_612_000, 3533) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolHistory` (r:1 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn drop_history() -> Weight { + // Proof Size summary in bytes: + // Measured: `829` + // Estimated: `3593` + // Minimum execution time: 38_571_000 picoseconds. + Weight::from_parts(39_493_000, 3593) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::AllowedRenewals` (r:1 w:1) + /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + fn drop_renewal() -> Weight { + // Proof Size summary in bytes: + // Measured: `525` + // Estimated: `4698` + // Minimum execution time: 24_714_000 picoseconds. + Weight::from_parts(25_288_000, 4698) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) + /// The range of component `n` is `[0, 1000]`. + fn request_core_count(_n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_258_000 picoseconds. + Weight::from_parts(7_925_570, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) + /// The range of component `n` is `[0, 1000]`. + fn process_core_count(_n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `97` + // Estimated: `3562` + // Minimum execution time: 7_136_000 picoseconds. + Weight::from_parts(7_788_194, 3562) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Broker::InstaPoolHistory` (r:0 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn process_revenue() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_049_000 picoseconds. + Weight::from_parts(6_311_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::InstaPoolIo` (r:3 w:3) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::Reservations` (r:1 w:0) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:0 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:0 w:10) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn rotate_sale(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `6281` + // Estimated: `8499` + // Minimum execution time: 47_504_000 picoseconds. + Weight::from_parts(49_778_098, 8499) + // Standard Error: 109 + .saturating_add(Weight::from_parts(427, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(15_u64)) + } + /// Storage: `Broker::InstaPoolIo` (r:1 w:0) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolHistory` (r:0 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn process_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3493` + // Minimum execution time: 9_573_000 picoseconds. + Weight::from_parts(10_034_000, 3493) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Workplan` (r:1 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workload` (r:1 w:1) + /// Proof: `Broker::Workload` (`max_values`: None, `max_size`: Some(1212), added: 3687, mode: `MaxEncodedLen`) + fn process_core_schedule() -> Weight { + // Proof Size summary in bytes: + // Measured: `1423` + // Estimated: `4681` + // Minimum execution time: 21_331_000 picoseconds. + Weight::from_parts(22_235_000, 4681) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + fn request_revenue_info_at() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 191_000 picoseconds. + Weight::from_parts(234_000, 0) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Broker::Configuration` (r:0 w:1) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + fn configure() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_448_000 picoseconds. + Weight::from_parts(3_729_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Reservations` (r:1 w:1) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + fn reserve() -> Weight { + // Proof Size summary in bytes: + // Measured: `5016` + // Estimated: `7496` + // Minimum execution time: 22_537_000 picoseconds. + Weight::from_parts(23_335_000, 7496) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Reservations` (r:1 w:1) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + fn unreserve() -> Weight { + // Proof Size summary in bytes: + // Measured: `6218` + // Estimated: `7496` + // Minimum execution time: 21_668_000 picoseconds. + Weight::from_parts(22_442_000, 7496) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + fn set_lease() -> Weight { + // Proof Size summary in bytes: + // Measured: `239` + // Estimated: `1526` + // Minimum execution time: 13_606_000 picoseconds. + Weight::from_parts(14_104_000, 1526) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolIo` (r:3 w:3) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::Reservations` (r:1 w:0) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:0 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:0 w:1) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:0 w:10) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn start_sales(_n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `6330` + // Estimated: `8499` + // Minimum execution time: 64_012_000 picoseconds. + Weight::from_parts(67_819_922, 8499) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(16_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:1 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Broker::Regions` (r:0 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn purchase() -> Weight { + // Proof Size summary in bytes: + // Measured: `568` + // Estimated: `2053` + // Minimum execution time: 48_110_000 picoseconds. + Weight::from_parts(49_234_000, 2053) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:1 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Broker::AllowedRenewals` (r:1 w:2) + /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Broker::Workplan` (r:0 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + fn renew() -> Weight { + // Proof Size summary in bytes: + // Measured: `686` + // Estimated: `4698` + // Minimum execution time: 69_580_000 picoseconds. + Weight::from_parts(70_914_000, 4698) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + } + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `495` + // Estimated: `3550` + // Minimum execution time: 17_687_000 picoseconds. + Weight::from_parts(18_573_000, 3550) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Regions` (r:1 w:2) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn partition() -> Weight { + // Proof Size summary in bytes: + // Measured: `495` + // Estimated: `3550` + // Minimum execution time: 19_675_000 picoseconds. + Weight::from_parts(20_234_000, 3550) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Regions` (r:1 w:2) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn interlace() -> Weight { + // Proof Size summary in bytes: + // Measured: `495` + // Estimated: `3550` + // Minimum execution time: 19_426_000 picoseconds. + Weight::from_parts(20_414_000, 3550) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:1 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + fn assign() -> Weight { + // Proof Size summary in bytes: + // Measured: `740` + // Estimated: `4681` + // Minimum execution time: 31_751_000 picoseconds. + Weight::from_parts(32_966_000, 4681) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:1 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolIo` (r:2 w:2) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolContribution` (r:0 w:1) + /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `775` + // Estimated: `5996` + // Minimum execution time: 36_709_000 picoseconds. + Weight::from_parts(38_930_000, 5996) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `Broker::InstaPoolContribution` (r:1 w:1) + /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolHistory` (r:3 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `m` is `[1, 3]`. + fn claim_revenue(m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `720` + // Estimated: `6196 + m * (2520 ±0)` + // Minimum execution time: 55_510_000 picoseconds. + Weight::from_parts(56_665_061, 6196) + // Standard Error: 61_729 + .saturating_add(Weight::from_parts(1_724_824, 0).saturating_mul(m.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(Weight::from_parts(0, 2520).saturating_mul(m.into())) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn purchase_credit() -> Weight { + // Proof Size summary in bytes: + // Measured: `103` + // Estimated: `3593` + // Minimum execution time: 44_992_000 picoseconds. + Weight::from_parts(46_225_000, 3593) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::Regions` (r:1 w:1) + /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn drop_region() -> Weight { + // Proof Size summary in bytes: + // Measured: `603` + // Estimated: `3550` + // Minimum execution time: 28_207_000 picoseconds. + Weight::from_parts(28_707_000, 3550) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolContribution` (r:1 w:1) + /// Proof: `Broker::InstaPoolContribution` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn drop_contribution() -> Weight { + // Proof Size summary in bytes: + // Measured: `601` + // Estimated: `3533` + // Minimum execution time: 31_813_000 picoseconds. + Weight::from_parts(32_612_000, 3533) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Configuration` (r:1 w:0) + /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolHistory` (r:1 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn drop_history() -> Weight { + // Proof Size summary in bytes: + // Measured: `829` + // Estimated: `3593` + // Minimum execution time: 38_571_000 picoseconds. + Weight::from_parts(39_493_000, 3593) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Status` (r:1 w:0) + /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) + /// Storage: `Broker::AllowedRenewals` (r:1 w:1) + /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) + fn drop_renewal() -> Weight { + // Proof Size summary in bytes: + // Measured: `525` + // Estimated: `4698` + // Minimum execution time: 24_714_000 picoseconds. + Weight::from_parts(25_288_000, 4698) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:0 w:1) + /// The range of component `n` is `[0, 1000]`. + fn request_core_count(_n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_258_000 picoseconds. + Weight::from_parts(7_925_570, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:0) + /// The range of component `n` is `[0, 1000]`. + fn process_core_count(_n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `97` + // Estimated: `3562` + // Minimum execution time: 7_136_000 picoseconds. + Weight::from_parts(7_788_194, 3562) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Broker::InstaPoolHistory` (r:0 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn process_revenue() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_049_000 picoseconds. + Weight::from_parts(6_311_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::InstaPoolIo` (r:3 w:3) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::Reservations` (r:1 w:0) + /// Proof: `Broker::Reservations` (`max_values`: Some(1), `max_size`: Some(6011), added: 6506, mode: `MaxEncodedLen`) + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + /// Storage: `Broker::SaleInfo` (r:0 w:1) + /// Proof: `Broker::SaleInfo` (`max_values`: Some(1), `max_size`: Some(57), added: 552, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workplan` (r:0 w:10) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn rotate_sale(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `6281` + // Estimated: `8499` + // Minimum execution time: 47_504_000 picoseconds. + Weight::from_parts(49_778_098, 8499) + // Standard Error: 109 + .saturating_add(Weight::from_parts(427, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(15_u64)) + } + /// Storage: `Broker::InstaPoolIo` (r:1 w:0) + /// Proof: `Broker::InstaPoolIo` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Broker::InstaPoolHistory` (r:0 w:1) + /// Proof: `Broker::InstaPoolHistory` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + fn process_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3493` + // Minimum execution time: 9_573_000 picoseconds. + Weight::from_parts(10_034_000, 3493) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Broker::Workplan` (r:1 w:1) + /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) + /// Storage: `Broker::Workload` (r:1 w:1) + /// Proof: `Broker::Workload` (`max_values`: None, `max_size`: Some(1212), added: 3687, mode: `MaxEncodedLen`) + fn process_core_schedule() -> Weight { + // Proof Size summary in bytes: + // Measured: `1423` + // Estimated: `4681` + // Minimum execution time: 21_331_000 picoseconds. + Weight::from_parts(22_235_000, 4681) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + fn request_revenue_info_at() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 191_000 picoseconds. + Weight::from_parts(234_000, 0) + } +} diff --git a/frame/child-bounties/Cargo.toml b/frame/child-bounties/Cargo.toml index 7613c462eb0c2..2db68263a02d4 100644 --- a/frame/child-bounties/Cargo.toml +++ b/frame/child-bounties/Cargo.toml @@ -32,13 +32,14 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "pallet-bounties/std", "pallet-treasury/std", "scale-info/std", @@ -46,17 +47,16 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] runtime-benchmarks = [ "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-bounties/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -64,5 +64,5 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-bounties/try-runtime", "pallet-treasury/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 2ca447434f4b0..b80de34ecc2ba 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -47,5 +47,5 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 1084091173934..ac6ad39eac5a4 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -42,13 +42,13 @@ #![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "128"] +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_io::storage; use sp_runtime::{traits::Hash, RuntimeDebug}; use sp_std::{marker::PhantomData, prelude::*, result}; use frame_support::{ - codec::{Decode, Encode, MaxEncodedLen}, dispatch::{ DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo, diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index a5c309adc97bc..75a6093dffac8 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -64,45 +64,45 @@ pallet-proxy = { version = "4.0.0-dev", path = "../proxy" } sp-keystore = { version = "0.27.0", path = "../../primitives/keystore" } [features] -default = ["std"] +default = [ "std" ] std = [ - "serde", "codec/std", - "scale-info/std", - "sp-core/std", - "sp-runtime/std", - "sp-io/std", - "sp-std/std", + "environmental/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "wasm-instrument/std", - "wasmi/std", - "pallet-contracts-primitives/std", - "pallet-contracts-proc-macro/full", "log/std", - "rand/std", - "environmental/std", "pallet-balances?/std", + "pallet-contracts-primitives/std", + "pallet-contracts-proc-macro/full", "pallet-insecure-randomness-collective-flip/std", "pallet-proxy/std", "pallet-timestamp/std", "pallet-utility/std", + "rand/std", + "scale-info/std", + "serde", "sp-api/std", - "sp-keystore/std" + "sp-core/std", + "sp-io/std", + "sp-keystore/std", + "sp-runtime/std", + "sp-std/std", + "wasm-instrument/std", + "wasmi/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "rand", - "rand_pcg", - "wasm-instrument", - "pallet-balances/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-utility/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "rand", + "rand_pcg", + "sp-runtime/runtime-benchmarks", + "wasm-instrument", ] try-runtime = [ "frame-support/try-runtime", @@ -114,4 +114,3 @@ try-runtime = [ "pallet-utility/try-runtime", "sp-runtime/try-runtime", ] -unsafe-debug = [] diff --git a/frame/contracts/primitives/Cargo.toml b/frame/contracts/primitives/Cargo.toml index facfe34e1bc50..c868035c2404d 100644 --- a/frame/contracts/primitives/Cargo.toml +++ b/frame/contracts/primitives/Cargo.toml @@ -23,11 +23,11 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../pr sp-weights = { version = "20.0.0", default-features = false, path = "../../../primitives/weights" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", + "scale-info/std", "sp-runtime/std", "sp-std/std", - "scale-info/std", - "sp-weights/std" + "sp-weights/std", ] diff --git a/frame/contracts/src/debug.rs b/frame/contracts/src/debug.rs new file mode 100644 index 0000000000000..a92f428c8f8a4 --- /dev/null +++ b/frame/contracts/src/debug.rs @@ -0,0 +1,55 @@ +pub use crate::exec::ExportedFunction; +use crate::{CodeHash, Config, LOG_TARGET}; +use pallet_contracts_primitives::ExecReturnValue; + +/// Umbrella trait for all interfaces that serves for debugging. +pub trait Debugger: Tracing {} + +impl Debugger for V where V: Tracing {} + +/// Defines methods to capture contract calls, enabling external observers to +/// measure, trace, and react to contract interactions. +pub trait Tracing { + /// The type of [`CallSpan`] that is created by this trait. + type CallSpan: CallSpan; + + /// Creates a new call span to encompass the upcoming contract execution. + /// + /// This method should be invoked just before the execution of a contract and + /// marks the beginning of a traceable span of execution. + /// + /// # Arguments + /// + /// * `code_hash` - The code hash of the contract being called. + /// * `entry_point` - Describes whether the call is the constructor or a regular call. + /// * `input_data` - The raw input data of the call. + fn new_call_span( + code_hash: &CodeHash, + entry_point: ExportedFunction, + input_data: &[u8], + ) -> Self::CallSpan; +} + +/// Defines a span of execution for a contract call. +pub trait CallSpan { + /// Called just after the execution of a contract. + /// + /// # Arguments + /// + /// * `output` - The raw output of the call. + fn after_call(self, output: &ExecReturnValue); +} + +impl Tracing for () { + type CallSpan = (); + + fn new_call_span(code_hash: &CodeHash, entry_point: ExportedFunction, input_data: &[u8]) { + log::trace!(target: LOG_TARGET, "call {entry_point:?} hash: {code_hash:?}, input_data: {input_data:?}") + } +} + +impl CallSpan for () { + fn after_call(self, output: &ExecReturnValue) { + log::trace!(target: LOG_TARGET, "call result {output:?}") + } +} diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index a4d0760e6c0ac..1ba44220ff8dc 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -15,9 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(feature = "unsafe-debug")] -use crate::unsafe_debug::ExecutionObserver; use crate::{ + debug::{CallSpan, Tracing}, gas::GasMeter, storage::{self, meter::Diff, WriteOutcome}, BalanceOf, CodeHash, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf, @@ -908,20 +907,15 @@ where // Every non delegate call or instantiate also optionally transfers the balance. self.initial_transfer()?; - #[cfg(feature = "unsafe-debug")] - let (code_hash, input_clone) = { - let code_hash = *executable.code_hash(); - T::Debug::before_call(&code_hash, entry_point, &input_data); - (code_hash, input_data.clone()) - }; + let call_span = + T::Debug::new_call_span(executable.code_hash(), entry_point, &input_data); // Call into the Wasm blob. let output = executable .execute(self, &entry_point, input_data) .map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?; - #[cfg(feature = "unsafe-debug")] - T::Debug::after_call(&code_hash, entry_point, input_clone, &output); + call_span.after_call(&output); // Avoid useless work that would be reverted anyways. if output.did_revert() { diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index a511ac81a73b7..2b9dd07b3f6fe 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -96,14 +96,14 @@ mod storage; mod wasm; pub mod chain_extension; +pub mod debug; pub mod migration; -pub mod unsafe_debug; pub mod weights; #[cfg(test)] mod tests; use crate::{ - exec::{AccountIdOf, ErrorOrigin, ExecError, Executable, Key, Stack as ExecStack}, + exec::{AccountIdOf, ErrorOrigin, ExecError, Executable, Key, MomentOf, Stack as ExecStack}, gas::GasMeter, storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager}, wasm::{CodeInfo, WasmBlob}, @@ -122,9 +122,13 @@ use frame_support::{ ConstU32, Contains, Get, Randomness, Time, }, weights::Weight, - BoundedVec, RuntimeDebug, RuntimeDebugNoBound, + BoundedVec, DefaultNoBound, RuntimeDebugNoBound, +}; +use frame_system::{ + ensure_signed, + pallet_prelude::{BlockNumberFor, OriginFor}, + EventRecord, Pallet as System, }; -use frame_system::{ensure_signed, pallet_prelude::OriginFor, EventRecord, Pallet as System}; use pallet_contracts_primitives::{ Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult, ContractInstantiateResult, ContractResult, ExecReturnValue, GetStorageResult, @@ -132,11 +136,15 @@ use pallet_contracts_primitives::{ }; use scale_info::TypeInfo; use smallvec::Array; -use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup, Zero}; +use sp_runtime::{ + traits::{Convert, Hash, Saturating, StaticLookup, Zero}, + RuntimeDebug, +}; use sp_std::{fmt::Debug, prelude::*}; pub use crate::{ address::{AddressGenerator, DefaultAddressGenerator}, + debug::Tracing, exec::Frame, migration::{MigrateSequence, Migration, NoopMigration}, pallet::*, @@ -179,9 +187,40 @@ const SENTINEL: u32 = u32::MAX; /// Example: `RUST_LOG=runtime::contracts=debug my_code --dev` const LOG_TARGET: &str = "runtime::contracts"; +/// Wrapper around `PhantomData` to prevent it being filtered by `scale-info`. +/// +/// `scale-info` filters out `PhantomData` fields because usually we are only interested +/// in sized types. However, when trying to communicate **types** as opposed to **values** +/// we want to have those zero sized types be included. +#[derive(Encode, Decode, DefaultNoBound, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct EnvironmentType(PhantomData); + +/// List of all runtime configurable types that are used in the communication between +/// `pallet-contracts` and any given contract. +/// +/// Since those types are configurable they can vary between +/// chains all using `pallet-contracts`. Hence we need a mechanism to communicate those types +/// in a way that can be consumed by offchain tooling. +/// +/// This type only exists in order to appear in the metadata where it can be read by +/// offchain tooling. +#[derive(Encode, Decode, DefaultNoBound, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[scale_info(skip_type_params(T))] +pub struct Environment { + account_id: EnvironmentType>, + balance: EnvironmentType>, + hash: EnvironmentType<::Hash>, + hasher: EnvironmentType<::Hashing>, + timestamp: EnvironmentType>, + block_number: EnvironmentType>, +} + #[frame_support::pallet] pub mod pallet { use super::*; + use crate::debug::Debugger; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use sp_runtime::Perbill; @@ -353,13 +392,18 @@ pub mod pallet { /// ``` type Migrations: MigrateSequence; - /// Type that provides debug handling for the contract execution process. - /// - /// # Warning + /// # Note + /// For most production chains, it's recommended to use the `()` implementation of this + /// trait. This implementation offers additional logging when the log target + /// "runtime::contracts" is set to trace. + type Debug: Debugger; + + /// Type that bundles together all the runtime configurable interface types. /// - /// Do **not** use it in a production environment or for benchmarking purposes. - #[cfg(feature = "unsafe-debug")] - type Debug: unsafe_debug::UnsafeDebug; + /// This is not a real config. We just mention the type here as constant so that + /// its type appears in the metadata. Only valid value is `()`. + #[pallet::constant] + type Environment: Get>; } #[pallet::hooks] diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs index d8ebc25ed9a22..3e3d6f37884c7 100644 --- a/frame/contracts/src/migration.rs +++ b/frame/contracts/src/migration.rs @@ -69,7 +69,6 @@ include!(concat!(env!("OUT_DIR"), "/migration_codegen.rs")); use crate::{weights::WeightInfo, Config, Error, MigrationInProgress, Pallet, Weight, LOG_TARGET}; use codec::{Codec, Decode}; use frame_support::{ - codec, pallet_prelude::*, traits::{ConstU32, OnRuntimeUpgrade}, }; diff --git a/frame/contracts/src/migration/v09.rs b/frame/contracts/src/migration/v09.rs index e6c6642955642..98fcccc2c0bec 100644 --- a/frame/contracts/src/migration/v09.rs +++ b/frame/contracts/src/migration/v09.rs @@ -23,7 +23,7 @@ use crate::{ CodeHash, Config, Determinism, Pallet, Weight, LOG_TARGET, }; use codec::{Decode, Encode}; -use frame_support::{codec, pallet_prelude::*, storage_alias, DefaultNoBound, Identity}; +use frame_support::{pallet_prelude::*, storage_alias, DefaultNoBound, Identity}; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; use sp_std::prelude::*; diff --git a/frame/contracts/src/migration/v10.rs b/frame/contracts/src/migration/v10.rs index e33c8d080ad9f..f02e28f6fde32 100644 --- a/frame/contracts/src/migration/v10.rs +++ b/frame/contracts/src/migration/v10.rs @@ -27,7 +27,6 @@ use crate::{ use codec::{Decode, Encode}; use core::cmp::{max, min}; use frame_support::{ - codec, pallet_prelude::*, storage_alias, traits::{ diff --git a/frame/contracts/src/migration/v11.rs b/frame/contracts/src/migration/v11.rs index 8123d73aee560..a5b11f6e08977 100644 --- a/frame/contracts/src/migration/v11.rs +++ b/frame/contracts/src/migration/v11.rs @@ -27,7 +27,7 @@ use crate::{ use sp_runtime::TryRuntimeError; use codec::{Decode, Encode}; -use frame_support::{codec, pallet_prelude::*, storage_alias, DefaultNoBound}; +use frame_support::{pallet_prelude::*, storage_alias, DefaultNoBound}; use sp_std::{marker::PhantomData, prelude::*}; mod old { use super::*; diff --git a/frame/contracts/src/migration/v12.rs b/frame/contracts/src/migration/v12.rs index 75018f943d100..eb045aa42e9d7 100644 --- a/frame/contracts/src/migration/v12.rs +++ b/frame/contracts/src/migration/v12.rs @@ -25,7 +25,7 @@ use crate::{ }; use codec::{Decode, Encode}; use frame_support::{ - codec, pallet_prelude::*, storage_alias, traits::ReservableCurrency, DefaultNoBound, Identity, + pallet_prelude::*, storage_alias, traits::ReservableCurrency, DefaultNoBound, Identity, }; use scale_info::prelude::format; use sp_core::hexdisplay::HexDisplay; diff --git a/frame/contracts/src/migration/v13.rs b/frame/contracts/src/migration/v13.rs index 774b04a9c65d7..dd2eb12eb62a5 100644 --- a/frame/contracts/src/migration/v13.rs +++ b/frame/contracts/src/migration/v13.rs @@ -24,7 +24,7 @@ use crate::{ AccountIdOf, BalanceOf, CodeHash, Config, Pallet, TrieId, Weight, LOG_TARGET, }; use codec::{Decode, Encode}; -use frame_support::{codec, pallet_prelude::*, storage_alias, DefaultNoBound}; +use frame_support::{pallet_prelude::*, storage_alias, DefaultNoBound}; use sp_runtime::BoundedBTreeMap; use sp_std::prelude::*; diff --git a/frame/contracts/src/migration/v14.rs b/frame/contracts/src/migration/v14.rs index 0daa0ceb5548a..efb49dff4f10a 100644 --- a/frame/contracts/src/migration/v14.rs +++ b/frame/contracts/src/migration/v14.rs @@ -32,7 +32,6 @@ use environmental::Vec; #[cfg(feature = "try-runtime")] use frame_support::traits::fungible::{Inspect, InspectHold}; use frame_support::{ - codec, pallet_prelude::*, storage_alias, traits::{fungible::MutateHold, ReservableCurrency}, diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 5c8fca43ab746..8cc6d00b3d45d 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -16,9 +16,12 @@ // limitations under the License. mod pallet_dummy; -mod unsafe_debug; +mod test_debug; -use self::test_utils::{ensure_stored, expected_deposit, hash}; +use self::{ + test_debug::TestDebug, + test_utils::{ensure_stored, expected_deposit, hash}, +}; use crate::{ self as pallet_contracts, chain_extension::{ @@ -479,8 +482,8 @@ impl Config for Test { type Migrations = crate::migration::codegen::BenchMigrations; type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type MaxDelegateDependencies = MaxDelegateDependencies; - #[cfg(feature = "unsafe-debug")] - type Debug = unsafe_debug::TestDebugger; + type Debug = TestDebug; + type Environment = (); } pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); diff --git a/frame/contracts/src/tests/unsafe_debug.rs b/frame/contracts/src/tests/test_debug.rs similarity index 83% rename from frame/contracts/src/tests/unsafe_debug.rs rename to frame/contracts/src/tests/test_debug.rs index 160a6ed6dc54f..ba936a4588d18 100644 --- a/frame/contracts/src/tests/unsafe_debug.rs +++ b/frame/contracts/src/tests/test_debug.rs @@ -1,7 +1,5 @@ -#![cfg(feature = "unsafe-debug")] - use super::*; -use crate::unsafe_debug::{ExecutionObserver, ExportedFunction}; +use crate::debug::{CallSpan, ExportedFunction, Tracing}; use frame_support::traits::Currency; use pallet_contracts_primitives::ExecReturnValue; use pretty_assertions::assert_eq; @@ -19,31 +17,40 @@ thread_local! { static DEBUG_EXECUTION_TRACE: RefCell> = RefCell::new(Vec::new()); } -pub struct TestDebugger; +pub struct TestDebug; +pub struct TestCallSpan { + code_hash: CodeHash, + call: ExportedFunction, + input: Vec, +} + +impl Tracing for TestDebug { + type CallSpan = TestCallSpan; -impl ExecutionObserver> for TestDebugger { - fn before_call(code_hash: &CodeHash, entry_point: ExportedFunction, input_data: &[u8]) { + fn new_call_span( + code_hash: &CodeHash, + entry_point: ExportedFunction, + input_data: &[u8], + ) -> TestCallSpan { DEBUG_EXECUTION_TRACE.with(|d| { d.borrow_mut().push(DebugFrame { - code_hash: code_hash.clone(), + code_hash: *code_hash, call: entry_point, input: input_data.to_vec(), result: None, }) }); + TestCallSpan { code_hash: *code_hash, call: entry_point, input: input_data.to_vec() } } +} - fn after_call( - code_hash: &CodeHash, - entry_point: ExportedFunction, - input_data: Vec, - output: &ExecReturnValue, - ) { +impl CallSpan for TestCallSpan { + fn after_call(self, output: &ExecReturnValue) { DEBUG_EXECUTION_TRACE.with(|d| { d.borrow_mut().push(DebugFrame { - code_hash: code_hash.clone(), - call: entry_point, - input: input_data, + code_hash: self.code_hash, + call: self.call, + input: self.input, result: Some(output.data.clone()), }) }); diff --git a/frame/contracts/src/unsafe_debug.rs b/frame/contracts/src/unsafe_debug.rs deleted file mode 100644 index 418af5e605d28..0000000000000 --- a/frame/contracts/src/unsafe_debug.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![cfg(feature = "unsafe-debug")] - -pub use crate::exec::ExportedFunction; -use crate::{CodeHash, Vec}; -use pallet_contracts_primitives::ExecReturnValue; - -/// Umbrella trait for all interfaces that serves for debugging, but are not suitable for any -/// production or benchmarking use. -pub trait UnsafeDebug: ExecutionObserver> {} - -impl UnsafeDebug for D where D: ExecutionObserver> {} - -/// Defines the interface between pallet contracts and the outside observer. -/// -/// The intended use is the environment, where the observer holds directly the whole runtime -/// (externalities) and thus can react to the execution breakpoints synchronously. -/// -/// This definitely *should not* be used in any production or benchmarking setting, since handling -/// callbacks might be arbitrarily expensive and thus significantly influence performance. -pub trait ExecutionObserver { - /// Called just before the execution of a contract. - /// - /// # Arguments - /// - /// * `code_hash` - The code hash of the contract being called. - /// * `entry_point` - Describes whether the call is the constructor or a regular call. - /// * `input_data` - The raw input data of the call. - fn before_call(_code_hash: &CodeHash, _entry_point: ExportedFunction, _input_data: &[u8]) {} - - /// Called just after the execution of a contract. - /// - /// # Arguments - /// - /// * `code_hash` - The code hash of the contract being called. - /// * `entry_point` - Describes whether the call was the constructor or a regular call. - /// * `input_data` - The raw input data of the call. - /// * `output` - The raw output of the call. - fn after_call( - _code_hash: &CodeHash, - _entry_point: ExportedFunction, - _input_data: Vec, - _output: &ExecReturnValue, - ) { - } -} - -impl ExecutionObserver for () {} diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index 9d29da70a87d9..ca23ab9fe5dd0 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -26,11 +26,14 @@ use crate::{ use bitflags::bitflags; use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; -use frame_support::{dispatch::DispatchError, ensure, traits::Get, weights::Weight, RuntimeDebug}; +use frame_support::{dispatch::DispatchError, ensure, traits::Get, weights::Weight}; use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags}; use pallet_contracts_proc_macro::define_env; use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256}; -use sp_runtime::traits::{Bounded, Zero}; +use sp_runtime::{ + traits::{Bounded, Zero}, + RuntimeDebug, +}; use sp_std::{fmt, prelude::*}; use wasmi::{core::HostError, errors::LinkerError, Linker, Memory, Store}; diff --git a/frame/conviction-voting/Cargo.toml b/frame/conviction-voting/Cargo.toml index cdc50340f7731..c5e1e5b990516 100644 --- a/frame/conviction-voting/Cargo.toml +++ b/frame/conviction-voting/Cargo.toml @@ -33,34 +33,34 @@ pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", + "pallet-scheduler/std", "scale-info/std", "serde", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "pallet-scheduler/std", - "sp-core/std" ] runtime-benchmarks = [ - "frame-support/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", + "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks" + "pallet-scheduler/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-scheduler/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/core-fellowship/Cargo.toml b/frame/core-fellowship/Cargo.toml index 0d2cb7904efd9..981e71c651383 100644 --- a/frame/core-fellowship/Cargo.toml +++ b/frame/core-fellowship/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -49,5 +49,5 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/core-fellowship/src/lib.rs b/frame/core-fellowship/src/lib.rs index 8f3d9633fcf22..ace614d2bddb9 100644 --- a/frame/core-fellowship/src/lib.rs +++ b/frame/core-fellowship/src/lib.rs @@ -61,6 +61,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_arithmetic::traits::{Saturating, Zero}; +use sp_runtime::RuntimeDebug; use sp_std::{marker::PhantomData, prelude::*}; use frame_support::{ @@ -69,7 +70,7 @@ use frame_support::{ traits::{ tokens::Balance as BalanceTrait, EnsureOrigin, EnsureOriginWithArg, Get, RankedMembers, }, - BoundedVec, RuntimeDebug, + BoundedVec, }; #[cfg(test)] @@ -327,7 +328,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_params())] #[pallet::call_index(1)] pub fn set_params(origin: OriginFor, params: Box>) -> DispatchResult { - T::ParamsOrigin::try_origin(origin).map(|_| ()).or_else(|o| ensure_root(o))?; + T::ParamsOrigin::ensure_origin_or_root(origin)?; Params::::put(params.as_ref()); Self::deposit_event(Event::::ParamsChanged { params: *params }); Ok(()) diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index f29af914295fe..71e52ed73be00 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -33,30 +33,30 @@ pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } pallet-preimage = { version = "4.0.0-dev", path = "../preimage" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", + "pallet-preimage/std", + "pallet-scheduler/std", "scale-info/std", "serde", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std", - "pallet-balances/std", - "pallet-preimage/std", - "pallet-scheduler/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks" + "pallet-scheduler/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -64,5 +64,5 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-preimage/try-runtime", "pallet-scheduler/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/democracy/src/migrations/v1.rs b/frame/democracy/src/migrations/v1.rs index 27a500a615cff..c27f437901b7e 100644 --- a/frame/democracy/src/migrations/v1.rs +++ b/frame/democracy/src/migrations/v1.rs @@ -159,7 +159,7 @@ mod test { tests::{Test as T, *}, types::*, }; - use frame_support::bounded_vec; + use sp_runtime::bounded_vec; #[allow(deprecated)] #[test] diff --git a/frame/election-provider-multi-phase/Cargo.toml b/frame/election-provider-multi-phase/Cargo.toml index a971897a751b0..0ccde14bc4c6c 100644 --- a/frame/election-provider-multi-phase/Cargo.toml +++ b/frame/election-provider-multi-phase/Cargo.toml @@ -48,46 +48,43 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } frame-benchmarking = { version = "4.0.0-dev", path = "../benchmarking" } [features] -default = ["std"] +default = [ "std" ] std = [ - "pallet-election-provider-support-benchmarking?/std", "codec/std", - "scale-info/std", - "log/std", - + "frame-benchmarking?/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", - - "sp-io/std", - "sp-std/std", - "sp-core/std", - "sp-runtime/std", - "sp-npos-elections/std", - "sp-arithmetic/std", - "frame-election-provider-support/std", "log/std", - - "frame-benchmarking?/std", + "log/std", + "pallet-balances/std", + "pallet-election-provider-support-benchmarking?/std", "rand/std", + "scale-info/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-io/std", + "sp-npos-elections/std", + "sp-runtime/std", + "sp-std/std", + "sp-tracing/std", "strum/std", - "pallet-balances/std", - "sp-tracing/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", - "rand", - "strum", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-election-provider-support-benchmarking?/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "rand", + "sp-runtime/runtime-benchmarks", + "strum", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 82c7279879feb..05d151e51ecc5 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -23,7 +23,7 @@ use frame_election_provider_support::{ }; pub use frame_support::{assert_noop, assert_ok, pallet_prelude::GetDefault}; use frame_support::{ - bounded_vec, parameter_types, + parameter_types, traits::{ConstU32, Hooks}, weights::{constants, Weight}, BoundedVec, @@ -42,6 +42,7 @@ use sp_npos_elections::{ ElectionResult, EvaluateSupport, }; use sp_runtime::{ + bounded_vec, testing::Header, traits::{BlakeTwo256, IdentityLookup}, BuildStorage, PerU16, diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index e21e6c5e6d229..af8f632f8a9e3 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -983,15 +983,13 @@ mod tests { TransactionValidityError, }; use codec::Decode; - use frame_benchmarking::Zero; use frame_election_provider_support::IndexAssignment; - use frame_support::{ - assert_noop, assert_ok, bounded_vec, dispatch::Dispatchable, traits::OffchainWorker, - }; + use frame_support::{assert_noop, assert_ok, dispatch::Dispatchable, traits::OffchainWorker}; use sp_npos_elections::ElectionScore; use sp_runtime::{ + bounded_vec, offchain::storage_lock::{BlockAndTime, StorageLock}, - traits::ValidateUnsigned, + traits::{ValidateUnsigned, Zero}, ModuleError, PerU16, Perbill, }; diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index 2aeb06b0442de..975be4ee04044 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -29,27 +29,27 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } [features] -default = ["std"] -fuzz = ["default"] +default = [ "std" ] +fuzz = [ "default" ] std = [ "codec/std", "frame-support/std", "frame-system/std", "scale-info/std", "sp-arithmetic/std", - "sp-npos-elections/std", "sp-core/std", + "sp-io/std", + "sp-npos-elections/std", "sp-runtime/std", "sp-std/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/election-provider-support/benchmarking/Cargo.toml b/frame/election-provider-support/benchmarking/Cargo.toml index 2614c61d4352d..477869b45a5c8 100644 --- a/frame/election-provider-support/benchmarking/Cargo.toml +++ b/frame/election-provider-support/benchmarking/Cargo.toml @@ -20,9 +20,10 @@ frame-election-provider-support = { version = "4.0.0-dev", default-features = fa frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" } sp-runtime = { version = "24.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -30,10 +31,11 @@ std = [ "frame-system/std", "sp-npos-elections/std", "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] diff --git a/frame/election-provider-support/benchmarking/src/lib.rs b/frame/election-provider-support/benchmarking/src/lib.rs index 774b7036fd413..6c75aed0a911d 100644 --- a/frame/election-provider-support/benchmarking/src/lib.rs +++ b/frame/election-provider-support/benchmarking/src/lib.rs @@ -22,8 +22,9 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Decode; -use frame_benchmarking::v1::{benchmarks, Vec}; +use frame_benchmarking::v1::benchmarks; use frame_election_provider_support::{NposSolver, PhragMMS, SequentialPhragmen}; +use sp_std::vec::Vec; pub struct Pallet(frame_system::Pallet); pub trait Config: frame_system::Config {} diff --git a/frame/election-provider-support/src/lib.rs b/frame/election-provider-support/src/lib.rs index 577ac9c0b65a9..2e9ee3b8a48b5 100644 --- a/frame/election-provider-support/src/lib.rs +++ b/frame/election-provider-support/src/lib.rs @@ -82,7 +82,7 @@ //! # use frame_election_provider_support::{*, data_provider}; //! # use sp_npos_elections::{Support, Assignment}; //! # use frame_support::traits::ConstU32; -//! # use frame_support::bounded_vec; +//! # use sp_runtime::bounded_vec; //! //! type AccountId = u64; //! type Balance = u64; @@ -177,14 +177,17 @@ pub mod bounds; pub mod onchain; pub mod traits; -use sp_runtime::traits::{Bounded, Saturating, Zero}; +use sp_runtime::{ + traits::{Bounded, Saturating, Zero}, + RuntimeDebug, +}; use sp_std::{fmt::Debug, prelude::*}; pub use bounds::DataProviderBounds; pub use codec::{Decode, Encode}; /// Re-export the solution generation macro. pub use frame_election_provider_solution_type::generate_solution_type; -pub use frame_support::{traits::Get, weights::Weight, BoundedVec, RuntimeDebug}; +pub use frame_support::{traits::Get, weights::Weight, BoundedVec}; /// Re-export some type as they are used in the interface. pub use sp_arithmetic::PerThing; pub use sp_npos_elections::{ diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 21ee710ea304d..8ac245a360bb5 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -254,7 +254,8 @@ mod tests { } mod mock_data_provider { - use frame_support::{bounded_vec, traits::ConstU32}; + use frame_support::traits::ConstU32; + use sp_runtime::bounded_vec; use super::*; use crate::{data_provider, VoterOf}; diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index ac4f2411dd280..b8c2efdc068c0 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -35,22 +35,22 @@ sp-tracing = { path = "../../primitives/tracing" } substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-npos-elections/std", "sp-runtime/std", - "sp-std/std", - "pallet-balances/std", "sp-staking/std", - "sp-tracing/std" + "sp-std/std", + "sp-tracing/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -58,11 +58,11 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index b23ddda4e8d1c..6912649bd122d 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -107,6 +107,7 @@ use frame_support::{ }, weights::Weight, }; +use log; use scale_info::TypeInfo; use sp_npos_elections::{ElectionResult, ExtendedBalance}; use sp_runtime::{ @@ -309,7 +310,7 @@ pub mod pallet { frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as f32 }; - frame_support::log::debug!( + log::debug!( target: LOG_TARGET, "election weight {}s ({:?}) // chain's block weight {}s ({:?})", to_seconds(&election_weight), diff --git a/frame/elections-phragmen/src/migrations/v3.rs b/frame/elections-phragmen/src/migrations/v3.rs index 204614a5b46cb..cdca1138ebbd2 100644 --- a/frame/elections-phragmen/src/migrations/v3.rs +++ b/frame/elections-phragmen/src/migrations/v3.rs @@ -21,8 +21,9 @@ use super::super::LOG_TARGET; use crate::{Config, Pallet}; use codec::{Decode, Encode, FullCodec}; use frame_support::{ - pallet_prelude::ValueQuery, traits::StorageVersion, weights::Weight, RuntimeDebug, Twox64Concat, + pallet_prelude::ValueQuery, traits::StorageVersion, weights::Weight, Twox64Concat, }; +use sp_runtime::RuntimeDebug; use sp_std::prelude::*; #[derive(Encode, Decode, Clone, Default, RuntimeDebug, PartialEq)] diff --git a/frame/examples/Cargo.toml b/frame/examples/Cargo.toml index af67bef792b6f..e636bc67ea89d 100644 --- a/frame/examples/Cargo.toml +++ b/frame/examples/Cargo.toml @@ -22,18 +22,18 @@ pallet-example-split = { default-features = false, path = "./split" } [features] default = [ "std" ] std = [ - "pallet-example-basic/std", - "pallet-default-config-example/std", - "pallet-example-offchain-worker/std", - "pallet-example-kitchensink/std", - "pallet-dev-mode/std", - "pallet-example-split/std", + "pallet-default-config-example/std", + "pallet-dev-mode/std", + "pallet-example-basic/std", + "pallet-example-kitchensink/std", + "pallet-example-offchain-worker/std", + "pallet-example-split/std", ] try-runtime = [ - "pallet-example-basic/try-runtime", - "pallet-default-config-example/try-runtime", - "pallet-example-offchain-worker/try-runtime", - "pallet-example-kitchensink/try-runtime", - "pallet-dev-mode/try-runtime", - "pallet-example-split/try-runtime", + "pallet-default-config-example/try-runtime", + "pallet-dev-mode/try-runtime", + "pallet-example-basic/try-runtime", + "pallet-example-kitchensink/try-runtime", + "pallet-example-offchain-worker/try-runtime", + "pallet-example-split/try-runtime", ] diff --git a/frame/examples/basic/Cargo.toml b/frame/examples/basic/Cargo.toml index 60bfa1352f482..667afb23c83e1 100644 --- a/frame/examples/basic/Cargo.toml +++ b/frame/examples/basic/Cargo.toml @@ -28,7 +28,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../../primiti sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -37,21 +37,21 @@ std = [ "log/std", "pallet-balances/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/examples/default-config/Cargo.toml b/frame/examples/default-config/Cargo.toml index eac342b736f2e..fbb14730fe7ef 100644 --- a/frame/examples/default-config/Cargo.toml +++ b/frame/examples/default-config/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { default-features = false, path = "../../../primitives/runtime" } sp-std = { default-features = false, path = "../../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -38,5 +38,5 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/examples/default-config/src/lib.rs b/frame/examples/default-config/src/lib.rs index 8715b8c45ff0e..d2eade0ccff1e 100644 --- a/frame/examples/default-config/src/lib.rs +++ b/frame/examples/default-config/src/lib.rs @@ -87,7 +87,7 @@ pub mod pallet { /// A type providing default configurations for this pallet in testing environment. pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] @@ -109,7 +109,7 @@ pub mod pallet { /// example, we simple derive `frame_system::config_preludes::TestDefaultConfig` again. pub struct OtherDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for OtherDefaultConfig {} #[frame_support::register_default_impl(OtherDefaultConfig)] @@ -147,16 +147,7 @@ pub mod tests { #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { // these items are defined by frame-system as `no_default`, so we must specify them here. - // Note that these are types that actually rely on the outer runtime, and can't sensibly - // have an _independent_ default. type Block = Block; - type BlockHashCount = frame_support::traits::ConstU64<10>; - type BaseCallFilter = frame_support::traits::Everything; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; - type PalletInfo = PalletInfo; - type OnSetCode = (); // all of this is coming from `frame_system::config_preludes::TestDefaultConfig`. @@ -177,6 +168,17 @@ pub mod tests { // type BlockWeights = (); // type BlockLength = (); // type DbWeight = (); + // type BaseCallFilter = frame_support::traits::Everything; + // type BlockHashCount = frame_support::traits::ConstU64<10>; + // type OnSetCode = (); + + // These are marked as `#[inject_runtime_type]`. Hence, they are being injected as + // types generated by `construct_runtime`. + + // type RuntimeOrigin = RuntimeOrigin; + // type RuntimeCall = RuntimeCall; + // type RuntimeEvent = RuntimeEvent; + // type PalletInfo = PalletInfo; // you could still overwrite any of them if desired. type SS58Prefix = frame_support::traits::ConstU16<456>; diff --git a/frame/examples/dev-mode/Cargo.toml b/frame/examples/dev-mode/Cargo.toml index 66b87a5b5245e..1dda112bf0864 100644 --- a/frame/examples/dev-mode/Cargo.toml +++ b/frame/examples/dev-mode/Cargo.toml @@ -27,7 +27,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../../primiti sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -35,14 +35,14 @@ std = [ "log/std", "pallet-balances/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/examples/kitchensink/Cargo.toml b/frame/examples/kitchensink/Cargo.toml index 0537f497b64df..942260115719d 100644 --- a/frame/examples/kitchensink/Cargo.toml +++ b/frame/examples/kitchensink/Cargo.toml @@ -31,34 +31,30 @@ pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../ sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", - "log/std", - "scale-info/std", - + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - + "log/std", + "pallet-balances/std", + "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - - "frame-benchmarking?/std", - - "pallet-balances/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/examples/offchain-worker/Cargo.toml b/frame/examples/offchain-worker/Cargo.toml index dd3f8e070d583..f3359ee77e11b 100644 --- a/frame/examples/offchain-worker/Cargo.toml +++ b/frame/examples/offchain-worker/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../pr sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -36,12 +36,12 @@ std = [ "scale-info/std", "sp-core/std", "sp-io/std", - "sp-keystore/std", - "sp-runtime/std", - "sp-std/std" + "sp-keystore/std", + "sp-runtime/std", + "sp-std/std", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/examples/split/Cargo.toml b/frame/examples/split/Cargo.toml index 3ef5b5a070be4..f64d79855a1a5 100644 --- a/frame/examples/split/Cargo.toml +++ b/frame/examples/split/Cargo.toml @@ -29,27 +29,21 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", - "log/std", - "scale-info/std", - + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - + "log/std", + "scale-info/std", + "sp-core/std", "sp-io/std", "sp-std/std", - - "frame-benchmarking?/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks" -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime" + "frame-system/runtime-benchmarks", ] +try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index fa466dd2041ea..48cbb47fe7d28 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ "derive", ] } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } @@ -36,29 +37,30 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-version = { version = "22.0.0", path = "../../primitives/version" } [features] -default = ["std"] -with-tracing = ["sp-tracing/with-tracing"] +default = [ "std" ] +with-tracing = [ "sp-tracing/with-tracing" ] std = [ "codec/std", "frame-support/std", "frame-system/std", "frame-try-runtime/std", + "log/std", + "pallet-balances/std", + "pallet-transaction-payment/std", "scale-info/std", "sp-core/std", + "sp-inherents/std", "sp-io/std", "sp-runtime/std", "sp-std/std", "sp-tracing/std", - "pallet-balances/std", - "pallet-transaction-payment/std", - "sp-inherents/std", - "sp-version/std" + "sp-version/std", ] try-runtime = [ "frame-support/try-runtime", - "frame-try-runtime/try-runtime", - "sp-runtime/try-runtime", "frame-system/try-runtime", + "frame-try-runtime/try-runtime", "pallet-balances/try-runtime", - "pallet-transaction-payment/try-runtime" + "pallet-transaction-payment/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 4e24717a39e93..1d9afdfa60aa4 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -138,6 +138,8 @@ use sp_runtime::{ }; use sp_std::{marker::PhantomData, prelude::*}; +#[cfg(feature = "try-runtime")] +use log; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; @@ -252,7 +254,7 @@ where signature_check: bool, select: frame_try_runtime::TryStateSelect, ) -> Result { - frame_support::log::info!( + log::info!( target: LOG_TARGET, "try-runtime: executing block #{:?} / state root check: {:?} / signature check: {:?} / try-state-select: {:?}", block.header().number(), @@ -289,7 +291,7 @@ where for e in extrinsics { if let Err(err) = try_apply_extrinsic(e.clone()) { - frame_support::log::error!( + log::error!( target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", e, err, @@ -308,7 +310,7 @@ where BlockNumberFor, >>::try_state(*header.number(), select) .map_err(|e| { - frame_support::log::error!(target: LOG_TARGET, "failure: {:?}", e); + log::error!(target: LOG_TARGET, "failure: {:?}", e); e })?; drop(_guard); @@ -338,7 +340,7 @@ where ); } - frame_support::log::info!( + log::info!( target: LOG_TARGET, "try-runtime: Block #{:?} successfully executed", header.number(), diff --git a/frame/fast-unstake/Cargo.toml b/frame/fast-unstake/Cargo.toml index 8b48537843df1..6e67253f762f7 100644 --- a/frame/fast-unstake/Cargo.toml +++ b/frame/fast-unstake/Cargo.toml @@ -39,46 +39,42 @@ pallet-balances = { path = "../balances" } pallet-timestamp = { path = "../timestamp" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", - "log/std", - "scale-info/std", - + "frame-benchmarking/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", - - "sp-io/std", - "sp-staking/std", - "sp-runtime/std", - "sp-std/std", - - "frame-election-provider-support/std", - - "frame-benchmarking/std", + "log/std", "pallet-balances/std", "pallet-staking/std", "pallet-timestamp/std", + "scale-info/std", "sp-core/std", - "sp-tracing/std" + "sp-io/std", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", + "sp-tracing/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-staking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-staking/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/fast-unstake/src/mock.rs b/frame/fast-unstake/src/mock.rs index 3a3d9e2d4b133..dc24a823c0db0 100644 --- a/frame/fast-unstake/src/mock.rs +++ b/frame/fast-unstake/src/mock.rs @@ -16,8 +16,8 @@ // limitations under the License. use crate::{self as fast_unstake}; -use frame_benchmarking::frame_support::assert_ok; use frame_support::{ + assert_ok, pallet_prelude::*, parameter_types, traits::{ConstU64, Currency}, diff --git a/frame/glutton/Cargo.toml b/frame/glutton/Cargo.toml index afaa7fdcf973f..65b01e8390b57 100644 --- a/frame/glutton/Cargo.toml +++ b/frame/glutton/Cargo.toml @@ -29,31 +29,31 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ "blake2/std", "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" ] diff --git a/frame/glutton/src/lib.rs b/frame/glutton/src/lib.rs index 5950bd676b378..c76cc30017cf0 100644 --- a/frame/glutton/src/lib.rs +++ b/frame/glutton/src/lib.rs @@ -227,7 +227,7 @@ pub mod pallet { new_count: u32, witness_count: Option, ) -> DispatchResult { - T::AdminOrigin::try_origin(origin).map(|_| ()).or_else(|o| ensure_root(o))?; + T::AdminOrigin::ensure_origin_or_root(origin)?; let current_count = TrashDataCount::::get(); ensure!( @@ -252,7 +252,7 @@ pub mod pallet { /// Only callable by Root or `AdminOrigin`. #[pallet::call_index(1)] pub fn set_compute(origin: OriginFor, compute: FixedU64) -> DispatchResult { - T::AdminOrigin::try_origin(origin).map(|_| ()).or_else(|o| ensure_root(o))?; + T::AdminOrigin::ensure_origin_or_root(origin)?; ensure!(compute <= RESOURCE_HARD_LIMIT, Error::::InsaneLimit); Compute::::set(compute); @@ -262,7 +262,7 @@ pub mod pallet { } /// Set how much of the remaining `proof_size` weight should be consumed by `on_idle`. - // + /// /// `1.0` means that all remaining `proof_size` will be consumed. The PoV benchmarking /// results that are used here are likely an over-estimation. 100% intended consumption will /// therefore translate to less than 100% actual consumption. @@ -270,7 +270,7 @@ pub mod pallet { /// Only callable by Root or `AdminOrigin`. #[pallet::call_index(2)] pub fn set_storage(origin: OriginFor, storage: FixedU64) -> DispatchResult { - T::AdminOrigin::try_origin(origin).map(|_| ()).or_else(|o| ensure_root(o))?; + T::AdminOrigin::ensure_origin_or_root(origin)?; ensure!(storage <= RESOURCE_HARD_LIMIT, Error::::InsaneLimit); Storage::::set(storage); diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 1f0d86cc49cb7..b9f8cc5c2cb89 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -42,29 +42,29 @@ pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } sp-keyring = { version = "24.0.0", path = "../../primitives/keyring" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", "log/std", "pallet-authorship/std", + "pallet-balances/std", + "pallet-offences/std", "pallet-session/std", + "pallet-staking/std", + "pallet-timestamp/std", "scale-info/std", "sp-application-crypto/std", - "sp-core/std", "sp-consensus-grandpa/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-session/std", "sp-staking/std", "sp-std/std", - "frame-election-provider-support/std", - "pallet-balances/std", - "pallet-offences/std", - "pallet-staking/std", - "pallet-timestamp/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -76,11 +76,11 @@ runtime-benchmarks = [ "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", @@ -88,5 +88,5 @@ try-runtime = [ "pallet-session/try-runtime", "pallet-staking/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 942fba9053294..fef4ed400a55a 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -28,29 +28,29 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 076bf91962efd..23e0563a190db 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -31,14 +31,15 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives pallet-session = { version = "4.0.0-dev", path = "../session" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", "pallet-authorship/std", + "pallet-session/std", "scale-info/std", "sp-application-crypto/std", "sp-core/std", @@ -46,19 +47,18 @@ std = [ "sp-runtime/std", "sp-staking/std", "sp-std/std", - "pallet-session/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-authorship/try-runtime", "pallet-session/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 52fe97cc7e071..84e41a0cbed20 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -28,30 +28,30 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-keyring", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/insecure-randomness-collective-flip/Cargo.toml b/frame/insecure-randomness-collective-flip/Cargo.toml index d078eafacffc8..6676dac91527d 100644 --- a/frame/insecure-randomness-collective-flip/Cargo.toml +++ b/frame/insecure-randomness-collective-flip/Cargo.toml @@ -26,20 +26,20 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", "safe-mix/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std", - "sp-io/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/lottery/Cargo.toml b/frame/lottery/Cargo.toml index a46bf7feff65d..85503edaee45c 100644 --- a/frame/lottery/Cargo.toml +++ b/frame/lottery/Cargo.toml @@ -29,31 +29,31 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", + "frame-support-test/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "frame-support-test/std", - "pallet-balances/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-support-test/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/lottery/src/lib.rs b/frame/lottery/src/lib.rs index a6a94b4ab19af..c9c0254042424 100644 --- a/frame/lottery/src/lib.rs +++ b/frame/lottery/src/lib.rs @@ -61,12 +61,12 @@ use frame_support::{ pallet_prelude::MaxEncodedLen, storage::bounded_vec::BoundedVec, traits::{Currency, ExistenceRequirement::KeepAlive, Get, Randomness, ReservableCurrency}, - PalletId, RuntimeDebug, + PalletId, }; pub use pallet::*; use sp_runtime::{ traits::{AccountIdConversion, Saturating, Zero}, - ArithmeticError, DispatchError, + ArithmeticError, DispatchError, RuntimeDebug, }; use sp_std::prelude::*; pub use weights::WeightInfo; diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index e41a1e0919627..e2674cb64053b 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -47,5 +47,5 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 24b9fb5fe9069..6fb61f0e491be 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -525,12 +525,13 @@ mod tests { use sp_core::H256; use sp_runtime::{ + bounded_vec, traits::{BadOrigin, BlakeTwo256, IdentityLookup}, BuildStorage, }; use frame_support::{ - assert_noop, assert_ok, bounded_vec, ord_parameter_types, parameter_types, + assert_noop, assert_ok, ord_parameter_types, parameter_types, traits::{ConstU32, ConstU64, StorageVersion}, }; use frame_system::EnsureSignedBy; diff --git a/frame/merkle-mountain-range/Cargo.toml b/frame/merkle-mountain-range/Cargo.toml index 1d7739eb93c2c..3496b84350d0f 100644 --- a/frame/merkle-mountain-range/Cargo.toml +++ b/frame/merkle-mountain-range/Cargo.toml @@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } @@ -29,12 +30,13 @@ env_logger = "0.9" itertools = "0.10.3" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "log/std", "scale-info/std", "sp-core/std", "sp-io/std", @@ -46,10 +48,10 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/merkle-mountain-range/src/lib.rs b/frame/merkle-mountain-range/src/lib.rs index 2edef9a35d57a..664f4bc73901b 100644 --- a/frame/merkle-mountain-range/src/lib.rs +++ b/frame/merkle-mountain-range/src/lib.rs @@ -56,8 +56,9 @@ //! NOTE This pallet is experimental and not proven to work in production. #![cfg_attr(not(feature = "std"), no_std)] -use frame_support::{log, weights::Weight}; +use frame_support::weights::Weight; use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; +use log; use sp_mmr_primitives::utils; use sp_runtime::{ traits::{self, One, Saturating}, diff --git a/frame/merkle-mountain-range/src/mmr/storage.rs b/frame/merkle-mountain-range/src/mmr/storage.rs index d7466784e4ab8..03039be83ac1a 100644 --- a/frame/merkle-mountain-range/src/mmr/storage.rs +++ b/frame/merkle-mountain-range/src/mmr/storage.rs @@ -18,7 +18,7 @@ //! An MMR storage implementation. use codec::Encode; -use frame_support::log::{debug, trace}; +use log::{debug, trace}; use sp_core::offchain::StorageKind; use sp_io::offchain_index; use sp_mmr_primitives::{mmr_lib, mmr_lib::helper, utils::NodesUtils}; diff --git a/frame/message-queue/Cargo.toml b/frame/message-queue/Cargo.toml index 929b713b7eb2e..4fe2b4636667d 100644 --- a/frame/message-queue/Cargo.toml +++ b/frame/message-queue/Cargo.toml @@ -31,29 +31,29 @@ rand = "0.8.5" rand_distr = "0.4.3" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", "scale-info/std", + "sp-arithmetic/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-arithmetic/std", + "sp-tracing/std", "sp-weights/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "sp-tracing/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/multisig/Cargo.toml b/frame/multisig/Cargo.toml index 07e13e2238695..7927fea620758 100644 --- a/frame/multisig/Cargo.toml +++ b/frame/multisig/Cargo.toml @@ -29,28 +29,28 @@ log = { version = "0.4.17", default-features = false } pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index ab117315f8985..e4426c64b4125 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -57,14 +57,14 @@ use frame_support::{ ensure, traits::{Currency, Get, ReservableCurrency}, weights::Weight, - BoundedVec, RuntimeDebug, + BoundedVec, }; use frame_system::{self as system, pallet_prelude::BlockNumberFor, RawOrigin}; use scale_info::TypeInfo; use sp_io::hashing::blake2_256; use sp_runtime::{ traits::{Dispatchable, TrailingZeroInput, Zero}, - DispatchError, + DispatchError, RuntimeDebug, }; use sp_std::prelude::*; pub use weights::WeightInfo; diff --git a/frame/nft-fractionalization/Cargo.toml b/frame/nft-fractionalization/Cargo.toml index 8f706a1e00ae7..b75f3262c2d01 100644 --- a/frame/nft-fractionalization/Cargo.toml +++ b/frame/nft-fractionalization/Cargo.toml @@ -31,7 +31,7 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-std = { version = "8.0.0", path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking/std", @@ -39,22 +39,22 @@ std = [ "frame-system/std", "log/std", "pallet-assets/std", + "pallet-balances/std", "pallet-nfts/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-nfts/runtime-benchmarks" + "pallet-nfts/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -62,5 +62,5 @@ try-runtime = [ "pallet-assets/try-runtime", "pallet-balances/try-runtime", "pallet-nfts/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/nfts/Cargo.toml b/frame/nfts/Cargo.toml index d378803f5de94..126e4439b5024 100644 --- a/frame/nfts/Cargo.toml +++ b/frame/nfts/Cargo.toml @@ -30,31 +30,31 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-keystore = { version = "0.27.0", path = "../../primitives/keystore" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", + "sp-keystore/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-keystore/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/nfts/runtime-api/Cargo.toml b/frame/nfts/runtime-api/Cargo.toml index bf5f9f0ec001f..a3e08708ae178 100644 --- a/frame/nfts/runtime-api/Cargo.toml +++ b/frame/nfts/runtime-api/Cargo.toml @@ -19,10 +19,5 @@ pallet-nfts = { version = "4.0.0-dev", default-features = false, path = "../../n sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } [features] -default = ["std"] -std = [ - "codec/std", - "frame-support/std", - "pallet-nfts/std", - "sp-api/std", -] +default = [ "std" ] +std = [ "codec/std", "frame-support/std", "pallet-nfts/std", "sp-api/std" ] diff --git a/frame/nfts/src/migration.rs b/frame/nfts/src/migration.rs index a4529148e35b6..f90d332062a2c 100644 --- a/frame/nfts/src/migration.rs +++ b/frame/nfts/src/migration.rs @@ -16,7 +16,8 @@ // limitations under the License. use super::*; -use frame_support::{log, traits::OnRuntimeUpgrade}; +use frame_support::traits::OnRuntimeUpgrade; +use log; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index 450fee2abcce1..129c99d310d97 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -26,21 +26,21 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/nis/Cargo.toml b/frame/nis/Cargo.toml index bad1bed8f9042..2b012bbe91a83 100644 --- a/frame/nis/Cargo.toml +++ b/frame/nis/Cargo.toml @@ -28,30 +28,30 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "sp-arithmetic/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/node-authorization/Cargo.toml b/frame/node-authorization/Cargo.toml index 24155841271e5..b801d736498c3 100644 --- a/frame/node-authorization/Cargo.toml +++ b/frame/node-authorization/Cargo.toml @@ -23,7 +23,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -38,5 +38,5 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/nomination-pools/Cargo.toml b/frame/nomination-pools/Cargo.toml index f3b9a025ecf7c..e0158215e797a 100644 --- a/frame/nomination-pools/Cargo.toml +++ b/frame/nomination-pools/Cargo.toml @@ -35,32 +35,32 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-tracing = { version = "10.0.0", path = "../../primitives/tracing" } [features] -default = ["std"] -fuzzing = ["pallet-balances", "sp-tracing"] +default = [ "std" ] +fuzzing = [ "pallet-balances", "sp-tracing" ] std = [ "codec/std", - "scale-info/std", "frame-support/std", "frame-system/std", - "sp-runtime/std", - "sp-std/std", - "sp-io/std", - "sp-staking/std", - "sp-core/std", "log/std", "pallet-balances?/std", - "sp-tracing?/std" + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", + "sp-tracing?/std", ] runtime-benchmarks = [ - "sp-staking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances?/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances?/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/nomination-pools/benchmarking/Cargo.toml b/frame/nomination-pools/benchmarking/Cargo.toml index 38b79d2dabc4c..836f65e849fe0 100644 --- a/frame/nomination-pools/benchmarking/Cargo.toml +++ b/frame/nomination-pools/benchmarking/Cargo.toml @@ -40,7 +40,7 @@ sp-core = { version = "21.0.0", path = "../../../primitives/core" } sp-io = { version = "23.0.0", path = "../../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "frame-benchmarking/std", @@ -48,28 +48,28 @@ std = [ "frame-support/std", "frame-system/std", "pallet-bags-list/std", - "pallet-staking/std", + "pallet-balances/std", "pallet-nomination-pools/std", - "sp-runtime/std", + "pallet-staking/std", + "pallet-timestamp/std", + "sp-core/std", + "sp-io/std", "sp-runtime-interface/std", + "sp-runtime/std", "sp-staking/std", "sp-std/std", - "pallet-balances/std", - "pallet-timestamp/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ - "frame-election-provider-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks", + "frame-election-provider-support/runtime-benchmarks", "frame-support/runtime-benchmarks", - "pallet-staking/runtime-benchmarks", - "pallet-nomination-pools/runtime-benchmarks", + "frame-system/runtime-benchmarks", "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks" + "pallet-nomination-pools/runtime-benchmarks", + "pallet-staking/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", ] diff --git a/frame/nomination-pools/benchmarking/src/lib.rs b/frame/nomination-pools/benchmarking/src/lib.rs index e757f66e725a0..45f0ca0ecfe6e 100644 --- a/frame/nomination-pools/benchmarking/src/lib.rs +++ b/frame/nomination-pools/benchmarking/src/lib.rs @@ -23,11 +23,12 @@ #[cfg(test)] mod mock; -use frame_benchmarking::v1::{ - account, frame_support::traits::Currency, vec, whitelist_account, Vec, -}; +use frame_benchmarking::v1::{account, whitelist_account}; use frame_election_provider_support::SortedListProvider; -use frame_support::{assert_ok, ensure, traits::Get}; +use frame_support::{ + assert_ok, ensure, + traits::{Currency, Get}, +}; use frame_system::RawOrigin as RuntimeOrigin; use pallet_nomination_pools::{ BalanceOf, BondExtra, BondedPoolInner, BondedPools, ClaimPermission, ClaimPermissions, @@ -41,6 +42,7 @@ use sp_runtime::{ Perbill, }; use sp_staking::{EraIndex, StakingInterface}; +use sp_std::{vec, vec::Vec}; // `frame_benchmarking::benchmarks!` macro needs this use pallet_nomination_pools::Call; diff --git a/frame/nomination-pools/runtime-api/Cargo.toml b/frame/nomination-pools/runtime-api/Cargo.toml index f92a303e9bbe1..eef1d42d43397 100644 --- a/frame/nomination-pools/runtime-api/Cargo.toml +++ b/frame/nomination-pools/runtime-api/Cargo.toml @@ -19,10 +19,5 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../../primiti pallet-nomination-pools = { version = "1.0.0", default-features = false, path = "../" } [features] -default = ["std"] -std = [ - "codec/std", - "sp-api/std", - "sp-std/std", - "pallet-nomination-pools/std", -] +default = [ "std" ] +std = [ "codec/std", "pallet-nomination-pools/std", "sp-api/std", "sp-std/std" ] diff --git a/frame/nomination-pools/src/tests.rs b/frame/nomination-pools/src/tests.rs index ac8fa5c4dbc0c..d0fe4e40a18b7 100644 --- a/frame/nomination-pools/src/tests.rs +++ b/frame/nomination-pools/src/tests.rs @@ -17,9 +17,9 @@ use super::*; use crate::{mock::*, Event}; -use frame_support::{assert_err, assert_noop, assert_ok, assert_storage_noop, bounded_btree_map}; +use frame_support::{assert_err, assert_noop, assert_ok, assert_storage_noop}; use pallet_balances::Event as BEvent; -use sp_runtime::{traits::Dispatchable, FixedU128}; +use sp_runtime::{bounded_btree_map, traits::Dispatchable, FixedU128}; macro_rules! unbonding_pools_with_era { ($($k:expr => $v:expr),* $(,)?) => {{ @@ -3260,7 +3260,7 @@ mod pool_withdraw_unbonded { mod withdraw_unbonded { use super::*; - use frame_support::bounded_btree_map; + use sp_runtime::bounded_btree_map; #[test] fn withdraw_unbonded_works_against_slashed_no_era_sub_pool() { diff --git a/frame/nomination-pools/test-staking/src/lib.rs b/frame/nomination-pools/test-staking/src/lib.rs index 1587492582143..9108da510a3a5 100644 --- a/frame/nomination-pools/test-staking/src/lib.rs +++ b/frame/nomination-pools/test-staking/src/lib.rs @@ -19,14 +19,14 @@ mod mock; -use frame_support::{assert_noop, assert_ok, bounded_btree_map, traits::Currency}; +use frame_support::{assert_noop, assert_ok, traits::Currency}; use mock::*; use pallet_nomination_pools::{ BondedPools, Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember, PoolMembers, PoolState, }; use pallet_staking::{CurrentEra, Event as StakingEvent, Payee, RewardDestination}; -use sp_runtime::traits::Zero; +use sp_runtime::{bounded_btree_map, traits::Zero}; #[test] fn pool_lifecycle_e2e() { diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index f2542b125d86f..fb92f102940c2 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -29,7 +29,7 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -38,22 +38,22 @@ std = [ "pallet-balances/std", "scale-info/std", "serde", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-staking/std", "sp-std/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 3483ad743a462..17309478d62ec 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -38,13 +38,14 @@ sp-core = { version = "21.0.0", path = "../../../primitives/core" } sp-io = { version = "23.0.0", path = "../../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking/std", "frame-election-provider-support/std", "frame-support/std", "frame-system/std", + "log/std", "pallet-babe/std", "pallet-balances/std", "pallet-grandpa/std", @@ -52,18 +53,16 @@ std = [ "pallet-offences/std", "pallet-session/std", "pallet-staking/std", + "pallet-timestamp/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-staking/std", "sp-std/std", - "log/std", - "pallet-timestamp/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ - "pallet-staking/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "frame-support/runtime-benchmarks", @@ -73,7 +72,8 @@ runtime-benchmarks = [ "pallet-grandpa/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", "pallet-offences/runtime-benchmarks", + "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] diff --git a/frame/paged-list/Cargo.toml b/frame/paged-list/Cargo.toml index 3d7010d331b2e..4f697b6333c8e 100644 --- a/frame/paged-list/Cargo.toml +++ b/frame/paged-list/Cargo.toml @@ -24,16 +24,35 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } sp-core = { version = "21.0.0", path = "../../primitives/core", default-features = false } sp-io = { version = "23.0.0", path = "../../primitives/io", default-features = false } +sp-metadata-ir = { version = "0.1.0", default-features = false, optional = true, path = "../../primitives/metadata-ir" } [features] -default = ["std"] - -std = ["codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std"] +default = [ "std" ] + +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-metadata-ir/std", + "sp-runtime/std", + "sp-std/std", +] -runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] + +frame-metadata = [ "sp-metadata-ir" ] diff --git a/frame/paged-list/src/paged_list.rs b/frame/paged-list/src/paged_list.rs index 37ebe80d93448..3597c3dea6823 100644 --- a/frame/paged-list/src/paged_list.rs +++ b/frame/paged-list/src/paged_list.rs @@ -408,12 +408,12 @@ where pub(crate) mod mock { pub use super::*; pub use frame_support::{ - metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}, parameter_types, storage::{types::ValueQuery, StorageList as _}, StorageNoopGuard, }; pub use sp_io::{hashing::twox_128, TestExternalities}; + pub use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}; parameter_types! { pub const ValuesPerNewPage: u32 = 5; diff --git a/frame/preimage/Cargo.toml b/frame/preimage/Cargo.toml index b942823a2d26b..f9ba45cedab2a 100644 --- a/frame/preimage/Cargo.toml +++ b/frame/preimage/Cargo.toml @@ -25,14 +25,14 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-core = { version = "21.0.0", default-features = false, path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] std = [ "codec/std", @@ -40,16 +40,16 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/preimage/src/migration.rs b/frame/preimage/src/migration.rs index 46e555498cd2d..0f3337e39bf50 100644 --- a/frame/preimage/src/migration.rs +++ b/frame/preimage/src/migration.rs @@ -192,7 +192,7 @@ mod test { use super::*; use crate::mock::{Test as T, *}; - use frame_support::bounded_vec; + use sp_runtime::bounded_vec; #[test] fn migration_works() { diff --git a/frame/preimage/src/tests.rs b/frame/preimage/src/tests.rs index 63a178c408a3f..fa621c8f5589e 100644 --- a/frame/preimage/src/tests.rs +++ b/frame/preimage/src/tests.rs @@ -23,12 +23,13 @@ use super::*; use crate::mock::*; use frame_support::{ - assert_err, assert_noop, assert_ok, assert_storage_noop, bounded_vec, + assert_err, assert_noop, assert_ok, assert_storage_noop, traits::{Bounded, BoundedInline, Hash as PreimageHash}, StorageNoopGuard, }; use pallet_balances::Error as BalancesError; use sp_core::{blake2_256, H256}; +use sp_runtime::bounded_vec; /// Returns one `Inline`, `Lookup` and `Legacy` item each with different data and hash. pub fn make_bounded_values() -> (Bounded>, Bounded>, Bounded>) { diff --git a/frame/proxy/Cargo.toml b/frame/proxy/Cargo.toml index a32a31ce41ade..734926c4a2f92 100644 --- a/frame/proxy/Cargo.toml +++ b/frame/proxy/Cargo.toml @@ -28,19 +28,19 @@ pallet-utility = { version = "4.0.0-dev", path = "../utility" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", + "pallet-utility/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "pallet-utility/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -48,12 +48,12 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-utility/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-utility/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 33e9fcfade35a..586d52fb62bdd 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -38,7 +38,6 @@ use frame_support::{ dispatch::{DispatchError, GetDispatchInfo}, ensure, traits::{Currency, Get, InstanceFilter, IsSubType, IsType, OriginTrait, ReservableCurrency}, - RuntimeDebug, }; use frame_system::{self as system, ensure_signed, pallet_prelude::BlockNumberFor}; pub use pallet::*; @@ -46,7 +45,7 @@ use scale_info::TypeInfo; use sp_io::hashing::blake2_256; use sp_runtime::{ traits::{Dispatchable, Hash, Saturating, StaticLookup, TrailingZeroInput, Zero}, - DispatchResult, + DispatchResult, RuntimeDebug, }; use sp_std::prelude::*; pub use weights::WeightInfo; diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 4b055a3935b95..48a2a4ed0cc33 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -27,10 +27,9 @@ use frame_support::{ assert_noop, assert_ok, derive_impl, dispatch::DispatchError, traits::{ConstU32, ConstU64, Contains}, - RuntimeDebug, }; use sp_core::H256; -use sp_runtime::{traits::BlakeTwo256, BuildStorage}; +use sp_runtime::{traits::BlakeTwo256, BuildStorage, RuntimeDebug}; type Block = frame_system::mocking::MockBlock; diff --git a/frame/ranked-collective/Cargo.toml b/frame/ranked-collective/Cargo.toml index 0a20b4eb97ca1..1152aeea4fa06 100644 --- a/frame/ranked-collective/Cargo.toml +++ b/frame/ranked-collective/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -49,5 +49,5 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/ranked-collective/src/lib.rs b/frame/ranked-collective/src/lib.rs index fe1308cd034f4..d94932a1dac71 100644 --- a/frame/ranked-collective/src/lib.rs +++ b/frame/ranked-collective/src/lib.rs @@ -41,6 +41,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "128"] +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_arithmetic::traits::Saturating; use sp_runtime::{ @@ -51,7 +52,6 @@ use sp_runtime::{ use sp_std::{marker::PhantomData, prelude::*}; use frame_support::{ - codec::{Decode, Encode, MaxEncodedLen}, dispatch::{DispatchError, DispatchResultWithPostInfo, PostDispatchInfo}, ensure, impl_ensure_origin_with_arg_ignoring_arg, traits::{EnsureOrigin, EnsureOriginWithArg, PollStatus, Polling, RankedMembers, VoteTally}, diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index 14d32866e0101..9e86728bc8976 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -27,30 +27,30 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ 'frame-benchmarking', + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index 9c01d25d4f76b..5673147c8e005 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -152,13 +152,16 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_runtime::traits::{CheckedAdd, CheckedMul, Dispatchable, SaturatedConversion, StaticLookup}; +use sp_runtime::{ + traits::{CheckedAdd, CheckedMul, Dispatchable, SaturatedConversion, StaticLookup}, + RuntimeDebug, +}; use sp_std::prelude::*; use frame_support::{ dispatch::{GetDispatchInfo, PostDispatchInfo}, traits::{BalanceStatus, Currency, ReservableCurrency}, - BoundedVec, RuntimeDebug, + BoundedVec, }; pub use pallet::*; diff --git a/frame/recovery/src/tests.rs b/frame/recovery/src/tests.rs index 85024d0bc4a9d..93df07015852e 100644 --- a/frame/recovery/src/tests.rs +++ b/frame/recovery/src/tests.rs @@ -18,12 +18,12 @@ //! Tests for the module. use super::*; -use frame_support::{assert_noop, assert_ok, bounded_vec, traits::Currency}; +use frame_support::{assert_noop, assert_ok, traits::Currency}; use mock::{ new_test_ext, run_to_block, Balances, BalancesCall, MaxFriends, Recovery, RecoveryCall, RuntimeCall, RuntimeOrigin, Test, }; -use sp_runtime::traits::BadOrigin; +use sp_runtime::{bounded_vec, traits::BadOrigin}; #[test] fn basic_setup_works() { diff --git a/frame/referenda/Cargo.toml b/frame/referenda/Cargo.toml index a52d987806421..abaed893ee54b 100644 --- a/frame/referenda/Cargo.toml +++ b/frame/referenda/Cargo.toml @@ -36,34 +36,34 @@ pallet-scheduler = { version = "4.0.0-dev", path = "../scheduler" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", - "sp-runtime/std", - "sp-arithmetic/std", "frame-system/std", + "pallet-balances/std", + "pallet-preimage/std", + "pallet-scheduler/std", "scale-info/std", "serde", + "sp-arithmetic/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", + "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "pallet-preimage/std", - "pallet-scheduler/std", - "sp-core/std" ] runtime-benchmarks = [ "assert_matches", "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks" + "pallet-scheduler/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -71,5 +71,5 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-preimage/try-runtime", "pallet-scheduler/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/remark/Cargo.toml b/frame/remark/Cargo.toml index df77770c3a846..47078bddeb5ba 100644 --- a/frame/remark/Cargo.toml +++ b/frame/remark/Cargo.toml @@ -28,16 +28,16 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives sp-core = { version = "21.0.0", default-features = false, path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "scale-info/std", @@ -50,5 +50,5 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/root-offences/Cargo.toml b/frame/root-offences/Cargo.toml index 6b7623b9af0e7..e8f38f8aca343 100644 --- a/frame/root-offences/Cargo.toml +++ b/frame/root-offences/Cargo.toml @@ -44,33 +44,32 @@ runtime-benchmarks = [ "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-session/try-runtime", "pallet-staking/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] -default = ["std"] +default = [ "std" ] std = [ "codec/std", + "frame-election-provider-support/std", "frame-support/std", - "frame-system/std", + "pallet-balances/std", "pallet-session/std", "pallet-staking/std", - "scale-info/std", - "sp-runtime/std", - "frame-election-provider-support/std", - "pallet-balances/std", "pallet-timestamp/std", + "scale-info/std", "sp-core/std", "sp-io/std", + "sp-runtime/std", "sp-staking/std", - "sp-std/std" + "sp-std/std", ] diff --git a/frame/root-testing/Cargo.toml b/frame/root-testing/Cargo.toml index e6f32587d4593..b76cb5a059a34 100644 --- a/frame/root-testing/Cargo.toml +++ b/frame/root-testing/Cargo.toml @@ -27,18 +27,16 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", - "frame-system/std", "scale-info/std", - - "sp-runtime/std", "sp-core/std", "sp-io/std", - "sp-std/std" + "sp-runtime/std", + "sp-std/std", ] diff --git a/frame/safe-mode/Cargo.toml b/frame/safe-mode/Cargo.toml new file mode 100644 index 0000000000000..ca04a3e1b93d3 --- /dev/null +++ b/frame/safe-mode/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = "pallet-safe-mode" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME safe-mode pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +sp-arithmetic = { version = "16.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } +pallet-balances = { version = "4.0.0-dev", path = "../balances", default-features = false, optional = true } +pallet-utility = { version = "4.0.0-dev", path = "../utility", default-features = false, optional = true } +pallet-proxy = { version = "4.0.0-dev", path = "../proxy", default-features = false, optional = true } + +[dev-dependencies] +sp-core = { version = "21.0.0", path = "../../primitives/core" } +sp-io = { version = "23.0.0", path = "../../primitives/io" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-utility = { version = "4.0.0-dev", path = "../utility" } +pallet-proxy = { version = "4.0.0-dev", path = "../proxy" } + +[features] +default = [ "std" ] +std = [ + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "pallet-balances?/std", + "pallet-proxy?/std", + "pallet-utility?/std", + "scale-info/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances?/try-runtime", + "pallet-proxy?/try-runtime", + "pallet-utility?/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/frame/safe-mode/src/benchmarking.rs b/frame/safe-mode/src/benchmarking.rs new file mode 100644 index 0000000000000..566150e982afc --- /dev/null +++ b/frame/safe-mode/src/benchmarking.rs @@ -0,0 +1,236 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(feature = "runtime-benchmarks")] + +use super::{Pallet as SafeMode, *}; + +use frame_benchmarking::v2::*; +use frame_support::traits::{fungible::Mutate as FunMutate, UnfilteredDispatchable}; +use frame_system::{Pallet as System, RawOrigin}; +use sp_runtime::traits::{Bounded, One, Zero}; + +#[benchmarks(where T::Currency: FunMutate)] +mod benchmarks { + use super::*; + + /// `on_initialize` doing nothing. + #[benchmark] + fn on_initialize_noop() { + #[block] + { + SafeMode::::on_initialize(1u32.into()); + } + } + + /// `on_initialize` exiting since the until block is in the past. + #[benchmark] + fn on_initialize_exit() { + EnteredUntil::::put(&BlockNumberFor::::zero()); + assert!(SafeMode::::is_entered()); + + #[block] + { + SafeMode::::on_initialize(1u32.into()); + } + + assert!(!SafeMode::::is_entered()); + } + + /// Permissionless enter - if configured. + #[benchmark] + fn enter() -> Result<(), BenchmarkError> { + T::EnterDepositAmount::get().ok_or_else(|| BenchmarkError::Weightless)?; + + let caller: T::AccountId = whitelisted_caller(); + let origin = RawOrigin::Signed(caller.clone()); + T::Currency::set_balance(&caller, init_bal::()); + + #[extrinsic_call] + _(origin); + + assert_eq!( + EnteredUntil::::get().unwrap(), + System::::block_number() + T::EnterDuration::get() + ); + Ok(()) + } + + /// Forceful enter - if configured. + #[benchmark] + fn force_enter() -> Result<(), BenchmarkError> { + let force_origin = + T::ForceEnterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + let duration = T::ForceEnterOrigin::ensure_origin(force_origin.clone()).unwrap(); + + #[extrinsic_call] + _(force_origin as T::RuntimeOrigin); + + assert_eq!(EnteredUntil::::get().unwrap(), System::::block_number() + duration); + Ok(()) + } + + /// Permissionless extend - if configured. + #[benchmark] + fn extend() -> Result<(), BenchmarkError> { + T::ExtendDepositAmount::get().ok_or_else(|| BenchmarkError::Weightless)?; + + let alice: T::AccountId = whitelisted_caller(); + T::Currency::set_balance(&alice, init_bal::()); + + System::::set_block_number(1u32.into()); + assert!(SafeMode::::do_enter(None, 1u32.into()).is_ok()); + + #[extrinsic_call] + _(RawOrigin::Signed(alice)); + + assert_eq!( + EnteredUntil::::get().unwrap(), + System::::block_number() + 1u32.into() + T::ExtendDuration::get() + ); + Ok(()) + } + + /// Forceful extend - if configured. + #[benchmark] + fn force_extend() -> Result<(), BenchmarkError> { + let force_origin = T::ForceExtendOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + System::::set_block_number(1u32.into()); + assert!(SafeMode::::do_enter(None, 1u32.into()).is_ok()); + + let duration = T::ForceExtendOrigin::ensure_origin(force_origin.clone()).unwrap(); + let call = Call::::force_extend {}; + + #[block] + { + call.dispatch_bypass_filter(force_origin)?; + } + + assert_eq!( + EnteredUntil::::get().unwrap(), + System::::block_number() + 1u32.into() + duration + ); + Ok(()) + } + + /// Forceful exit - if configured. + #[benchmark] + fn force_exit() -> Result<(), BenchmarkError> { + let force_origin = + T::ForceExitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + assert!(SafeMode::::do_enter(None, 1u32.into()).is_ok()); + + #[extrinsic_call] + _(force_origin as T::RuntimeOrigin); + + assert_eq!(EnteredUntil::::get(), None); + Ok(()) + } + + /// Permissionless release of a deposit - if configured. + #[benchmark] + fn release_deposit() -> Result<(), BenchmarkError> { + let delay = T::ReleaseDelay::get().ok_or_else(|| BenchmarkError::Weightless)?; + + let alice: T::AccountId = whitelisted_caller(); + let origin = RawOrigin::Signed(alice.clone()); + + T::Currency::set_balance(&alice, init_bal::()); + // Mock the storage. This is needed in case the `EnterDepositAmount` is zero. + let block: BlockNumberFor = 1u32.into(); + let bal: BalanceOf = 1u32.into(); + Deposits::::insert(&alice, &block, &bal); + T::Currency::hold(&HoldReason::EnterOrExtend.into(), &alice, bal)?; + EnteredUntil::::put(&block); + assert!(SafeMode::::do_exit(ExitReason::Force).is_ok()); + + System::::set_block_number(delay + One::one() + 2u32.into()); + System::::on_initialize(System::::block_number()); + SafeMode::::on_initialize(System::::block_number()); + + #[extrinsic_call] + _(origin, alice.clone(), 1u32.into()); + + assert!(!Deposits::::contains_key(&alice, &block)); + assert_eq!(T::Currency::balance(&alice), init_bal::()); + Ok(()) + } + + /// Forceful release of a deposit - if configured. + #[benchmark] + fn force_release_deposit() -> Result<(), BenchmarkError> { + let force_origin = T::ForceDepositOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + let alice: T::AccountId = whitelisted_caller(); + T::Currency::set_balance(&alice, init_bal::()); + + // Mock the storage. This is needed in case the `EnterDepositAmount` is zero. + let block: BlockNumberFor = 1u32.into(); + let bal: BalanceOf = 1u32.into(); + Deposits::::insert(&alice, &block, &bal); + T::Currency::hold(&&HoldReason::EnterOrExtend.into(), &alice, bal)?; + EnteredUntil::::put(&block); + + assert_eq!(T::Currency::balance(&alice), init_bal::() - 1u32.into()); + assert!(SafeMode::::do_exit(ExitReason::Force).is_ok()); + + System::::set_block_number(System::::block_number() + One::one()); + System::::on_initialize(System::::block_number()); + SafeMode::::on_initialize(System::::block_number()); + + #[extrinsic_call] + _(force_origin as T::RuntimeOrigin, alice.clone(), block); + + assert!(!Deposits::::contains_key(&alice, block)); + assert_eq!(T::Currency::balance(&alice), init_bal::()); + Ok(()) + } + + #[benchmark] + fn force_slash_deposit() -> Result<(), BenchmarkError> { + let force_origin = T::ForceDepositOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + let alice: T::AccountId = whitelisted_caller(); + T::Currency::set_balance(&alice, init_bal::()); + + // Mock the storage. This is needed in case the `EnterDepositAmount` is zero. + let block: BlockNumberFor = 1u32.into(); + let bal: BalanceOf = 1u32.into(); + Deposits::::insert(&alice, &block, &bal); + T::Currency::hold(&&HoldReason::EnterOrExtend.into(), &alice, bal)?; + EnteredUntil::::put(&block); + assert!(SafeMode::::do_exit(ExitReason::Force).is_ok()); + + #[extrinsic_call] + _(force_origin as T::RuntimeOrigin, alice.clone(), block); + + assert!(!Deposits::::contains_key(&alice, block)); + assert_eq!(T::Currency::balance(&alice), init_bal::() - 1u32.into()); + Ok(()) + } + + fn init_bal() -> BalanceOf { + BalanceOf::::max_value() / 10u32.into() + } + + impl_benchmark_test_suite!(SafeMode, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/safe-mode/src/lib.rs b/frame/safe-mode/src/lib.rs new file mode 100644 index 0000000000000..ff045b964afbb --- /dev/null +++ b/frame/safe-mode/src/lib.rs @@ -0,0 +1,596 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(rustdoc::broken_intra_doc_links)] + +mod benchmarking; +pub mod mock; +mod tests; +pub mod weights; + +use frame_support::{ + defensive_assert, + pallet_prelude::*, + traits::{ + fungible::{ + hold::{Inspect as FunHoldInspect, Mutate as FunHoldMutate}, + Inspect as FunInspect, + }, + tokens::{Fortitude, Precision}, + CallMetadata, Contains, Defensive, GetCallMetadata, PalletInfoAccess, SafeModeNotify, + }, + weights::Weight, + DefaultNoBound, +}; +use frame_system::pallet_prelude::*; +use sp_arithmetic::traits::Zero; +use sp_runtime::traits::Saturating; +use sp_std::{convert::TryInto, prelude::*}; + +pub use pallet::*; +pub use weights::*; + +type BalanceOf = + <::Currency as FunInspect<::AccountId>>::Balance; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Currency type for this pallet, used for Deposits. + type Currency: FunHoldInspect + + FunHoldMutate; + + /// The hold reason when reserving funds for entering or extending the safe-mode. + type RuntimeHoldReason: From; + + /// Contains all runtime calls in any pallet that can be dispatched even while the safe-mode + /// is entered. + /// + /// The safe-mode pallet cannot disable it's own calls, and does not need to be explicitly + /// added here. + type WhitelistedCalls: Contains; + + /// For how many blocks the safe-mode will be entered by [`Pallet::enter`]. + #[pallet::constant] + type EnterDuration: Get>; + + /// For how many blocks the safe-mode can be extended by each [`Pallet::extend`] call. + /// + /// This does not impose a hard limit as the safe-mode can be extended multiple times. + #[pallet::constant] + type ExtendDuration: Get>; + + /// The amount that will be reserved upon calling [`Pallet::enter`]. + /// + /// `None` disallows permissionlessly enabling the safe-mode and is a sane default. + #[pallet::constant] + type EnterDepositAmount: Get>>; + + /// The amount that will be reserved upon calling [`Pallet::extend`]. + /// + /// `None` disallows permissionlessly extending the safe-mode and is a sane default. + #[pallet::constant] + type ExtendDepositAmount: Get>>; + + /// The origin that may call [`Pallet::force_enter`]. + /// + /// The `Success` value is the number of blocks that this origin can enter safe-mode for. + type ForceEnterOrigin: EnsureOrigin>; + + /// The origin that may call [`Pallet::force_extend`]. + /// + /// The `Success` value is the number of blocks that this origin can extend the safe-mode. + type ForceExtendOrigin: EnsureOrigin>; + + /// The origin that may call [`Pallet::force_enter`]. + type ForceExitOrigin: EnsureOrigin; + + /// The only origin that can force to release or slash a deposit. + type ForceDepositOrigin: EnsureOrigin; + + /// Notifies external logic when the safe-mode is being entered or exited. + type Notify: SafeModeNotify; + + /// The minimal duration a deposit will remain reserved after safe-mode is entered or + /// extended, unless [`Pallet::force_release_deposit`] is successfully called sooner. + /// + /// Every deposit is tied to a specific activation or extension, thus each deposit can be + /// released independently after the delay for it has passed. + /// + /// `None` disallows permissionlessly releasing the safe-mode deposits and is a sane + /// default. + #[pallet::constant] + type ReleaseDelay: Get>>; + + // Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + /// The safe-mode is (already or still) entered. + Entered, + + /// The safe-mode is (already or still) exited. + Exited, + + /// This functionality of the pallet is disabled by the configuration. + NotConfigured, + + /// There is no balance reserved. + NoDeposit, + + /// The account already has a deposit reserved and can therefore not enter or extend again. + AlreadyDeposited, + + /// This deposit cannot be released yet. + CannotReleaseYet, + + /// An error from the underlying `Currency`. + CurrencyError, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// The safe-mode was entered until inclusively this block. + Entered { until: BlockNumberFor }, + + /// The safe-mode was extended until inclusively this block. + Extended { until: BlockNumberFor }, + + /// Exited the safe-mode for a specific reason. + Exited { reason: ExitReason }, + + /// An account reserved funds for either entering or extending the safe-mode. + DepositPlaced { account: T::AccountId, amount: BalanceOf }, + + /// An account had a reserve released that was reserved. + DepositReleased { account: T::AccountId, amount: BalanceOf }, + + /// An account had reserve slashed that was reserved. + DepositSlashed { account: T::AccountId, amount: BalanceOf }, + + /// Could not hold funds for entering or extending the safe-mode. + /// + /// This error comes from the underlying `Currency`. + CannotDeposit, + + /// Could not release funds for entering or extending the safe-mode. + /// + /// This error comes from the underlying `Currency`. + CannotRelease, + } + + /// The reason why the safe-mode was deactivated. + #[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] + pub enum ExitReason { + /// The safe-mode was automatically deactivated after it's duration ran out. + Timeout, + + /// The safe-mode was forcefully deactivated by [`Pallet::force_exit`]. + Force, + } + + /// Contains the last block number that the safe-mode will remain entered in. + /// + /// Set to `None` when safe-mode is exited. + /// + /// Safe-mode is automatically exited when the current block number exceeds this value. + #[pallet::storage] + pub type EnteredUntil = StorageValue<_, BlockNumberFor, OptionQuery>; + + /// Holds the reserve that was taken from an account at a specific block number. + /// + /// This helps governance to have an overview of outstanding deposits that should be returned or + /// slashed. + #[pallet::storage] + pub type Deposits = StorageDoubleMap< + _, + Twox64Concat, + T::AccountId, + Twox64Concat, + BlockNumberFor, + BalanceOf, + OptionQuery, + >; + + /// Configure the initial state of this pallet in the genesis block. + #[pallet::genesis_config] + #[derive(DefaultNoBound)] + pub struct GenesisConfig { + pub entered_until: Option>, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + if let Some(block) = self.entered_until { + EnteredUntil::::put(block); + } + } + } + + /// A reason for the pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + /// Funds are held for entering or extending the safe-mode. + #[codec(index = 0)] + EnterOrExtend, + } + + #[pallet::call] + impl Pallet { + /// Enter safe-mode permissionlessly for [`Config::EnterDuration`] blocks. + /// + /// Reserves [`Config::EnterDepositAmount`] from the caller's account. + /// Emits an [`Event::Entered`] event on success. + /// Errors with [`Error::Entered`] if the safe-mode is already entered. + /// Errors with [`Error::NotConfigured`] if the deposit amount is `None`. + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::enter())] + pub fn enter(origin: OriginFor) -> DispatchResult { + let who = ensure_signed(origin)?; + + Self::do_enter(Some(who), T::EnterDuration::get()).map_err(Into::into) + } + + /// Enter safe-mode by force for a per-origin configured number of blocks. + /// + /// Emits an [`Event::Entered`] event on success. + /// Errors with [`Error::Entered`] if the safe-mode is already entered. + /// + /// Can only be called by the [`Config::ForceEnterOrigin`] origin. + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::force_enter())] + pub fn force_enter(origin: OriginFor) -> DispatchResult { + let duration = T::ForceEnterOrigin::ensure_origin(origin)?; + + Self::do_enter(None, duration).map_err(Into::into) + } + + /// Extend the safe-mode permissionlessly for [`Config::ExtendDuration`] blocks. + /// + /// This accumulates on top of the current remaining duration. + /// Reserves [`Config::ExtendDepositAmount`] from the caller's account. + /// Emits an [`Event::Extended`] event on success. + /// Errors with [`Error::Exited`] if the safe-mode is entered. + /// Errors with [`Error::NotConfigured`] if the deposit amount is `None`. + /// + /// This may be called by any signed origin with [`Config::ExtendDepositAmount`] free + /// currency to reserve. This call can be disabled for all origins by configuring + /// [`Config::ExtendDepositAmount`] to `None`. + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::extend())] + pub fn extend(origin: OriginFor) -> DispatchResult { + let who = ensure_signed(origin)?; + + Self::do_extend(Some(who), T::ExtendDuration::get()).map_err(Into::into) + } + + /// Extend the safe-mode by force for a per-origin configured number of blocks. + /// + /// Emits an [`Event::Extended`] event on success. + /// Errors with [`Error::Exited`] if the safe-mode is inactive. + /// + /// Can only be called by the [`Config::ForceExtendOrigin`] origin. + #[pallet::call_index(3)] + #[pallet::weight(T::WeightInfo::force_extend())] + pub fn force_extend(origin: OriginFor) -> DispatchResult { + let duration = T::ForceExtendOrigin::ensure_origin(origin)?; + + Self::do_extend(None, duration).map_err(Into::into) + } + + /// Exit safe-mode by force. + /// + /// Emits an [`Event::Exited`] with [`ExitReason::Force`] event on success. + /// Errors with [`Error::Exited`] if the safe-mode is inactive. + /// + /// Note: `safe-mode` will be automatically deactivated by [`Pallet::on_initialize`] hook + /// after the block height is greater than the [`EnteredUntil`] storage item. + /// Emits an [`Event::Exited`] with [`ExitReason::Timeout`] event when deactivated in the + /// hook. + #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::force_exit())] + pub fn force_exit(origin: OriginFor) -> DispatchResult { + T::ForceExitOrigin::ensure_origin(origin)?; + + Self::do_exit(ExitReason::Force).map_err(Into::into) + } + + /// Slash a deposit for an account that entered or extended safe-mode at a given + /// historical block. + /// + /// This can only be called while safe-mode is entered. + /// + /// Emits a [`Event::DepositSlashed`] event on success. + /// Errors with [`Error::Entered`] if safe-mode is entered. + /// + /// Can only be called by the [`Config::ForceDepositOrigin`] origin. + #[pallet::call_index(5)] + #[pallet::weight(T::WeightInfo::force_slash_deposit())] + pub fn force_slash_deposit( + origin: OriginFor, + account: T::AccountId, + block: BlockNumberFor, + ) -> DispatchResult { + T::ForceDepositOrigin::ensure_origin(origin)?; + + Self::do_force_deposit(account, block).map_err(Into::into) + } + + /// Permissionlessly release a deposit for an account that entered safe-mode at a + /// given historical block. + /// + /// The call can be completely disabled by setting [`Config::ReleaseDelay`] to `None`. + /// This cannot be called while safe-mode is entered and not until + /// [`Config::ReleaseDelay`] blocks have passed since safe-mode was entered. + /// + /// Emits a [`Event::DepositReleased`] event on success. + /// Errors with [`Error::Entered`] if the safe-mode is entered. + /// Errors with [`Error::CannotReleaseYet`] if [`Config::ReleaseDelay`] block have not + /// passed since safe-mode was entered. Errors with [`Error::NoDeposit`] if the payee has no + /// reserved currency at the block specified. + #[pallet::call_index(6)] + #[pallet::weight(T::WeightInfo::release_deposit())] + pub fn release_deposit( + origin: OriginFor, + account: T::AccountId, + block: BlockNumberFor, + ) -> DispatchResult { + ensure_signed(origin)?; + + Self::do_release(false, account, block).map_err(Into::into) + } + + /// Force to release a deposit for an account that entered safe-mode at a given + /// historical block. + /// + /// This can be called while safe-mode is still entered. + /// + /// Emits a [`Event::DepositReleased`] event on success. + /// Errors with [`Error::Entered`] if safe-mode is entered. + /// Errors with [`Error::NoDeposit`] if the payee has no reserved currency at the + /// specified block. + /// + /// Can only be called by the [`Config::ForceDepositOrigin`] origin. + #[pallet::call_index(7)] + #[pallet::weight(T::WeightInfo::force_release_deposit())] + pub fn force_release_deposit( + origin: OriginFor, + account: T::AccountId, + block: BlockNumberFor, + ) -> DispatchResult { + T::ForceDepositOrigin::ensure_origin(origin)?; + + Self::do_release(true, account, block).map_err(Into::into) + } + } + + #[pallet::hooks] + impl Hooks> for Pallet { + /// Automatically exits safe-mode when the current block number is greater than + /// [`EnteredUntil`]. + fn on_initialize(current: BlockNumberFor) -> Weight { + let Some(limit) = EnteredUntil::::get() else { + return T::WeightInfo::on_initialize_noop(); + }; + + if current > limit { + let _ = Self::do_exit(ExitReason::Timeout).defensive_proof("Only Errors if safe-mode is not entered. Safe-mode has already been checked to be entered; qed"); + T::WeightInfo::on_initialize_exit() + } else { + T::WeightInfo::on_initialize_noop() + } + } + } +} + +impl Pallet { + /// Logic for the [`crate::Pallet::enter`] and [`crate::Pallet::force_enter`] calls. + pub(crate) fn do_enter( + who: Option, + duration: BlockNumberFor, + ) -> Result<(), Error> { + ensure!(!Self::is_entered(), Error::::Entered); + + if let Some(who) = who { + let amount = T::EnterDepositAmount::get().ok_or(Error::::NotConfigured)?; + Self::hold(who, amount)?; + } + + let until = >::block_number().saturating_add(duration); + EnteredUntil::::put(until); + Self::deposit_event(Event::Entered { until }); + T::Notify::entered(); + Ok(()) + } + + /// Logic for the [`crate::Pallet::extend`] and [`crate::Pallet::force_extend`] calls. + pub(crate) fn do_extend( + who: Option, + duration: BlockNumberFor, + ) -> Result<(), Error> { + let mut until = EnteredUntil::::get().ok_or(Error::::Exited)?; + + if let Some(who) = who { + let amount = T::ExtendDepositAmount::get().ok_or(Error::::NotConfigured)?; + Self::hold(who, amount)?; + } + + until.saturating_accrue(duration); + EnteredUntil::::put(until); + Self::deposit_event(Event::::Extended { until }); + Ok(()) + } + + /// Logic for the [`crate::Pallet::force_exit`] call. + /// + /// Errors if safe-mode is already exited. + pub(crate) fn do_exit(reason: ExitReason) -> Result<(), Error> { + let _until = EnteredUntil::::take().ok_or(Error::::Exited)?; + Self::deposit_event(Event::Exited { reason }); + T::Notify::exited(); + Ok(()) + } + + /// Logic for the [`crate::Pallet::release_deposit`] and + /// [`crate::Pallet::force_release_deposit`] calls. + pub(crate) fn do_release( + force: bool, + account: T::AccountId, + block: BlockNumberFor, + ) -> Result<(), Error> { + let amount = Deposits::::take(&account, &block).ok_or(Error::::NoDeposit)?; + + if !force { + ensure!(!Self::is_entered(), Error::::Entered); + + let delay = T::ReleaseDelay::get().ok_or(Error::::NotConfigured)?; + let now = >::block_number(); + ensure!(now > block.saturating_add(delay), Error::::CannotReleaseYet); + } + + let amount = T::Currency::release( + &&HoldReason::EnterOrExtend.into(), + &account, + amount, + Precision::BestEffort, + ) + .map_err(|_| Error::::CurrencyError)?; + Self::deposit_event(Event::::DepositReleased { account, amount }); + Ok(()) + } + + /// Logic for the [`crate::Pallet::slash_deposit`] call. + pub(crate) fn do_force_deposit( + account: T::AccountId, + block: BlockNumberFor, + ) -> Result<(), Error> { + let amount = Deposits::::take(&account, block).ok_or(Error::::NoDeposit)?; + + let burned = T::Currency::burn_held( + &&HoldReason::EnterOrExtend.into(), + &account, + amount, + Precision::BestEffort, + Fortitude::Force, + ) + .map_err(|_| Error::::CurrencyError)?; + defensive_assert!(burned == amount, "Could not burn the full held amount"); + Self::deposit_event(Event::::DepositSlashed { account, amount }); + Ok(()) + } + + /// Place a hold for exactly `amount` and store it in `Deposits`. + /// + /// Errors if the account already has a hold for the same reason. + fn hold(who: T::AccountId, amount: BalanceOf) -> Result<(), Error> { + let block = >::block_number(); + if !T::Currency::balance_on_hold(&HoldReason::EnterOrExtend.into(), &who).is_zero() { + return Err(Error::::AlreadyDeposited.into()) + } + + T::Currency::hold(&HoldReason::EnterOrExtend.into(), &who, amount) + .map_err(|_| Error::::CurrencyError)?; + Deposits::::insert(&who, block, amount); + Self::deposit_event(Event::::DepositPlaced { account: who, amount }); + + Ok(()) + } + + /// Return whether `safe-mode` is entered. + pub fn is_entered() -> bool { + EnteredUntil::::exists() + } + + /// Return whether the given call is allowed to be dispatched. + pub fn is_allowed(call: &T::RuntimeCall) -> bool + where + T::RuntimeCall: GetCallMetadata, + { + let CallMetadata { pallet_name, .. } = call.get_call_metadata(); + // SAFETY: The `SafeMode` pallet is always allowed. + if pallet_name == as PalletInfoAccess>::name() { + return true + } + + if Self::is_entered() { + T::WhitelistedCalls::contains(call) + } else { + true + } + } +} + +impl Contains for Pallet +where + T::RuntimeCall: GetCallMetadata, +{ + /// Return whether the given call is allowed to be dispatched. + fn contains(call: &T::RuntimeCall) -> bool { + Pallet::::is_allowed(call) + } +} + +impl frame_support::traits::SafeMode for Pallet { + type BlockNumber = BlockNumberFor; + + fn is_entered() -> bool { + Self::is_entered() + } + + fn remaining() -> Option> { + EnteredUntil::::get().map(|until| { + let now = >::block_number(); + until.saturating_sub(now) + }) + } + + fn enter(duration: BlockNumberFor) -> Result<(), frame_support::traits::SafeModeError> { + Self::do_enter(None, duration).map_err(Into::into) + } + + fn extend(duration: BlockNumberFor) -> Result<(), frame_support::traits::SafeModeError> { + Self::do_extend(None, duration).map_err(Into::into) + } + + fn exit() -> Result<(), frame_support::traits::SafeModeError> { + Self::do_exit(ExitReason::Force).map_err(Into::into) + } +} + +impl From> for frame_support::traits::SafeModeError { + fn from(err: Error) -> Self { + match err { + Error::::Entered => Self::AlreadyEntered, + Error::::Exited => Self::AlreadyExited, + _ => Self::Unknown, + } + } +} diff --git a/frame/safe-mode/src/mock.rs b/frame/safe-mode/src/mock.rs new file mode 100644 index 0000000000000..337b6076f84b9 --- /dev/null +++ b/frame/safe-mode/src/mock.rs @@ -0,0 +1,270 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests and test utilities for safe mode pallet. + +#![cfg(test)] + +use super::*; +use crate as pallet_safe_mode; + +use frame_support::{ + parameter_types, + traits::{ConstU64, Everything, InsideBoth, InstanceFilter, IsInVec, SafeModeNotify}, +}; +use frame_system::EnsureSignedBy; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +impl frame_system::Config for Test { + type BaseCallFilter = InsideBoth; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +/// Identifies a hold on an account's balance. +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, Debug, TypeInfo, +)] +pub enum HoldReason { + /// The safe-mode pallet holds funds since an account either entered or extended the safe-mode. + SafeMode, +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU64<2>; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = ConstU32<10>; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type FreezeIdentifier = (); + type MaxHolds = ConstU32<10>; + type MaxFreezes = ConstU32<0>; +} + +impl pallet_utility::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + +/// Mocked proxies to check that the safe-mode also works with the proxy pallet. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, +)] +pub enum ProxyType { + Any, + JustTransfer, + JustUtility, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::JustTransfer => { + matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) + }, + ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), + } + } + fn is_superset(&self, o: &Self) -> bool { + self == &ProxyType::Any || self == o + } +} + +impl pallet_proxy::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ConstU64<1>; + type ProxyDepositFactor = ConstU64<1>; + type MaxProxies = ConstU32<4>; + type WeightInfo = (); + type CallHasher = BlakeTwo256; + type MaxPending = ConstU32<2>; + type AnnouncementDepositBase = ConstU64<1>; + type AnnouncementDepositFactor = ConstU64<1>; +} + +/// The calls that can always bypass safe-mode. +pub struct WhitelistedCalls; +impl Contains for WhitelistedCalls { + fn contains(call: &RuntimeCall) -> bool { + match call { + RuntimeCall::Balances(_) => false, + _ => true, + } + } +} + +parameter_types! { + pub const EnterDuration: u64 = 7; + pub const ExtendDuration: u64 = 10; + pub const EnterDepositAmount: u64 = 100; + pub const ExtendDepositAmount: u64 = 100; + pub const ReleaseDelay: u64 = 20; + pub const SafeModeHoldReason: HoldReason = HoldReason::SafeMode; + + pub const ForceEnterWeak: u64 = 3; + pub const ForceEnterStrong: u64 = 5; + + pub const ForceExtendWeak: u64 = 11; + pub const ForceExtendStrong: u64 = 15; + + // NOTE: The account ID maps to the duration. Easy for testing. + pub ForceEnterOrigins: Vec = vec![ForceEnterWeak::get(), ForceEnterStrong::get()]; + pub ForceExtendOrigins: Vec = vec![ForceExtendWeak::get(), ForceExtendStrong::get()]; + + pub storage Notifications: Vec<(u64, bool)> = vec![]; +} + +pub struct MockedNotify; +impl SafeModeNotify for MockedNotify { + fn entered() { + let mut ns = Notifications::get(); + ns.push((>::block_number(), true)); + Notifications::set(&ns); + } + + fn exited() { + let mut ns = Notifications::get(); + ns.push((>::block_number(), false)); + Notifications::set(&ns); + } +} + +frame_support::ord_parameter_types! { + pub const ForceExitOrigin: u64 = 100; + pub const ForceDepositOrigin: u64 = 200; +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; + type WhitelistedCalls = WhitelistedCalls; + type EnterDuration = EnterDuration; + type EnterDepositAmount = EnterDepositAmount; + type ExtendDuration = ExtendDuration; + type ExtendDepositAmount = ExtendDepositAmount; + type ForceEnterOrigin = EnsureSignedBy, u64>; + type ForceExtendOrigin = EnsureSignedBy, u64>; + type ForceExitOrigin = EnsureSignedBy; + type ForceDepositOrigin = EnsureSignedBy; + type ReleaseDelay = ReleaseDelay; + type Notify = MockedNotify; + type WeightInfo = (); +} + +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + Balances: pallet_balances, + Utility: pallet_utility, + Proxy: pallet_proxy, + SafeMode: pallet_safe_mode, + } +); + +pub const BAL_ACC0: u64 = 1234; +pub const BAL_ACC1: u64 = 5678; + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { + // The 0 account is NOT a special origin, the rest may be. + balances: vec![(0, BAL_ACC0), (1, BAL_ACC1), (2, 5678), (3, 5678), (4, 5678)], + } + .assimilate_storage(&mut t) + .unwrap(); + pallet_safe_mode::GenesisConfig:: { entered_until: None } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} + +pub fn next_block() { + SafeMode::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + SafeMode::on_initialize(System::block_number()); +} + +pub fn run_to(n: u64) { + while System::block_number() < n { + next_block(); + } +} diff --git a/frame/safe-mode/src/tests.rs b/frame/safe-mode/src/tests.rs new file mode 100644 index 0000000000000..4ce9922d3b65c --- /dev/null +++ b/frame/safe-mode/src/tests.rs @@ -0,0 +1,613 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test utilities for the safe mode pallet. + +#![cfg(test)] + +use super::*; +use crate::mock::{RuntimeCall, *}; + +use frame_support::{assert_err, assert_noop, assert_ok, dispatch::Dispatchable, traits::Currency}; +use sp_runtime::TransactionOutcome; + +/// Do something hypothetically by rolling back any changes afterwards. +/// +/// Returns the original result of the closure. +macro_rules! hypothetically { + ( $e:expr ) => { + frame_support::storage::transactional::with_transaction( + || -> TransactionOutcome> { + sp_runtime::TransactionOutcome::Rollback(Ok($e)) + }, + ) + .expect("Always returning Ok; qed") + }; +} + +/// Assert something to be [*hypothetically*] `Ok` without actually committing it. +/// +/// Reverts any storage changes made by the closure. +macro_rules! hypothetically_ok { + ($e:expr $(, $args:expr)* $(,)?) => { + let result = hypothetically!($e); + assert_ok!(result $(, $args)*); + }; +} + +#[test] +fn fails_to_filter_calls_to_safe_mode_pallet() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + let activated_at_block = System::block_number(); + + assert_err!( + call_transfer().dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + + next_block(); + assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1))); + assert_ok!(SafeMode::force_extend(signed(ForceExtendStrong::get()))); + assert_err!( + call_transfer().dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get()))); + assert_ok!(SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + )); + + next_block(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_err!( + call_transfer().dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get()))); + assert_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + 2 + )); + }); +} + +#[test] +fn fails_to_activate_if_activated() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_noop!(SafeMode::enter(RuntimeOrigin::signed(2)), Error::::Entered); + }); +} + +#[test] +fn fails_to_extend_if_not_activated() { + new_test_ext().execute_with(|| { + assert_eq!(EnteredUntil::::get(), None); + assert_noop!(SafeMode::extend(RuntimeOrigin::signed(2)), Error::::Exited); + }); +} + +#[test] +fn fails_to_force_release_deposits_with_wrong_block() { + new_test_ext().execute_with(|| { + let activated_at_block = System::block_number(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + run_to(mock::EnterDuration::get() + activated_at_block + 1); + + assert_err!( + SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + 1 + ), + Error::::NoDeposit + ); + + assert_err!( + SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + 1 + ), + Error::::NoDeposit + ); + }); +} + +#[test] +fn fails_to_release_deposits_too_early() { + new_test_ext().execute_with(|| { + let activated_at_block = System::block_number(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get()))); + assert_err!( + SafeMode::release_deposit(RuntimeOrigin::signed(2), 0, activated_at_block), + Error::::CannotReleaseYet + ); + run_to(activated_at_block + mock::ReleaseDelay::get() + 1); + assert_ok!(SafeMode::release_deposit(RuntimeOrigin::signed(2), 0, activated_at_block)); + }); +} + +// GENERAL SUCCESS/POSITIVE TESTS --------------------- + +#[test] +fn can_automatically_deactivate_after_timeout() { + new_test_ext().execute_with(|| { + let activated_at_block = System::block_number(); + assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get()))); + run_to(1 + activated_at_block + ForceEnterWeak::get()); + + assert_eq!(EnteredUntil::::get(), None); + }); +} + +#[test] +fn can_filter_balance_calls_when_activated() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer().dispatch(RuntimeOrigin::signed(0))); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_err!( + call_transfer().dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn can_filter_balance_in_batch_when_activated() { + new_test_ext().execute_with(|| { + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer()] }); + + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + System::assert_last_event( + pallet_utility::Event::BatchInterrupted { + index: 0, + error: frame_system::Error::::CallFiltered.into(), + } + .into(), + ); + }); +} + +#[test] +fn can_filter_balance_in_proxy_when_activated() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); + + assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer()))); + System::assert_last_event(pallet_proxy::Event::ProxyExecuted { result: Ok(()) }.into()); + + assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get()))); + + assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer()))); + System::assert_last_event( + pallet_proxy::Event::ProxyExecuted { + result: DispatchError::from(frame_system::Error::::CallFiltered).into(), + } + .into(), + ); + }); +} + +#[test] +fn can_activate() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_eq!( + EnteredUntil::::get().unwrap(), + System::block_number() + mock::EnterDuration::get() + ); + assert_eq!(Balances::reserved_balance(0), mock::EnterDepositAmount::get()); + assert_eq!(Notifications::get(), vec![(1, true)]); + assert_noop!(SafeMode::enter(RuntimeOrigin::signed(0)), Error::::Entered); + assert_eq!(Notifications::get(), vec![(1, true)]); + // Assert the deposit. + assert_eq!(Deposits::::get(0, 1), Some(mock::EnterDepositAmount::get())); + }); +} + +#[test] +fn notify_works() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_eq!(Notifications::get(), vec![(1, true)]); + run_to(10); + assert_eq!(Notifications::get(), vec![(1, true), (9, false)]); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(1))); + assert_ok!(SafeMode::extend(RuntimeOrigin::signed(2))); + run_to(30); + assert_eq!(Notifications::get(), vec![(1, true), (9, false), (10, true), (28, false)]); + }); +} + +#[test] +fn cannot_extend() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_err!(SafeMode::extend(RuntimeOrigin::signed(0)), Error::::AlreadyDeposited); + assert_eq!( + EnteredUntil::::get().unwrap(), + System::block_number() + mock::EnterDuration::get() + ); + assert_eq!(Balances::reserved_balance(0), mock::EnterDepositAmount::get()); + assert_eq!(Notifications::get(), vec![(1, true)]); + }); +} + +#[test] +fn fails_signed_origin_when_explicit_origin_required() { + new_test_ext().execute_with(|| { + assert_eq!(EnteredUntil::::get(), None); + let activated_at_block = System::block_number(); + + assert_err!(SafeMode::force_enter(RuntimeOrigin::signed(0)), DispatchError::BadOrigin); + assert_err!(SafeMode::force_extend(RuntimeOrigin::signed(0)), DispatchError::BadOrigin); + assert_err!(SafeMode::force_exit(RuntimeOrigin::signed(0)), DispatchError::BadOrigin); + assert_err!( + SafeMode::force_slash_deposit(RuntimeOrigin::signed(0), 0, activated_at_block), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_release_deposit(RuntimeOrigin::signed(0), 0, activated_at_block), + DispatchError::BadOrigin + ); + }); +} + +// CONFIGURED ORIGIN CALL TESTS --------------------- + +#[test] +fn fails_force_deactivate_if_not_activated() { + new_test_ext().execute_with(|| { + assert_noop!( + SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())), + Error::::Exited + ); + assert_noop!( + SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceExitOrigin::get())), + Error::::Exited + ); + assert!(Notifications::get().is_empty()); + }); +} + +#[test] +fn can_force_activate_with_config_origin() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::force_enter(signed(ForceEnterStrong::get()))); + assert_eq!(Notifications::get(), vec![(1, true)]); + assert_eq!( + EnteredUntil::::get().unwrap(), + System::block_number() + ForceEnterStrong::get() + ); + assert_noop!( + SafeMode::force_enter(signed(ForceEnterStrong::get())), + Error::::Entered + ); + assert_eq!(Notifications::get(), vec![(1, true)]); + }); +} + +#[test] +fn can_force_deactivate_with_config_origin() { + new_test_ext().execute_with(|| { + assert_eq!(EnteredUntil::::get(), None); + assert_err!( + SafeMode::force_exit(RuntimeOrigin::signed(ForceExitOrigin::get())), + Error::::Exited + ); + assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get()))); + assert_ok!(SafeMode::force_exit(RuntimeOrigin::signed(ForceExitOrigin::get()))); + assert_eq!(Notifications::get(), vec![(1, true), (1, false)]); + }); +} + +#[test] +fn can_force_extend_with_config_origin() { + new_test_ext().execute_with(|| { + // Activated by `Weak` and extended by `Medium`. + assert_ok!(SafeMode::force_enter(signed(ForceEnterWeak::get()))); + assert_eq!( + EnteredUntil::::get().unwrap(), + System::block_number() + ForceEnterWeak::get() + ); + assert_ok!(SafeMode::force_extend(signed(ForceExtendWeak::get()))); + assert_eq!( + EnteredUntil::::get().unwrap(), + System::block_number() + ForceEnterWeak::get() + ForceExtendWeak::get() + ); + }); +} + +#[test] +fn can_force_release_deposit_with_config_origin() { + new_test_ext().execute_with(|| { + let activated_at_block = System::block_number(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + hypothetically_ok!(SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + ),); + run_to(mock::EnterDuration::get() + activated_at_block + 1); + + assert_ok!(SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + )); + assert_eq!(Balances::free_balance(&0), BAL_ACC0); // accounts set in mock genesis + + Balances::make_free_balance_be(&0, BAL_ACC0); + let activated_and_extended_at_block = System::block_number(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1))); + run_to( + mock::EnterDuration::get() + + mock::ExtendDuration::get() + + activated_and_extended_at_block + + 1, + ); + + assert_ok!(SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_and_extended_at_block + )); + assert_eq!(Balances::free_balance(&0), BAL_ACC0); // accounts set in mock genesis + }); +} + +#[test] +fn can_release_deposit_while_entered() { + new_test_ext().execute_with(|| { + assert_eq!(System::block_number(), 1); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert!(SafeMode::is_entered()); + + assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get()); + + // We could slash in the same block or any later. + for i in 0..mock::EnterDuration::get() + 10 { + run_to(i); + hypothetically_ok!(SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + )); + } + // Now once we slash once + assert_ok!(SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + ),); + assert_eq!(Balances::free_balance(&0), BAL_ACC0); + // ... it wont work ever again. + assert_err!( + SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + ), + Error::::NoDeposit + ); + }); +} + +#[test] +fn can_slash_deposit_while_entered() { + new_test_ext().execute_with(|| { + assert_eq!(System::block_number(), 1); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert!(SafeMode::is_entered()); + + // We could slash in the same block or any later. + for i in 0..mock::EnterDuration::get() + 10 { + run_to(i); + hypothetically_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + )); + } + // Now once we slash once + assert_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + ),); + // ... it wont work ever again. + assert_err!( + SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + ), + Error::::NoDeposit + ); + }); +} + +#[test] +fn can_slash_deposit_from_extend_block() { + new_test_ext().execute_with(|| { + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1))); + assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get()); + assert_eq!(Balances::free_balance(&1), BAL_ACC1 - mock::ExtendDepositAmount::get()); + + assert_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + ),); + assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get()); + + assert_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 1, + 1 + ),); + assert_eq!(Balances::free_balance(&1), BAL_ACC1 - mock::ExtendDepositAmount::get()); + + // But never again. + assert_err!( + SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + 1 + ), + Error::::NoDeposit + ); + assert_err!( + SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 1, + 1 + ), + Error::::NoDeposit + ); + }); +} + +#[test] +fn can_slash_deposit_with_config_origin() { + new_test_ext().execute_with(|| { + let activated_at_block = System::block_number(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + hypothetically_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + ),); + run_to(mock::EnterDuration::get() + activated_at_block + 1); + + assert_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_at_block + )); + // accounts set in mock genesis + assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get()); + + Balances::make_free_balance_be(&0, BAL_ACC0); + let activated_and_extended_at_block = System::block_number(); + assert_ok!(SafeMode::enter(RuntimeOrigin::signed(0))); + assert_ok!(SafeMode::extend(RuntimeOrigin::signed(1))); + run_to( + mock::EnterDuration::get() + + mock::ExtendDuration::get() + + activated_and_extended_at_block + + 1, + ); + + assert_ok!(SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceDepositOrigin::get()), + 0, + activated_and_extended_at_block + )); + // accounts set in mock genesis + assert_eq!(Balances::free_balance(&0), BAL_ACC0 - mock::EnterDepositAmount::get()); + }); +} + +#[test] +fn fails_when_explicit_origin_required() { + new_test_ext().execute_with(|| { + assert_eq!(EnteredUntil::::get(), None); + let activated_at_block = System::block_number(); + + assert_err!(SafeMode::force_extend(signed(1)), DispatchError::BadOrigin); + assert_err!(SafeMode::force_exit(signed(1)), DispatchError::BadOrigin); + assert_err!( + SafeMode::force_slash_deposit(signed(1), 0, activated_at_block), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_release_deposit(signed(1), 0, activated_at_block), + DispatchError::BadOrigin + ); + + assert_err!(SafeMode::force_enter(signed(1)), DispatchError::BadOrigin); + assert_err!(SafeMode::force_exit(signed(1)), DispatchError::BadOrigin); + assert_err!( + SafeMode::force_slash_deposit(signed(1), 0, activated_at_block), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_release_deposit(signed(1), 0, activated_at_block), + DispatchError::BadOrigin + ); + + assert_err!( + SafeMode::force_enter(RuntimeOrigin::signed(mock::ForceExitOrigin::get())), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_extend(RuntimeOrigin::signed(mock::ForceExitOrigin::get())), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_slash_deposit( + RuntimeOrigin::signed(mock::ForceExitOrigin::get()), + 0, + activated_at_block + ), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_release_deposit( + RuntimeOrigin::signed(mock::ForceExitOrigin::get()), + 0, + activated_at_block + ), + DispatchError::BadOrigin + ); + + assert_err!( + SafeMode::force_enter(RuntimeOrigin::signed(mock::ForceDepositOrigin::get())), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_extend(RuntimeOrigin::signed(mock::ForceDepositOrigin::get())), + DispatchError::BadOrigin + ); + assert_err!( + SafeMode::force_exit(RuntimeOrigin::signed(mock::ForceDepositOrigin::get())), + DispatchError::BadOrigin + ); + }); +} + +fn call_transfer() -> RuntimeCall { + RuntimeCall::Balances(pallet_balances::Call::transfer { dest: 1, value: 1 }) +} + +fn signed(who: u64) -> RuntimeOrigin { + RuntimeOrigin::signed(who) +} diff --git a/frame/safe-mode/src/weights.rs b/frame/safe-mode/src/weights.rs new file mode 100644 index 0000000000000..f72bebcab9a4d --- /dev/null +++ b/frame/safe-mode/src/weights.rs @@ -0,0 +1,321 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for `pallet_safe_mode` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-aahe6cbd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// target/production/substrate-node +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_safe_mode +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/safe-mode/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_safe_mode`. +pub trait WeightInfo { + fn on_initialize_noop() -> Weight; + fn on_initialize_exit() -> Weight; + fn enter() -> Weight; + fn force_enter() -> Weight; + fn extend() -> Weight; + fn force_extend() -> Weight; + fn force_exit() -> Weight; + fn release_deposit() -> Weight; + fn force_release_deposit() -> Weight; + fn force_slash_deposit() -> Weight; +} + +/// Weights for `pallet_safe_mode` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn on_initialize_noop() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `1489` + // Minimum execution time: 2_500_000 picoseconds. + Weight::from_parts(2_594_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn on_initialize_exit() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `1489` + // Minimum execution time: 8_868_000 picoseconds. + Weight::from_parts(9_415_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::Deposits` (r:0 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn enter() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `3550` + // Minimum execution time: 50_541_000 picoseconds. + Weight::from_parts(51_558_000, 3550) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn force_enter() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `1489` + // Minimum execution time: 10_489_000 picoseconds. + Weight::from_parts(10_833_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::Deposits` (r:0 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn extend() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `3550` + // Minimum execution time: 50_818_000 picoseconds. + Weight::from_parts(51_873_000, 3550) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn force_extend() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `1489` + // Minimum execution time: 10_843_000 picoseconds. + Weight::from_parts(11_314_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn force_exit() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `1489` + // Minimum execution time: 10_382_000 picoseconds. + Weight::from_parts(10_814_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::Deposits` (r:1 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn release_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `292` + // Estimated: `3550` + // Minimum execution time: 42_828_000 picoseconds. + Weight::from_parts(43_752_000, 3550) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `SafeMode::Deposits` (r:1 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn force_release_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `292` + // Estimated: `3550` + // Minimum execution time: 40_196_000 picoseconds. + Weight::from_parts(41_298_000, 3550) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `SafeMode::Deposits` (r:1 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn force_slash_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `292` + // Estimated: `3550` + // Minimum execution time: 33_660_000 picoseconds. + Weight::from_parts(34_426_000, 3550) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn on_initialize_noop() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `1489` + // Minimum execution time: 2_500_000 picoseconds. + Weight::from_parts(2_594_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn on_initialize_exit() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `1489` + // Minimum execution time: 8_868_000 picoseconds. + Weight::from_parts(9_415_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::Deposits` (r:0 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn enter() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `3550` + // Minimum execution time: 50_541_000 picoseconds. + Weight::from_parts(51_558_000, 3550) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn force_enter() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `1489` + // Minimum execution time: 10_489_000 picoseconds. + Weight::from_parts(10_833_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::Deposits` (r:0 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn extend() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `3550` + // Minimum execution time: 50_818_000 picoseconds. + Weight::from_parts(51_873_000, 3550) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn force_extend() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `1489` + // Minimum execution time: 10_843_000 picoseconds. + Weight::from_parts(11_314_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn force_exit() -> Weight { + // Proof Size summary in bytes: + // Measured: `169` + // Estimated: `1489` + // Minimum execution time: 10_382_000 picoseconds. + Weight::from_parts(10_814_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `SafeMode::Deposits` (r:1 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn release_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `292` + // Estimated: `3550` + // Minimum execution time: 42_828_000 picoseconds. + Weight::from_parts(43_752_000, 3550) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `SafeMode::Deposits` (r:1 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn force_release_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `292` + // Estimated: `3550` + // Minimum execution time: 40_196_000 picoseconds. + Weight::from_parts(41_298_000, 3550) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `SafeMode::Deposits` (r:1 w:1) + /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + fn force_slash_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `292` + // Estimated: `3550` + // Minimum execution time: 33_660_000 picoseconds. + Weight::from_parts(34_426_000, 3550) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } +} diff --git a/frame/salary/Cargo.toml b/frame/salary/Cargo.toml index 8fedecf4cec97..330b746fc1e3f 100644 --- a/frame/salary/Cargo.toml +++ b/frame/salary/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../primi sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", @@ -49,5 +49,5 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/salary/src/lib.rs b/frame/salary/src/lib.rs index 53dd7224909a8..75d6fdd329ac8 100644 --- a/frame/salary/src/lib.rs +++ b/frame/salary/src/lib.rs @@ -23,7 +23,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_arithmetic::traits::{Saturating, Zero}; -use sp_runtime::Perbill; +use sp_runtime::{Perbill, RuntimeDebug}; use sp_std::{marker::PhantomData, prelude::*}; use frame_support::{ @@ -33,7 +33,6 @@ use frame_support::{ tokens::{GetSalary, Pay, PaymentStatus}, RankedMembers, }, - RuntimeDebug, }; #[cfg(test)] diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 1d583d0892f9c..edc39924319d1 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -28,14 +28,14 @@ sp-core = { version = "21.0.0", default-features = false, path = "../../primitiv substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] std = [ "codec/std", @@ -43,17 +43,17 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-preimage/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", "sp-weights/std", - "pallet-preimage/std", - "sp-core/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-preimage/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index 58dd23d241cf8..6bed5b04aef87 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -26,21 +26,21 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index d8c6ef9b0f444..591c910488b16 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -21,12 +21,13 @@ use super::*; use crate as pallet_scored_pool; use frame_support::{ - bounded_vec, construct_runtime, ord_parameter_types, parameter_types, + construct_runtime, ord_parameter_types, parameter_types, traits::{ConstU32, ConstU64}, }; use frame_system::EnsureSignedBy; use sp_core::H256; use sp_runtime::{ + bounded_vec, traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 0858ae6656540..1fc5f4c1ab8c2 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -27,10 +27,11 @@ sp-session = { version = "4.0.0-dev", default-features = false, path = "../../pr sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking", features = ["serde"] } sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } sp-trie = { version = "22.0.0", default-features = false, optional = true, path = "../../primitives/trie" } +sp-state-machine = { version = "0.28.0", default-features = false, path = "../../primitives/state-machine" } [features] -default = ["historical", "std"] -historical = ["sp-trie"] +default = [ "historical", "std" ] +historical = [ "sp-trie" ] std = [ "codec/std", "frame-support/std", @@ -43,6 +44,7 @@ std = [ "sp-runtime/std", "sp-session/std", "sp-staking/std", + "sp-state-machine/std", "sp-std/std", "sp-trie/std", ] @@ -50,5 +52,5 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index a26cacc561e82..5db6821da1fab 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -13,6 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } rand = { version = "0.8.5", default-features = false, features = ["std_rng"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } @@ -34,31 +35,31 @@ sp-core = { version = "21.0.0", path = "../../../primitives/core" } sp-io = { version = "23.0.0", path = "../../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ "frame-benchmarking/std", + "frame-election-provider-support/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "pallet-session/std", "pallet-staking/std", + "pallet-timestamp/std", "rand/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-session/std", "sp-std/std", - "frame-election-provider-support/std", - "pallet-balances/std", - "pallet-timestamp/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ - "pallet-staking/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index cbf5d67ba567c..722bb14fb56ed 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -26,11 +26,9 @@ mod mock; use sp_runtime::traits::{One, StaticLookup, TrailingZeroInput}; use sp_std::{prelude::*, vec}; +use codec::Decode; use frame_benchmarking::v1::benchmarks; -use frame_support::{ - codec::Decode, - traits::{Get, KeyOwnerProofSystem, OnInitialize}, -}; +use frame_support::traits::{Get, KeyOwnerProofSystem, OnInitialize}; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use pallet_session::{historical::Pallet as Historical, Pallet as Session, *}; use pallet_staking::{ diff --git a/frame/session/src/historical/mod.rs b/frame/session/src/historical/mod.rs index 04129e4eba130..d74e9dd0b7c54 100644 --- a/frame/session/src/historical/mod.rs +++ b/frame/session/src/historical/mod.rs @@ -378,11 +378,9 @@ pub(crate) mod tests { }; use sp_runtime::{key_types::DUMMY, testing::UintAuthorityId, BuildStorage}; + use sp_state_machine::BasicExternalities; - use frame_support::{ - traits::{KeyOwnerProofSystem, OnInitialize}, - BasicExternalities, - }; + use frame_support::traits::{KeyOwnerProofSystem, OnInitialize}; type Historical = Pallet; diff --git a/frame/session/src/historical/offchain.rs b/frame/session/src/historical/offchain.rs index c44eea2f374c0..1b4d53b74b45e 100644 --- a/frame/session/src/historical/offchain.rs +++ b/frame/session/src/historical/offchain.rs @@ -150,11 +150,9 @@ mod tests { offchain::{testing::TestOffchainExt, OffchainDbExt, OffchainWorkerExt, StorageKind}, }; use sp_runtime::{testing::UintAuthorityId, BuildStorage}; + use sp_state_machine::BasicExternalities; - use frame_support::{ - traits::{KeyOwnerProofSystem, OnInitialize}, - BasicExternalities, - }; + use frame_support::traits::{KeyOwnerProofSystem, OnInitialize}; type Historical = Pallet; diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index d2b1c2b744674..1c0093c1df64f 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -115,8 +115,8 @@ mod mock; mod tests; pub mod weights; +use codec::{Decode, MaxEncodedLen}; use frame_support::{ - codec::{Decode, MaxEncodedLen}, dispatch::{DispatchError, DispatchResult}, ensure, traits::{ diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index b45ebfd25c44a..2db54e1a59756 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -32,11 +32,11 @@ use sp_runtime::{ BuildStorage, }; use sp_staking::SessionIndex; +use sp_state_machine::BasicExternalities; use frame_support::{ parameter_types, traits::{ConstU32, ConstU64}, - BasicExternalities, }; impl_opaque_keys! { diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index 38f2ca66bd195..55e5c1e01cb19 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -33,38 +33,36 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] # Enable `VersionedRuntimeUpgrade` for the migrations that is currently still experimental. -experimental = [ - "frame-support/experimental" -] +experimental = [ "frame-support/experimental" ] std = [ "codec/std", "frame-benchmarking?/std", + "frame-support-test/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "rand_chacha/std", "scale-info/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-io/std", - "frame-support-test/std", - "pallet-balances/std", - "sp-arithmetic/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking", - "sp-runtime/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-support-test/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 19a437ce4ccfc..2ad9b44d7b4b2 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -50,50 +50,50 @@ frame-election-provider-support = { version = "4.0.0-dev", path = "../election-p rand_chacha = { version = "0.2" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", - "serde/std", "codec/std", - "scale-info/std", - "sp-std/std", - "sp-io/std", + "frame-benchmarking?/std", + "frame-election-provider-support/std", "frame-support/std", - "sp-runtime/std", - "sp-staking/std", - "pallet-session/std", "frame-system/std", - "pallet-authorship/std", - "sp-application-crypto/std", "log/std", - "frame-election-provider-support/std", + "pallet-authorship/std", "pallet-bags-list/std", "pallet-balances/std", + "pallet-session/std", "pallet-timestamp/std", + "scale-info/std", + "serde/std", + "sp-application-crypto/std", "sp-core/std", + "sp-io/std", "sp-npos-elections/std", - "sp-tracing/std" + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", + "sp-tracing/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-election-provider-support/runtime-benchmarks", - "rand_chacha", - "sp-staking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "rand_chacha", + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "frame-support/try-runtime", "frame-election-provider-support/try-runtime", + "frame-support/try-runtime", "frame-system/try-runtime", "pallet-authorship/try-runtime", "pallet-bags-list/try-runtime", "pallet-balances/try-runtime", "pallet-session/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/staking/reward-fn/Cargo.toml b/frame/staking/reward-fn/Cargo.toml index 3561eeb8a90c2..a80210f7d9f19 100644 --- a/frame/staking/reward-fn/Cargo.toml +++ b/frame/staking/reward-fn/Cargo.toml @@ -18,8 +18,5 @@ log = { version = "0.4.17", default-features = false } sp-arithmetic = { version = "16.0.0", default-features = false, path = "../../../primitives/arithmetic" } [features] -default = ["std"] -std = [ - "log/std", - "sp-arithmetic/std", -] +default = [ "std" ] +std = [ "log/std", "sp-arithmetic/std" ] diff --git a/frame/staking/runtime-api/Cargo.toml b/frame/staking/runtime-api/Cargo.toml index 5c9af0ad3cbe8..afb7ce721cd2e 100644 --- a/frame/staking/runtime-api/Cargo.toml +++ b/frame/staking/runtime-api/Cargo.toml @@ -17,8 +17,5 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } [features] -default = ["std"] -std = [ - "codec/std", - "sp-api/std", -] +default = [ "std" ] +std = [ "codec/std", "sp-api/std" ] diff --git a/frame/staking/src/migrations.rs b/frame/staking/src/migrations.rs index 0a27290daacd8..332da506f01ed 100644 --- a/frame/staking/src/migrations.rs +++ b/frame/staking/src/migrations.rs @@ -296,7 +296,7 @@ pub mod v10 { pub mod v9 { use super::*; #[cfg(feature = "try-runtime")] - use frame_support::codec::{Decode, Encode}; + use codec::{Decode, Encode}; #[cfg(feature = "try-runtime")] use sp_std::vec::Vec; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 29539cbb84cf7..fd7dabac74d8d 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -23,7 +23,7 @@ use frame_election_provider_support::{ ElectionProvider, SortedListProvider, Support, }; use frame_support::{ - assert_noop, assert_ok, assert_storage_noop, bounded_vec, + assert_noop, assert_ok, assert_storage_noop, dispatch::{extract_actual_weight, GetDispatchInfo, WithPostDispatchInfo}, pallet_prelude::*, traits::{Currency, Get, ReservableCurrency}, @@ -31,7 +31,7 @@ use frame_support::{ use mock::*; use pallet_balances::Error as BalancesError; use sp_runtime::{ - assert_eq_error_rate, + assert_eq_error_rate, bounded_vec, traits::{BadOrigin, Dispatchable}, Perbill, Percent, Rounding, TokenError, }; diff --git a/frame/state-trie-migration/Cargo.toml b/frame/state-trie-migration/Cargo.toml index dd2693f10a851..d1bed941d4cce 100644 --- a/frame/state-trie-migration/Cargo.toml +++ b/frame/state-trie-migration/Cargo.toml @@ -35,20 +35,20 @@ pallet-balances = { path = "../balances" } sp-tracing = { path = "../../primitives/tracing" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-tracing/std" + "sp-tracing/std", ] runtime-benchmarks = [ "frame-benchmarking", @@ -56,12 +56,19 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", +] +remote-test = [ + "remote-externalities", + "serde", + "std", + "substrate-state-trie-migration-rpc", + "thousands", + "zstd", ] -remote-test = [ "remote-externalities", "serde", "std", "substrate-state-trie-migration-rpc", "thousands", "zstd" ] diff --git a/frame/state-trie-migration/src/lib.rs b/frame/state-trie-migration/src/lib.rs index c5b41cd9a4439..e22a47458b7d5 100644 --- a/frame/state-trie-migration/src/lib.rs +++ b/frame/state-trie-migration/src/lib.rs @@ -1268,8 +1268,8 @@ mod mock { #[cfg(test)] mod test { use super::{mock::*, *}; - use frame_support::{bounded_vec, dispatch::*}; - use sp_runtime::{traits::Bounded, StateVersion}; + use frame_support::dispatch::*; + use sp_runtime::{bounded_vec, traits::Bounded, StateVersion}; #[test] fn fails_if_no_migration() { diff --git a/frame/statement/Cargo.toml b/frame/statement/Cargo.toml index cc51258165c90..4740c421d7f46 100644 --- a/frame/statement/Cargo.toml +++ b/frame/statement/Cargo.toml @@ -31,20 +31,20 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } default = [ "std" ] std = [ "codec/std", - "scale-info/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", + "scale-info/std", "sp-api/std", - "sp-runtime/std", - "sp-std/std", - "sp-io/std", "sp-core/std", + "sp-io/std", + "sp-runtime/std", "sp-statement-store/std", - "pallet-balances/std" + "sp-std/std", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 9f3851d91ef54..ed46ad53c2f61 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -26,26 +26,26 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../primitives sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "frame-support/runtime-benchmarks" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index da6ee19e04a0d..d115a83722ac8 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -28,6 +28,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" } sp-weights = { version = "20.0.0", default-features = false, path = "../../primitives/weights" } sp-debug-derive = { default-features = false, path = "../../primitives/debug-derive" } +sp-metadata-ir = { version = "0.1.0", default-features = false, path = "../../primitives/metadata-ir" } tt-call = "1.0.8" macro_magic = "0.4.2" frame-support-procedural = { version = "4.0.0-dev", default-features = false, path = "./procedural" } @@ -43,6 +44,7 @@ environmental = { version = "1.1.4", default-features = false } sp-genesis-builder = { version = "0.1.0", default-features=false, path = "../../primitives/genesis-builder" } serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] } docify = "0.2.1" +static_assertions = "1.1.0" aquamarine = { version = "0.3.2" } @@ -53,49 +55,53 @@ frame-system = { version = "4.0.0-dev", path = "../system" } array-bytes = "6.1" [features] -default = ["std"] +default = [ "std" ] std = [ - "sp-core/std", + "codec/std", + "environmental/std", + "frame-metadata/std", + "frame-support-procedural/std", + "frame-system/std", "k256/std", + "log/std", + "scale-info/std", "serde/std", "sp-api/std", - "sp-io/std", - "codec/std", - "scale-info/std", - "sp-std/std", - "sp-runtime/std", - "sp-tracing/std", "sp-arithmetic/std", - "frame-metadata/std", + "sp-core/std", + "sp-debug-derive/std", + "sp-genesis-builder/std", "sp-inherents/std", + "sp-io/std", + "sp-metadata-ir/std", + "sp-runtime/std", "sp-staking/std", "sp-state-machine/std", + "sp-std/std", + "sp-tracing/std", "sp-weights/std", - "frame-support-procedural/std", - "log/std", - "environmental/std", - "sp-genesis-builder/std", - "frame-system/std", - "sp-debug-derive/std" ] runtime-benchmarks = [ "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks" + "sp-staking/runtime-benchmarks", ] try-runtime = [ - "sp-debug-derive/force-debug", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-debug-derive/force-debug", + "sp-runtime/try-runtime", ] experimental = [] # By default some types have documentation, `no-metadata-docs` allows to reduce the documentation # in the metadata. -no-metadata-docs = ["frame-support-procedural/no-metadata-docs", "sp-api/no-metadata-docs"] +no-metadata-docs = [ + "frame-support-procedural/no-metadata-docs", + "sp-api/no-metadata-docs", +] # By default some types have documentation, `full-metadata-docs` allows to add documentation to # more types in the metadata. -full-metadata-docs = ["scale-info/docs"] +full-metadata-docs = [ "scale-info/docs" ] # Generate impl-trait for tuples with the given number of tuples. Will be needed as the number of # pallets in a runtime grows. Does increase the compile time! -tuples-96 = ["frame-support-procedural/tuples-96"] -tuples-128 = ["frame-support-procedural/tuples-128"] +tuples-96 = [ "frame-support-procedural/tuples-96" ] +tuples-128 = [ "frame-support-procedural/tuples-128" ] diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 1d201d5a87fc5..a5d4e9e2e801f 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] derive-syn-parse = "0.1.5" Inflector = "0.11.4" -cfg-expr = "0.15.1" +cfg-expr = "0.15.4" itertools = "0.10.3" proc-macro2 = "1.0.56" quote = "1.0.28" @@ -28,7 +28,7 @@ macro_magic = { version = "0.4.2", features = ["proc_support"] } expander = "2.0.0" [features] -default = ["std"] +default = [ "std" ] std = [] no-metadata-docs = [] # Generate impl-trait for tuples with the given number of tuples. Will be needed as the number of diff --git a/frame/support/procedural/src/benchmark.rs b/frame/support/procedural/src/benchmark.rs index 9f28e7129d2e1..6f8f1d155e1e5 100644 --- a/frame/support/procedural/src/benchmark.rs +++ b/frame/support/procedural/src/benchmark.rs @@ -419,7 +419,6 @@ pub fn benchmarks( }; let krate = generate_crate_access_2018("frame-benchmarking")?; - let support = quote!(#krate::frame_support); // benchmark name variables let benchmark_names_str: Vec = benchmark_names.iter().map(|n| n.to_string()).collect(); @@ -456,7 +455,7 @@ pub fn benchmarks( } impl<#type_impl_generics> #krate::BenchmarkingSetup<#type_use_generics> for SelectedBenchmark where #where_clause { - fn components(&self) -> #krate::Vec<(#krate::BenchmarkParameter, u32, u32)> { + fn components(&self) -> #krate::__private::Vec<(#krate::BenchmarkParameter, u32, u32)> { match self { #( Self::#benchmark_names => { @@ -472,7 +471,7 @@ pub fn benchmarks( components: &[(#krate::BenchmarkParameter, u32)], verify: bool, ) -> Result< - #krate::Box Result<(), #krate::BenchmarkError>>, + #krate::__private::Box Result<(), #krate::BenchmarkError>>, #krate::BenchmarkError, > { match self { @@ -493,8 +492,8 @@ pub fn benchmarks( { fn benchmarks( extra: bool, - ) -> #krate::Vec<#krate::BenchmarkMetadata> { - let mut all_names = #krate::vec![ + ) -> #krate::__private::Vec<#krate::BenchmarkMetadata> { + let mut all_names = #krate::__private::vec![ #(#benchmark_names_str), * ]; @@ -519,17 +518,17 @@ pub fn benchmarks( // https://github.com/paritytech/substrate/issues/13132 pov_modes: vec![], } - }).collect::<#krate::Vec<_>>() + }).collect::<#krate::__private::Vec<_>>() } fn run_benchmark( extrinsic: &[u8], c: &[(#krate::BenchmarkParameter, u32)], - whitelist: &[#krate::TrackedStorageKey], + whitelist: &[#krate::__private::TrackedStorageKey], verify: bool, internal_repeats: u32, - ) -> Result<#krate::Vec<#krate::BenchmarkResult>, #krate::BenchmarkError> { - let extrinsic = #krate::str::from_utf8(extrinsic).map_err(|_| "`extrinsic` is not a valid utf-8 string!")?; + ) -> Result<#krate::__private::Vec<#krate::BenchmarkResult>, #krate::BenchmarkError> { + let extrinsic = #krate::__private::str::from_utf8(extrinsic).map_err(|_| "`extrinsic` is not a valid utf-8 string!")?; let selected_benchmark = match extrinsic { #(#selected_benchmark_mappings), *, @@ -538,32 +537,32 @@ pub fn benchmarks( let mut whitelist = whitelist.to_vec(); let whitelisted_caller_key = as #support::storage::StorageMap<_, _,>>::hashed_key_for( + > as #krate::__private::storage::StorageMap<_, _,>>::hashed_key_for( #krate::whitelisted_caller::() ); whitelist.push(whitelisted_caller_key.into()); - let transactional_layer_key = #krate::TrackedStorageKey::new( - #support::storage::transactional::TRANSACTION_LEVEL_KEY.into(), + let transactional_layer_key = #krate::__private::TrackedStorageKey::new( + #krate::__private::storage::transactional::TRANSACTION_LEVEL_KEY.into(), ); whitelist.push(transactional_layer_key); // Whitelist the `:extrinsic_index`. - let extrinsic_index = #krate::TrackedStorageKey::new( - #krate::well_known_keys::EXTRINSIC_INDEX.into() + let extrinsic_index = #krate::__private::TrackedStorageKey::new( + #krate::__private::well_known_keys::EXTRINSIC_INDEX.into() ); whitelist.push(extrinsic_index); // Whitelist the `:intrablock_entropy`. - let intrablock_entropy = #krate::TrackedStorageKey::new( - #krate::well_known_keys::INTRABLOCK_ENTROPY.into() + let intrablock_entropy = #krate::__private::TrackedStorageKey::new( + #krate::__private::well_known_keys::INTRABLOCK_ENTROPY.into() ); whitelist.push(intrablock_entropy); #krate::benchmarking::set_whitelist(whitelist.clone()); - let mut results: #krate::Vec<#krate::BenchmarkResult> = #krate::Vec::new(); + let mut results: #krate::__private::Vec<#krate::BenchmarkResult> = #krate::__private::Vec::new(); // Always do at least one internal repeat... for _ in 0 .. internal_repeats.max(1) { // Always reset the state after the benchmark. - #krate::defer!(#krate::benchmarking::wipe_db()); + #krate::__private::defer!(#krate::benchmarking::wipe_db()); // Set up the externalities environment for the setup we want to // benchmark. @@ -572,7 +571,7 @@ pub fn benchmarks( >::instance(&selected_benchmark, c, verify)?; // Set the block number to at least 1 so events are deposited. - if #krate::Zero::is_zero(&frame_system::Pallet::::block_number()) { + if #krate::__private::Zero::is_zero(&frame_system::Pallet::::block_number()) { frame_system::Pallet::::set_block_number(1u32.into()); } @@ -583,14 +582,14 @@ pub fn benchmarks( // Access all whitelisted keys to get them into the proof recorder since the // recorder does now have a whitelist. for key in &whitelist { - #krate::frame_support::storage::unhashed::get_raw(&key.key); + #krate::__private::storage::unhashed::get_raw(&key.key); } // Reset the read/write counter so we don't count operations in the setup process. #krate::benchmarking::reset_read_write_count(); // Time the extrinsic logic. - #krate::log::trace!( + #krate::__private::log::trace!( target: "benchmark", "Start Benchmark: {} ({:?})", extrinsic, @@ -614,25 +613,25 @@ pub fn benchmarks( // Commit the changes to get proper write count #krate::benchmarking::commit_db(); - #krate::log::trace!( + #krate::__private::log::trace!( target: "benchmark", "End Benchmark: {} ns", elapsed_extrinsic ); let read_write_count = #krate::benchmarking::read_write_count(); - #krate::log::trace!( + #krate::__private::log::trace!( target: "benchmark", "Read/Write Count {:?}", read_write_count ); // Time the storage root recalculation. let start_storage_root = #krate::benchmarking::current_time(); - #krate::storage_root(#krate::StateVersion::V1); + #krate::__private::storage_root(#krate::__private::StateVersion::V1); let finish_storage_root = #krate::benchmarking::current_time(); let elapsed_storage_root = finish_storage_root - start_storage_root; let skip_meta = [ #(#skip_meta_benchmark_names_str),* ]; let read_and_written_keys = if skip_meta.contains(&extrinsic) { - #krate::vec![(b"Skipped Metadata".to_vec(), 0, 0, false)] + #krate::__private::vec![(b"Skipped Metadata".to_vec(), 0, 0, false)] } else { #krate::benchmarking::get_read_and_written_keys() }; @@ -667,7 +666,7 @@ pub fn benchmarks( /// author chooses not to implement benchmarks. #[allow(unused)] fn test_bench_by_name(name: &[u8]) -> Result<(), #krate::BenchmarkError> { - let name = #krate::str::from_utf8(name) + let name = #krate::__private::str::from_utf8(name) .map_err(|_| -> #krate::BenchmarkError { "`name` is not a valid utf8 string!".into() })?; match name { #(#benchmarks_by_name_mappings), @@ -724,8 +723,8 @@ fn expand_benchmark( Ok(ident) => ident, Err(err) => return err.to_compile_error().into(), }; - let codec = quote!(#krate::frame_support::codec); - let traits = quote!(#krate::frame_support::traits); + let codec = quote!(#krate::__private::codec); + let traits = quote!(#krate::__private::traits); let setup_stmts = benchmark_def.setup_stmts; let verify_stmts = benchmark_def.verify_stmts; let last_stmt = benchmark_def.last_stmt; @@ -894,8 +893,8 @@ fn expand_benchmark( #[allow(unused_variables)] impl<#type_impl_generics> #krate::BenchmarkingSetup<#type_use_generics> for #name where #where_clause { - fn components(&self) -> #krate::Vec<(#krate::BenchmarkParameter, u32, u32)> { - #krate::vec! [ + fn components(&self) -> #krate::__private::Vec<(#krate::BenchmarkParameter, u32, u32)> { + #krate::__private::vec! [ #( (#krate::BenchmarkParameter::#param_ranges) ),* @@ -906,7 +905,7 @@ fn expand_benchmark( &self, components: &[(#krate::BenchmarkParameter, u32)], verify: bool - ) -> Result<#krate::Box Result<(), #krate::BenchmarkError>>, #krate::BenchmarkError> { + ) -> Result<#krate::__private::Box Result<(), #krate::BenchmarkError>>, #krate::BenchmarkError> { #( // prepare instance #param_names let #param_names = components.iter() @@ -920,7 +919,7 @@ fn expand_benchmark( #setup_stmts )* #pre_call - Ok(#krate::Box::new(move || -> Result<(), #krate::BenchmarkError> { + Ok(#krate::__private::Box::new(move || -> Result<(), #krate::BenchmarkError> { #post_call if verify { #( @@ -941,10 +940,10 @@ fn expand_benchmark( SelectedBenchmark as #krate::BenchmarkingSetup >::components(&selected_benchmark); let execute_benchmark = | - c: #krate::Vec<(#krate::BenchmarkParameter, u32)> + c: #krate::__private::Vec<(#krate::BenchmarkParameter, u32)> | -> Result<(), #krate::BenchmarkError> { // Always reset the state after the benchmark. - #krate::defer!(#krate::benchmarking::wipe_db()); + #krate::__private::defer!(#krate::benchmarking::wipe_db()); // Set up the benchmark, return execution + verification function. let closure_to_verify = < @@ -952,7 +951,7 @@ fn expand_benchmark( >::instance(&selected_benchmark, &c, true)?; // Set the block number to at least 1 so events are deposited. - if #krate::Zero::is_zero(&frame_system::Pallet::::block_number()) { + if #krate::__private::Zero::is_zero(&frame_system::Pallet::::block_number()) { frame_system::Pallet::::set_block_number(1u32.into()); } @@ -985,7 +984,7 @@ fn expand_benchmark( return Err("The start of a `ParamRange` must be less than or equal to the end".into()); } - let mut values = #krate::vec![low]; + let mut values = #krate::__private::vec![low]; let diff = (high - low).min(num_values - 1); let slope = (high - low) as f32 / diff as f32; @@ -997,7 +996,7 @@ fn expand_benchmark( for component_value in values { // Select the max value for all the other components. - let c: #krate::Vec<(#krate::BenchmarkParameter, u32)> = components + let c: #krate::__private::Vec<(#krate::BenchmarkParameter, u32)> = components .iter() .map(|(n, _, h)| if *n == name { diff --git a/frame/support/procedural/src/construct_runtime/expand/call.rs b/frame/support/procedural/src/construct_runtime/expand/call.rs index cc4841418beec..cbf2ea9078535 100644 --- a/frame/support/procedural/src/construct_runtime/expand/call.rs +++ b/frame/support/procedural/src/construct_runtime/expand/call.rs @@ -68,10 +68,10 @@ pub fn expand_outer_dispatch( #[derive( Clone, PartialEq, Eq, - #scrate::codec::Encode, - #scrate::codec::Decode, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, + #scrate::__private::codec::Decode, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] pub enum RuntimeCall { #variant_defs @@ -166,7 +166,7 @@ pub fn expand_outer_dispatch( type PostInfo = #scrate::dispatch::PostDispatchInfo; fn dispatch(self, origin: RuntimeOrigin) -> #scrate::dispatch::DispatchResultWithPostInfo { if !::filter_call(&origin, &self) { - return #scrate::sp_std::result::Result::Err( + return #scrate::__private::sp_std::result::Result::Err( #system_path::Error::<#runtime>::CallFiltered.into() ); } diff --git a/frame/support/procedural/src/construct_runtime/expand/config.rs b/frame/support/procedural/src/construct_runtime/expand/config.rs index 440e856221a36..ffe55bceb80ef 100644 --- a/frame/support/procedural/src/construct_runtime/expand/config.rs +++ b/frame/support/procedural/src/construct_runtime/expand/config.rs @@ -67,8 +67,8 @@ pub fn expand_outer_config( #types - use #scrate::serde as __genesis_config_serde_import__; - #[derive(#scrate::serde::Serialize, #scrate::serde::Deserialize, Default)] + use #scrate::__private::serde as __genesis_config_serde_import__; + #[derive(#scrate::__private::serde::Serialize, #scrate::__private::serde::Deserialize, Default)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] #[serde(crate = "__genesis_config_serde_import__")] @@ -86,7 +86,7 @@ pub fn expand_outer_config( &self, storage: &mut #scrate::sp_runtime::Storage, ) -> std::result::Result<(), String> { - #scrate::BasicExternalities::execute_with_storage(storage, || { + #scrate::__private::BasicExternalities::execute_with_storage(storage, || { ::build(&self); Ok(()) }) diff --git a/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs b/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs index d357fab72115b..b142f8e84c92f 100644 --- a/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs +++ b/frame/support/procedural/src/construct_runtime/expand/freeze_reason.rs @@ -38,9 +38,9 @@ pub fn expand_outer_freeze_reason(pallet_decls: &[Pallet], scrate: &TokenStream) /// A reason for placing a freeze on funds. #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, - #scrate::codec::Encode, #scrate::codec::Decode, #scrate::codec::MaxEncodedLen, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] pub enum RuntimeFreezeReason { #( #freeze_reason_variants )* diff --git a/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs b/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs index 6acfe5382f18a..ed7183c4a150d 100644 --- a/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs +++ b/frame/support/procedural/src/construct_runtime/expand/hold_reason.rs @@ -38,9 +38,9 @@ pub fn expand_outer_hold_reason(pallet_decls: &[Pallet], scrate: &TokenStream) - /// A reason for placing a hold on funds. #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, - #scrate::codec::Encode, #scrate::codec::Decode, #scrate::codec::MaxEncodedLen, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] pub enum RuntimeHoldReason { #( #hold_reason_variants )* diff --git a/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/frame/support/procedural/src/construct_runtime/expand/inherent.rs index 1dc51d9cd2bc4..a77aad66dcfc2 100644 --- a/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -58,17 +58,17 @@ pub fn expand_outer_inherent( trait InherentDataExt { fn create_extrinsics(&self) -> - #scrate::sp_std::vec::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic>; + #scrate::__private::sp_std::vec::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic>; fn check_extrinsics(&self, block: &#block) -> #scrate::inherent::CheckInherentsResult; } impl InherentDataExt for #scrate::inherent::InherentData { fn create_extrinsics(&self) -> - #scrate::sp_std::vec::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic> + #scrate::__private::sp_std::vec::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic> { use #scrate::inherent::ProvideInherent; - let mut inherents = #scrate::sp_std::vec::Vec::new(); + let mut inherents = #scrate::__private::sp_std::vec::Vec::new(); #( #pallet_attrs @@ -91,7 +91,7 @@ pub fn expand_outer_inherent( use #scrate::traits::{IsSubType, ExtrinsicCall}; use #scrate::sp_runtime::traits::Block as _; use #scrate::_private::sp_inherents::Error; - use #scrate::log; + use #scrate::__private::log; let mut result = #scrate::inherent::CheckInherentsResult::new(); diff --git a/frame/support/procedural/src/construct_runtime/expand/lock_id.rs b/frame/support/procedural/src/construct_runtime/expand/lock_id.rs index d7031dcaf552b..ba35147a051fb 100644 --- a/frame/support/procedural/src/construct_runtime/expand/lock_id.rs +++ b/frame/support/procedural/src/construct_runtime/expand/lock_id.rs @@ -38,9 +38,9 @@ pub fn expand_outer_lock_id(pallet_decls: &[Pallet], scrate: &TokenStream) -> To /// An identifier for each lock placed on funds. #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, - #scrate::codec::Encode, #scrate::codec::Decode, #scrate::codec::MaxEncodedLen, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] pub enum RuntimeLockId { #( #lock_id_variants )* diff --git a/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/frame/support/procedural/src/construct_runtime/expand/metadata.rs index 0975fedb35d5b..0e76f9a92469a 100644 --- a/frame/support/procedural/src/construct_runtime/expand/metadata.rs +++ b/frame/support/procedural/src/construct_runtime/expand/metadata.rs @@ -61,7 +61,7 @@ pub fn expand_runtime_metadata( quote! { #attr - #scrate::metadata_ir::PalletMetadataIR { + #scrate::__private::metadata_ir::PalletMetadataIR { name: stringify!(#name), index: #index, storage: #storage, @@ -77,7 +77,7 @@ pub fn expand_runtime_metadata( quote! { impl #runtime { - fn metadata_ir() -> #scrate::metadata_ir::MetadataIR { + fn metadata_ir() -> #scrate::__private::metadata_ir::MetadataIR { // Each runtime must expose the `runtime_metadata()` to fetch the runtime API metadata. // The function is implemented by calling `impl_runtime_apis!`. // @@ -96,23 +96,23 @@ pub fn expand_runtime_metadata( // `Deref` needs a reference for resolving the function call. let rt = #runtime; - let ty = #scrate::scale_info::meta_type::<#extrinsic>(); - let address_ty = #scrate::scale_info::meta_type::< + let ty = #scrate::__private::scale_info::meta_type::<#extrinsic>(); + let address_ty = #scrate::__private::scale_info::meta_type::< <<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::SignaturePayload as #scrate::sp_runtime::traits::SignaturePayload>::SignatureAddress >(); - let call_ty = #scrate::scale_info::meta_type::< + let call_ty = #scrate::__private::scale_info::meta_type::< <#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::Call >(); - let signature_ty = #scrate::scale_info::meta_type::< + let signature_ty = #scrate::__private::scale_info::meta_type::< <<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::SignaturePayload as #scrate::sp_runtime::traits::SignaturePayload>::Signature >(); - let extra_ty = #scrate::scale_info::meta_type::< + let extra_ty = #scrate::__private::scale_info::meta_type::< <<#extrinsic as #scrate::sp_runtime::traits::Extrinsic>::SignaturePayload as #scrate::sp_runtime::traits::SignaturePayload>::SignatureExtra >(); - #scrate::metadata_ir::MetadataIR { - pallets: #scrate::sp_std::vec![ #(#pallets),* ], - extrinsic: #scrate::metadata_ir::ExtrinsicMetadataIR { + #scrate::__private::metadata_ir::MetadataIR { + pallets: #scrate::__private::sp_std::vec![ #(#pallets),* ], + extrinsic: #scrate::__private::metadata_ir::ExtrinsicMetadataIR { ty, version: <#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata>::VERSION, address_ty, @@ -125,39 +125,39 @@ pub fn expand_runtime_metadata( >::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension >::metadata() .into_iter() - .map(|meta| #scrate::metadata_ir::SignedExtensionMetadataIR { + .map(|meta| #scrate::__private::metadata_ir::SignedExtensionMetadataIR { identifier: meta.identifier, ty: meta.ty, additional_signed: meta.additional_signed, }) .collect(), }, - ty: #scrate::scale_info::meta_type::<#runtime>(), + ty: #scrate::__private::scale_info::meta_type::<#runtime>(), apis: (&rt).runtime_metadata(), - outer_enums: #scrate::metadata_ir::OuterEnumsIR { - call_enum_ty: #scrate::scale_info::meta_type::< + outer_enums: #scrate::__private::metadata_ir::OuterEnumsIR { + call_enum_ty: #scrate::__private::scale_info::meta_type::< <#runtime as #system_path::Config>::RuntimeCall >(), - event_enum_ty: #scrate::scale_info::meta_type::(), - error_enum_ty: #scrate::scale_info::meta_type::(), + event_enum_ty: #scrate::__private::scale_info::meta_type::(), + error_enum_ty: #scrate::__private::scale_info::meta_type::(), } } } - pub fn metadata() -> #scrate::metadata::RuntimeMetadataPrefixed { + pub fn metadata() -> #scrate::__private::metadata::RuntimeMetadataPrefixed { // Note: this always returns the V14 version. The runtime API function // must be deprecated. - #scrate::metadata_ir::into_v14(#runtime::metadata_ir()) + #scrate::__private::metadata_ir::into_v14(#runtime::metadata_ir()) } - pub fn metadata_at_version(version: u32) -> Option<#scrate::OpaqueMetadata> { - #scrate::metadata_ir::into_version(#runtime::metadata_ir(), version).map(|prefixed| { - #scrate::OpaqueMetadata::new(prefixed.into()) + pub fn metadata_at_version(version: u32) -> Option<#scrate::__private::OpaqueMetadata> { + #scrate::__private::metadata_ir::into_version(#runtime::metadata_ir(), version).map(|prefixed| { + #scrate::__private::OpaqueMetadata::new(prefixed.into()) }) } - pub fn metadata_versions() -> #scrate::sp_std::vec::Vec { - #scrate::metadata_ir::supported_versions() + pub fn metadata_versions() -> #scrate::__private::sp_std::vec::Vec { + #scrate::__private::metadata_ir::supported_versions() } } } @@ -220,8 +220,8 @@ fn expand_pallet_metadata_events( quote! { Some( - #scrate::metadata_ir::PalletEventMetadataIR { - ty: #scrate::scale_info::meta_type::<#pallet_event>() + #scrate::__private::metadata_ir::PalletEventMetadataIR { + ty: #scrate::__private::scale_info::meta_type::<#pallet_event>() } ) } diff --git a/frame/support/procedural/src/construct_runtime/expand/origin.rs b/frame/support/procedural/src/construct_runtime/expand/origin.rs index 0eaa73f603068..b421d2aaffabe 100644 --- a/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -105,25 +105,25 @@ pub fn expand_outer_origin( #[derive(Clone)] pub struct RuntimeOrigin { caller: OriginCaller, - filter: #scrate::sp_std::rc::Rc::RuntimeCall) -> bool>>, + filter: #scrate::__private::sp_std::rc::Rc::RuntimeCall) -> bool>>, } #[cfg(not(feature = "std"))] - impl #scrate::sp_std::fmt::Debug for RuntimeOrigin { + impl #scrate::__private::sp_std::fmt::Debug for RuntimeOrigin { fn fmt( &self, - fmt: &mut #scrate::sp_std::fmt::Formatter, - ) -> #scrate::sp_std::result::Result<(), #scrate::sp_std::fmt::Error> { + fmt: &mut #scrate::__private::sp_std::fmt::Formatter, + ) -> #scrate::__private::sp_std::result::Result<(), #scrate::__private::sp_std::fmt::Error> { fmt.write_str("") } } #[cfg(feature = "std")] - impl #scrate::sp_std::fmt::Debug for RuntimeOrigin { + impl #scrate::__private::sp_std::fmt::Debug for RuntimeOrigin { fn fmt( &self, - fmt: &mut #scrate::sp_std::fmt::Formatter, - ) -> #scrate::sp_std::result::Result<(), #scrate::sp_std::fmt::Error> { + fmt: &mut #scrate::__private::sp_std::fmt::Formatter, + ) -> #scrate::__private::sp_std::result::Result<(), #scrate::__private::sp_std::fmt::Error> { fmt.debug_struct("Origin") .field("caller", &self.caller) .field("filter", &"[function ptr]") @@ -139,7 +139,7 @@ pub fn expand_outer_origin( fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static) { let f = self.filter.clone(); - self.filter = #scrate::sp_std::rc::Rc::new(Box::new(move |call| { + self.filter = #scrate::__private::sp_std::rc::Rc::new(Box::new(move |call| { f(call) && filter(call) })); } @@ -150,7 +150,7 @@ pub fn expand_outer_origin( as #scrate::traits::Contains<<#runtime as #system_path::Config>::RuntimeCall> >::contains; - self.filter = #scrate::sp_std::rc::Rc::new(Box::new(filter)); + self.filter = #scrate::__private::sp_std::rc::Rc::new(Box::new(filter)); } fn set_caller_from(&mut self, other: impl Into) { @@ -197,8 +197,8 @@ pub fn expand_outer_origin( } #[derive( - Clone, PartialEq, Eq, #scrate::RuntimeDebug, #scrate::codec::Encode, - #scrate::codec::Decode, #scrate::scale_info::TypeInfo, #scrate::codec::MaxEncodedLen, + Clone, PartialEq, Eq, #scrate::__private::RuntimeDebug, #scrate::__private::codec::Encode, + #scrate::__private::codec::Decode, #scrate::__private::scale_info::TypeInfo, #scrate::__private::codec::MaxEncodedLen, )] #[allow(non_camel_case_types)] pub enum OriginCaller { @@ -206,7 +206,7 @@ pub fn expand_outer_origin( system(#system_path::Origin<#runtime>), #caller_variants #[allow(dead_code)] - Void(#scrate::Void) + Void(#scrate::__private::Void) } // For backwards compatibility and ease of accessing these functions. @@ -252,7 +252,7 @@ pub fn expand_outer_origin( impl TryFrom for #system_path::Origin<#runtime> { type Error = OriginCaller; fn try_from(x: OriginCaller) - -> #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, OriginCaller> + -> #scrate::__private::sp_std::result::Result<#system_path::Origin<#runtime>, OriginCaller> { if let OriginCaller::system(l) = x { Ok(l) @@ -275,7 +275,7 @@ pub fn expand_outer_origin( fn from(x: OriginCaller) -> Self { let mut o = RuntimeOrigin { caller: x, - filter: #scrate::sp_std::rc::Rc::new(Box::new(|_| true)), + filter: #scrate::__private::sp_std::rc::Rc::new(Box::new(|_| true)), }; #scrate::traits::OriginTrait::reset_filter(&mut o); @@ -284,7 +284,7 @@ pub fn expand_outer_origin( } } - impl From for #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, RuntimeOrigin> { + impl From for #scrate::__private::sp_std::result::Result<#system_path::Origin<#runtime>, RuntimeOrigin> { /// NOTE: converting to pallet origin loses the origin filter information. fn from(val: RuntimeOrigin) -> Self { if let OriginCaller::system(l) = val.caller { @@ -394,7 +394,7 @@ fn expand_origin_pallet_conversions( } #attr - impl From for #scrate::sp_std::result::Result<#pallet_origin, RuntimeOrigin> { + impl From for #scrate::__private::sp_std::result::Result<#pallet_origin, RuntimeOrigin> { /// NOTE: converting to pallet origin loses the origin filter information. fn from(val: RuntimeOrigin) -> Self { if let OriginCaller::#variant_name(l) = val.caller { @@ -410,7 +410,7 @@ fn expand_origin_pallet_conversions( type Error = OriginCaller; fn try_from( x: OriginCaller, - ) -> #scrate::sp_std::result::Result<#pallet_origin, OriginCaller> { + ) -> #scrate::__private::sp_std::result::Result<#pallet_origin, OriginCaller> { if let OriginCaller::#variant_name(l) = x { Ok(l) } else { @@ -424,7 +424,7 @@ fn expand_origin_pallet_conversions( type Error = (); fn try_from( x: &'a OriginCaller, - ) -> #scrate::sp_std::result::Result<&'a #pallet_origin, ()> { + ) -> #scrate::__private::sp_std::result::Result<&'a #pallet_origin, ()> { if let OriginCaller::#variant_name(l) = x { Ok(&l) } else { @@ -438,7 +438,7 @@ fn expand_origin_pallet_conversions( type Error = (); fn try_from( x: &'a RuntimeOrigin, - ) -> #scrate::sp_std::result::Result<&'a #pallet_origin, ()> { + ) -> #scrate::__private::sp_std::result::Result<&'a #pallet_origin, ()> { if let OriginCaller::#variant_name(l) = &x.caller { Ok(&l) } else { diff --git a/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs b/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs index b78360d5fc052..df69c19a4b617 100644 --- a/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs +++ b/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs @@ -159,10 +159,10 @@ pub fn expand_outer_enum( #[derive( #event_custom_derives - #scrate::codec::Encode, - #scrate::codec::Decode, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, + #scrate::__private::codec::Decode, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] #[allow(non_camel_case_types)] pub enum #enum_name_ident { @@ -247,7 +247,7 @@ fn expand_enum_conversion( impl TryInto<#pallet_enum> for #enum_name_ident { type Error = (); - fn try_into(self) -> #scrate::sp_std::result::Result<#pallet_enum, Self::Error> { + fn try_into(self) -> #scrate::__private::sp_std::result::Result<#pallet_enum, Self::Error> { match self { Self::#variant_name(evt) => Ok(evt), _ => Err(()), @@ -273,8 +273,8 @@ fn generate_error_impl(scrate: &TokenStream, enum_ty: OuterEnumType) -> TokenStr pub fn from_dispatch_error(err: #scrate::sp_runtime::DispatchError) -> Option { let #scrate::sp_runtime::DispatchError::Module(module_error) = err else { return None }; - let bytes = #scrate::codec::Encode::encode(&module_error); - #scrate::codec::Decode::decode(&mut &bytes[..]).ok() + let bytes = #scrate::__private::codec::Encode::encode(&module_error); + #scrate::__private::codec::Decode::decode(&mut &bytes[..]).ok() } } } diff --git a/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs b/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs index abffb97d43981..2a3283230ad84 100644 --- a/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs +++ b/frame/support/procedural/src/construct_runtime/expand/slash_reason.rs @@ -38,9 +38,9 @@ pub fn expand_outer_slash_reason(pallet_decls: &[Pallet], scrate: &TokenStream) /// A reason for slashing funds. #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, - #scrate::codec::Encode, #scrate::codec::Decode, #scrate::codec::MaxEncodedLen, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] pub enum RuntimeSlashReason { #( #slash_reason_variants )* diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index efc2244154479..f42dd837e3a95 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -94,11 +94,11 @@ //! ``` //! This call has some implicit pallet parts, thus it will expand to: //! ```ignore -//! frame_support::tt_call! { +//! frame_support::__private::tt_call! { //! macro = [{ pallet_balances::tt_default_parts }] //! ~~> frame_support::match_and_insert! { //! target = [{ -//! frame_support::tt_call! { +//! frame_support::__private::tt_call! { //! macro = [{ frame_system::tt_default_parts }] //! ~~> frame_support::match_and_insert! { //! target = [{ @@ -280,7 +280,7 @@ fn construct_runtime_implicit_to_explicit( let pallet_name = &pallet.name; let pallet_instance = pallet.instance.as_ref().map(|instance| quote::quote!(::<#instance>)); expansion = quote::quote!( - #frame_support::tt_call! { + #frame_support::__private::tt_call! { macro = [{ #pallet_path::tt_default_parts }] frame_support = [{ #frame_support }] ~~> #frame_support::match_and_insert! { @@ -316,7 +316,7 @@ fn construct_runtime_explicit_to_explicit_expanded( let pallet_name = &pallet.name; let pallet_instance = pallet.instance.as_ref().map(|instance| quote::quote!(::<#instance>)); expansion = quote::quote!( - #frame_support::tt_call! { + #frame_support::__private::tt_call! { macro = [{ #pallet_path::tt_extra_parts }] frame_support = [{ #frame_support }] ~~> #frame_support::match_and_insert! { @@ -428,7 +428,7 @@ fn construct_runtime_final_expansion( #[derive( Clone, Copy, PartialEq, Eq, #scrate::sp_runtime::RuntimeDebug, - #scrate::scale_info::TypeInfo + #scrate::__private::scale_info::TypeInfo )] pub struct #name; impl #scrate::sp_runtime::traits::GetRuntimeBlockType for #name { @@ -453,7 +453,7 @@ fn construct_runtime_final_expansion( #[doc(hidden)] trait InternalConstructRuntime { #[inline(always)] - fn runtime_metadata(&self) -> #scrate::sp_std::vec::Vec<#scrate::metadata_ir::RuntimeApiMetadataIR> { + fn runtime_metadata(&self) -> #scrate::__private::sp_std::vec::Vec<#scrate::__private::metadata_ir::RuntimeApiMetadataIR> { Default::default() } } @@ -700,10 +700,10 @@ fn decl_pallet_runtime_setup( impl #scrate::traits::PalletInfo for PalletInfo { fn index() -> Option { - let type_id = #scrate::sp_std::any::TypeId::of::

(); + let type_id = #scrate::__private::sp_std::any::TypeId::of::

(); #( #pallet_attrs - if type_id == #scrate::sp_std::any::TypeId::of::<#names>() { + if type_id == #scrate::__private::sp_std::any::TypeId::of::<#names>() { return Some(#indices) } )* @@ -712,10 +712,10 @@ fn decl_pallet_runtime_setup( } fn name() -> Option<&'static str> { - let type_id = #scrate::sp_std::any::TypeId::of::

(); + let type_id = #scrate::__private::sp_std::any::TypeId::of::

(); #( #pallet_attrs - if type_id == #scrate::sp_std::any::TypeId::of::<#names>() { + if type_id == #scrate::__private::sp_std::any::TypeId::of::<#names>() { return Some(#name_strings) } )* @@ -724,10 +724,10 @@ fn decl_pallet_runtime_setup( } fn module_name() -> Option<&'static str> { - let type_id = #scrate::sp_std::any::TypeId::of::

(); + let type_id = #scrate::__private::sp_std::any::TypeId::of::

(); #( #pallet_attrs - if type_id == #scrate::sp_std::any::TypeId::of::<#names>() { + if type_id == #scrate::__private::sp_std::any::TypeId::of::<#names>() { return Some(#module_names) } )* @@ -736,10 +736,10 @@ fn decl_pallet_runtime_setup( } fn crate_version() -> Option<#scrate::traits::CrateVersion> { - let type_id = #scrate::sp_std::any::TypeId::of::

(); + let type_id = #scrate::__private::sp_std::any::TypeId::of::

(); #( #pallet_attrs - if type_id == #scrate::sp_std::any::TypeId::of::<#names>() { + if type_id == #scrate::__private::sp_std::any::TypeId::of::<#names>() { return Some( <#pallet_structs as #scrate::traits::PalletInfoAccess>::crate_version() ) @@ -760,7 +760,7 @@ fn decl_integrity_test(scrate: &TokenStream2) -> TokenStream2 { #[test] pub fn runtime_integrity_tests() { - #scrate::sp_tracing::try_init_simple(); + #scrate::__private::sp_tracing::try_init_simple(); ::integrity_test(); } } @@ -781,7 +781,7 @@ fn decl_static_assertions( ); quote! { - #scrate::tt_call! { + #scrate::__private::tt_call! { macro = [{ #path::tt_error_token }] frame_support = [{ #scrate }] ~~> #scrate::assert_error_encoded_size! { diff --git a/frame/support/procedural/src/derive_impl.rs b/frame/support/procedural/src/derive_impl.rs index 5ea44c35bb646..8b5e334f1f551 100644 --- a/frame/support/procedural/src/derive_impl.rs +++ b/frame/support/procedural/src/derive_impl.rs @@ -22,14 +22,46 @@ use macro_magic::mm_core::ForeignPath; use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens}; use std::collections::HashSet; -use syn::{parse2, parse_quote, spanned::Spanned, Ident, ImplItem, ItemImpl, Path, Result, Token}; +use syn::{ + parse2, parse_quote, spanned::Spanned, token, Ident, ImplItem, ItemImpl, Path, Result, Token, +}; -#[derive(Parse)] +mod keyword { + syn::custom_keyword!(inject_runtime_type); + syn::custom_keyword!(no_aggregated_types); +} + +#[derive(derive_syn_parse::Parse, PartialEq, Eq)] +pub enum PalletAttrType { + #[peek(keyword::inject_runtime_type, name = "inject_runtime_type")] + RuntimeType(keyword::inject_runtime_type), +} + +#[derive(derive_syn_parse::Parse)] +pub struct PalletAttr { + _pound: Token![#], + #[bracket] + _bracket: token::Bracket, + #[inside(_bracket)] + typ: PalletAttrType, +} + +fn get_first_item_pallet_attr(item: &syn::ImplItemType) -> syn::Result> +where + Attr: syn::parse::Parse, +{ + item.attrs.get(0).map(|a| syn::parse2(a.into_token_stream())).transpose() +} + +#[derive(Parse, Debug)] pub struct DeriveImplAttrArgs { pub default_impl_path: Path, _as: Option, #[parse_if(_as.is_some())] pub disambiguation_path: Option, + _comma: Option, + #[parse_if(_comma.is_some())] + pub no_aggregated_types: Option, } impl ForeignPath for DeriveImplAttrArgs { @@ -43,6 +75,8 @@ impl ToTokens for DeriveImplAttrArgs { tokens.extend(self.default_impl_path.to_token_stream()); tokens.extend(self._as.to_token_stream()); tokens.extend(self.disambiguation_path.to_token_stream()); + tokens.extend(self._comma.to_token_stream()); + tokens.extend(self.no_aggregated_types.to_token_stream()); } } @@ -78,6 +112,7 @@ fn combine_impls( foreign_impl: ItemImpl, default_impl_path: Path, disambiguation_path: Path, + inject_runtime_types: bool, ) -> ItemImpl { let (existing_local_keys, existing_unsupported_items): (HashSet, HashSet) = local_impl @@ -96,7 +131,20 @@ fn combine_impls( // do not copy colliding items that have an ident return None } - if matches!(item, ImplItem::Type(_)) { + if let ImplItem::Type(typ) = item.clone() { + let mut typ = typ.clone(); + if let Ok(Some(PalletAttr { typ: PalletAttrType::RuntimeType(_), .. })) = + get_first_item_pallet_attr::(&mut typ) + { + let item: ImplItem = if inject_runtime_types { + parse_quote! { + type #ident = #ident; + } + } else { + item + }; + return Some(item) + } // modify and insert uncolliding type items let modified_item: ImplItem = parse_quote! { type #ident = <#default_impl_path as #disambiguation_path>::#ident; @@ -132,6 +180,7 @@ pub fn derive_impl( foreign_tokens: TokenStream2, local_tokens: TokenStream2, disambiguation_path: Option, + no_aggregated_types: Option, ) -> Result { let local_impl = parse2::(local_tokens)?; let foreign_impl = parse2::(foreign_tokens)?; @@ -151,8 +200,13 @@ pub fn derive_impl( }; // generate the combined impl - let combined_impl = - combine_impls(local_impl, foreign_impl, default_impl_path, disambiguation_path); + let combined_impl = combine_impls( + local_impl, + foreign_impl, + default_impl_path, + disambiguation_path, + no_aggregated_types.is_none(), + ); Ok(quote!(#combined_impl)) } diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 2a46696ed4f70..9957cf1cff85c 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -38,7 +38,7 @@ use macro_magic::import_tokens_attr; use proc_macro::TokenStream; use quote::{quote, ToTokens}; use std::{cell::RefCell, str::FromStr}; -use syn::{parse_macro_input, Error, ItemImpl, ItemMod}; +use syn::{parse_macro_input, Error, ItemImpl, ItemMod, TraitItemType}; pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; @@ -596,6 +596,19 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream /// /// Conversely, the `default_impl_path` argument is required and cannot be omitted. /// +/// Optionally, `no_aggregated_types` can be specified as follows: +/// +/// ```ignore +/// #[derive_impl(default_impl_path as disambiguation_path, no_aggregated_types)] +/// impl SomeTrait for SomeStruct { +/// ... +/// } +/// ``` +/// +/// If specified, this indicates that the aggregated types (as denoted by impl items +/// attached with [`#[inject_runtime_type]`]) should not be injected with the respective concrete +/// types. By default, all such types are injected. +/// /// You can also make use of `#[pallet::no_default]` on specific items in your default impl that you /// want to ensure will not be copied over but that you nonetheless want to use locally in the /// context of the foreign impl and the pallet (or context) in which it is defined. @@ -759,6 +772,7 @@ pub fn derive_impl(attrs: TokenStream, input: TokenStream) -> TokenStream { attrs.into(), input.into(), custom_attrs.disambiguation_path, + custom_attrs.no_aggregated_types, ) .unwrap_or_else(|r| r.into_compile_error()) .into() @@ -774,6 +788,19 @@ pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } +/// The optional attribute `#[pallet::no_default_bounds]` can be attached to trait items within a +/// `Config` trait impl that has [`#[pallet::config(with_default)]`](`macro@config`) attached. +/// +/// Attaching this attribute to a trait item ensures that the generated trait `DefaultConfig` +/// will not have any bounds for this trait item. +/// +/// As an example, if you have a trait item `type AccountId: SomeTrait;` in your `Config` trait, +/// the generated `DefaultConfig` will only have `type AccountId;` with no trait bound. +#[proc_macro_attribute] +pub fn no_default_bounds(_: TokenStream, _: TokenStream) -> TokenStream { + pallet_macro_stub() +} + /// Attach this attribute to an impl statement that you want to use with /// [`#[derive_impl(..)]`](`macro@derive_impl`). /// @@ -843,6 +870,25 @@ pub fn register_default_impl(attrs: TokenStream, tokens: TokenStream) -> TokenSt } } +#[proc_macro_attribute] +pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { + let item = tokens.clone(); + let item = syn::parse_macro_input!(item as TraitItemType); + if item.ident != "RuntimeCall" && + item.ident != "RuntimeEvent" && + item.ident != "RuntimeOrigin" && + item.ident != "PalletInfo" + { + return syn::Error::new_spanned( + item, + "`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo`", + ) + .to_compile_error() + .into(); + } + tokens +} + /// Used internally to decorate pallet attribute macro stubs when they are erroneously used /// outside of a pallet module fn pallet_macro_stub() -> TokenStream { diff --git a/frame/support/procedural/src/pallet/expand/call.rs b/frame/support/procedural/src/pallet/expand/call.rs index aa6a8e09f5250..6489949ed5c33 100644 --- a/frame/support/procedural/src/pallet/expand/call.rs +++ b/frame/support/procedural/src/pallet/expand/call.rs @@ -275,9 +275,9 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::CloneNoBound, #frame_support::EqNoBound, #frame_support::PartialEqNoBound, - #frame_support::codec::Encode, - #frame_support::codec::Decode, - #frame_support::scale_info::TypeInfo, + #frame_support::__private::codec::Encode, + #frame_support::__private::codec::Decode, + #frame_support::__private::scale_info::TypeInfo, )] #[codec(encode_bound())] #[codec(decode_bound())] @@ -287,7 +287,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { #[doc(hidden)] #[codec(skip)] __Ignore( - #frame_support::sp_std::marker::PhantomData<(#type_use_gen,)>, + #frame_support::__private::sp_std::marker::PhantomData<(#type_use_gen,)>, #frame_support::Never, ), #( @@ -394,8 +394,8 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { match self { #( Self::#fn_name { #( #args_name_pattern, )* } => { - #frame_support::sp_tracing::enter_span!( - #frame_support::sp_tracing::trace_span!(stringify!(#fn_name)) + #frame_support::__private::sp_tracing::enter_span!( + #frame_support::__private::sp_tracing::trace_span!(stringify!(#fn_name)) ); #maybe_allow_attrs <#pallet_ident<#type_use_gen>>::#fn_name(origin, #( #args_name, )* ) @@ -419,8 +419,8 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { impl<#type_impl_gen> #pallet_ident<#type_use_gen> #where_clause { #[doc(hidden)] - pub fn call_functions() -> #frame_support::metadata_ir::PalletCallMetadataIR { - #frame_support::scale_info::meta_type::<#call_ident<#type_use_gen>>().into() + pub fn call_functions() -> #frame_support::__private::metadata_ir::PalletCallMetadataIR { + #frame_support::__private::scale_info::meta_type::<#call_ident<#type_use_gen>>().into() } } ) diff --git a/frame/support/procedural/src/pallet/expand/config.rs b/frame/support/procedural/src/pallet/expand/config.rs index c1b8eb022471f..5cf4035a8f8b9 100644 --- a/frame/support/procedural/src/pallet/expand/config.rs +++ b/frame/support/procedural/src/pallet/expand/config.rs @@ -52,7 +52,23 @@ Consequently, a runtime that wants to include this pallet must implement this tr // impossible consequently. match &config.default_sub_trait { Some(default_sub_trait) if default_sub_trait.items.len() > 0 => { - let trait_items = &default_sub_trait.items; + let trait_items = &default_sub_trait + .items + .iter() + .map(|item| { + if item.1 { + if let syn::TraitItem::Type(item) = item.0.clone() { + let mut item = item.clone(); + item.bounds.clear(); + syn::TraitItem::Type(item) + } else { + item.0.clone() + } + } else { + item.0.clone() + } + }) + .collect::>(); let type_param_bounds = if default_sub_trait.has_system { let system = &def.frame_system; diff --git a/frame/support/procedural/src/pallet/expand/constants.rs b/frame/support/procedural/src/pallet/expand/constants.rs index 6e1cd3df627f3..57fa8b7f3cd9a 100644 --- a/frame/support/procedural/src/pallet/expand/constants.rs +++ b/frame/support/procedural/src/pallet/expand/constants.rs @@ -54,7 +54,7 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { default_byte_impl: quote::quote!( let value = <::#ident as #frame_support::traits::Get<#const_type>>::get(); - #frame_support::codec::Encode::encode(&value) + #frame_support::__private::codec::Encode::encode(&value) ), metadata_name: None, } @@ -69,7 +69,7 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { doc: const_.doc.clone(), default_byte_impl: quote::quote!( let value = >::#ident(); - #frame_support::codec::Encode::encode(&value) + #frame_support::__private::codec::Encode::encode(&value) ), metadata_name: const_.metadata_name.clone(), } @@ -85,11 +85,11 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { let default_byte_impl = &const_.default_byte_impl; quote::quote!({ - #frame_support::metadata_ir::PalletConstantMetadataIR { + #frame_support::__private::metadata_ir::PalletConstantMetadataIR { name: #ident_str, - ty: #frame_support::scale_info::meta_type::<#const_type>(), + ty: #frame_support::__private::scale_info::meta_type::<#const_type>(), value: { #default_byte_impl }, - docs: #frame_support::sp_std::vec![ #( #doc ),* ], + docs: #frame_support::__private::sp_std::vec![ #( #doc ),* ], } }) }); @@ -99,9 +99,9 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { #[doc(hidden)] pub fn pallet_constants_metadata() - -> #frame_support::sp_std::vec::Vec<#frame_support::metadata_ir::PalletConstantMetadataIR> + -> #frame_support::__private::sp_std::vec::Vec<#frame_support::__private::metadata_ir::PalletConstantMetadataIR> { - #frame_support::sp_std::vec![ #( #consts ),* ] + #frame_support::__private::sp_std::vec![ #( #consts ),* ] } } ) diff --git a/frame/support/procedural/src/pallet/expand/documentation.rs b/frame/support/procedural/src/pallet/expand/documentation.rs index 4e6347e83bb73..ec19f889a9f20 100644 --- a/frame/support/procedural/src/pallet/expand/documentation.rs +++ b/frame/support/procedural/src/pallet/expand/documentation.rs @@ -163,9 +163,9 @@ pub fn expand_documentation(def: &mut Def) -> proc_macro2::TokenStream { #[doc(hidden)] pub fn pallet_documentation_metadata() - -> #frame_support::sp_std::vec::Vec<&'static str> + -> #frame_support::__private::sp_std::vec::Vec<&'static str> { - #frame_support::sp_std::vec![ #( #docs ),* ] + #frame_support::__private::sp_std::vec![ #( #docs ),* ] } } ) diff --git a/frame/support/procedural/src/pallet/expand/error.rs b/frame/support/procedural/src/pallet/expand/error.rs index 376a6a9f51c6d..d3aa0b762bc52 100644 --- a/frame/support/procedural/src/pallet/expand/error.rs +++ b/frame/support/procedural/src/pallet/expand/error.rs @@ -44,7 +44,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { $caller:tt frame_support = [{ $($frame_support:ident)::* }] } => { - $($frame_support::)*tt_return! { + $($frame_support::)*__private::tt_return! { $caller } }; @@ -62,7 +62,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { #[doc(hidden)] #[codec(skip)] __Ignore( - #frame_support::sp_std::marker::PhantomData<(#type_use_gen)>, + #frame_support::__private::sp_std::marker::PhantomData<(#type_use_gen)>, #frame_support::Never, ) ); @@ -98,9 +98,9 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { // derive TypeInfo for error metadata error_item.attrs.push(syn::parse_quote! { #[derive( - #frame_support::codec::Encode, - #frame_support::codec::Decode, - #frame_support::scale_info::TypeInfo, + #frame_support::__private::codec::Encode, + #frame_support::__private::codec::Decode, + #frame_support::__private::scale_info::TypeInfo, #frame_support::PalletError, )] }); @@ -115,11 +115,11 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { } quote::quote_spanned!(error.attr_span => - impl<#type_impl_gen> #frame_support::sp_std::fmt::Debug for #error_ident<#type_use_gen> + impl<#type_impl_gen> #frame_support::__private::sp_std::fmt::Debug for #error_ident<#type_use_gen> #config_where_clause { - fn fmt(&self, f: &mut #frame_support::sp_std::fmt::Formatter<'_>) - -> #frame_support::sp_std::fmt::Result + fn fmt(&self, f: &mut #frame_support::__private::sp_std::fmt::Formatter<'_>) + -> #frame_support::__private::sp_std::fmt::Result { f.write_str(self.as_str()) } @@ -148,7 +148,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { #config_where_clause { fn from(err: #error_ident<#type_use_gen>) -> Self { - use #frame_support::codec::Encode; + use #frame_support::__private::codec::Encode; let index = < ::PalletInfo as #frame_support::traits::PalletInfo @@ -172,7 +172,7 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream { $caller:tt frame_support = [{ $($frame_support:ident)::* }] } => { - $($frame_support::)*tt_return! { + $($frame_support::)*__private::tt_return! { $caller error = [{ #error_ident }] } diff --git a/frame/support/procedural/src/pallet/expand/event.rs b/frame/support/procedural/src/pallet/expand/event.rs index f94bdef332d9d..fbb699b4d41cc 100644 --- a/frame/support/procedural/src/pallet/expand/event.rs +++ b/frame/support/procedural/src/pallet/expand/event.rs @@ -87,7 +87,7 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream { #[doc(hidden)] #[codec(skip)] __Ignore( - #frame_support::sp_std::marker::PhantomData<(#event_use_gen)>, + #frame_support::__private::sp_std::marker::PhantomData<(#event_use_gen)>, #frame_support::Never, ) ); @@ -109,9 +109,9 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::EqNoBound, #frame_support::PartialEqNoBound, #frame_support::RuntimeDebugNoBound, - #frame_support::codec::Encode, - #frame_support::codec::Decode, - #frame_support::scale_info::TypeInfo, + #frame_support::__private::codec::Encode, + #frame_support::__private::codec::Decode, + #frame_support::__private::scale_info::TypeInfo, )] )); diff --git a/frame/support/procedural/src/pallet/expand/genesis_build.rs b/frame/support/procedural/src/pallet/expand/genesis_build.rs index f54d308fce304..15ddfcf1d49d4 100644 --- a/frame/support/procedural/src/pallet/expand/genesis_build.rs +++ b/frame/support/procedural/src/pallet/expand/genesis_build.rs @@ -39,7 +39,7 @@ pub fn expand_genesis_build(def: &mut Def) -> proc_macro2::TokenStream { impl<#type_impl_gen> #frame_support::sp_runtime::BuildStorage for #gen_cfg_ident<#gen_cfg_use_gen> #where_clause { fn assimilate_storage(&self, storage: &mut sp_runtime::Storage) -> std::result::Result<(), std::string::String> { - #frame_support::BasicExternalities::execute_with_storage(storage, || { + #frame_support::__private::BasicExternalities::execute_with_storage(storage, || { self.build(); Ok(()) }) diff --git a/frame/support/procedural/src/pallet/expand/genesis_config.rs b/frame/support/procedural/src/pallet/expand/genesis_config.rs index cbe47bd8505f6..b00f9bcd1a662 100644 --- a/frame/support/procedural/src/pallet/expand/genesis_config.rs +++ b/frame/support/procedural/src/pallet/expand/genesis_config.rs @@ -79,7 +79,7 @@ pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream { let genesis_config_item = &mut def.item.content.as_mut().expect("Checked by def parser").1[genesis_config.index]; - let serde_crate = format!("{}::serde", frame_support); + let serde_crate = format!("{}::__private::serde", frame_support); match genesis_config_item { syn::Item::Enum(syn::ItemEnum { attrs, .. }) | diff --git a/frame/support/procedural/src/pallet/expand/hooks.rs b/frame/support/procedural/src/pallet/expand/hooks.rs index d2d2b2967fafb..2825756f270f0 100644 --- a/frame/support/procedural/src/pallet/expand/hooks.rs +++ b/frame/support/procedural/src/pallet/expand/hooks.rs @@ -38,7 +38,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { let log_runtime_upgrade = if has_runtime_upgrade { // a migration is defined here. quote::quote! { - #frame_support::log::info!( + #frame_support::__private::log::info!( target: #frame_support::LOG_TARGET, "⚠️ {} declares internal migrations (which *might* execute). \ On-chain `{:?}` vs current storage version `{:?}`", @@ -50,7 +50,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { } else { // default. quote::quote! { - #frame_support::log::debug!( + #frame_support::__private::log::debug!( target: #frame_support::LOG_TARGET, "✅ no migration for {}", pallet_name, @@ -64,7 +64,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { as #frame_support::traits::PalletInfo >::name::().expect("No name found for the pallet! This usually means that the pallet wasn't added to `construct_runtime!`."); - #frame_support::log::debug!( + #frame_support::__private::log::debug!( target: #frame_support::LOG_TARGET, "🩺 try-state pallet {:?}", pallet_name, @@ -97,7 +97,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::traits::PalletInfo >::name::().unwrap_or(""); - #frame_support::log::error!( + #frame_support::__private::log::error!( target: #frame_support::LOG_TARGET, "{}: On chain storage version {:?} doesn't match current storage version {:?}.", pallet_name, @@ -119,7 +119,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::traits::PalletInfo >::name::().unwrap_or(""); - #frame_support::log::error!( + #frame_support::__private::log::error!( target: #frame_support::LOG_TARGET, "{}: On chain storage version {:?} is set to non zero, \ while the pallet is missing the `#[pallet::storage_version(VERSION)]` attribute.", @@ -141,8 +141,8 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { for #pallet_ident<#type_use_gen> #where_clause { fn on_finalize(n: #frame_system::pallet_prelude::BlockNumberFor::) { - #frame_support::sp_tracing::enter_span!( - #frame_support::sp_tracing::trace_span!("on_finalize") + #frame_support::__private::sp_tracing::enter_span!( + #frame_support::__private::sp_tracing::trace_span!("on_finalize") ); < Self as #frame_support::traits::Hooks< @@ -175,8 +175,8 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { fn on_initialize( n: #frame_system::pallet_prelude::BlockNumberFor:: ) -> #frame_support::weights::Weight { - #frame_support::sp_tracing::enter_span!( - #frame_support::sp_tracing::trace_span!("on_initialize") + #frame_support::__private::sp_tracing::enter_span!( + #frame_support::__private::sp_tracing::trace_span!("on_initialize") ); < Self as #frame_support::traits::Hooks< @@ -191,8 +191,8 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { for #pallet_ident<#type_use_gen> #where_clause { fn on_runtime_upgrade() -> #frame_support::weights::Weight { - #frame_support::sp_tracing::enter_span!( - #frame_support::sp_tracing::trace_span!("on_runtime_update") + #frame_support::__private::sp_tracing::enter_span!( + #frame_support::__private::sp_tracing::trace_span!("on_runtime_update") ); // log info about the upgrade. @@ -211,7 +211,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { } #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result<#frame_support::sp_std::vec::Vec, #frame_support::sp_runtime::TryRuntimeError> { + fn pre_upgrade() -> Result<#frame_support::__private::sp_std::vec::Vec, #frame_support::sp_runtime::TryRuntimeError> { < Self as @@ -220,7 +220,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { } #[cfg(feature = "try-runtime")] - fn post_upgrade(state: #frame_support::sp_std::vec::Vec) -> Result<(), #frame_support::sp_runtime::TryRuntimeError> { + fn post_upgrade(state: #frame_support::__private::sp_std::vec::Vec) -> Result<(), #frame_support::sp_runtime::TryRuntimeError> { #post_storage_version_check < @@ -251,7 +251,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { for #pallet_ident<#type_use_gen> #where_clause { fn integrity_test() { - #frame_support::sp_io::TestExternalities::default().execute_with(|| { + #frame_support::__private::sp_io::TestExternalities::default().execute_with(|| { < Self as #frame_support::traits::Hooks< #frame_system::pallet_prelude::BlockNumberFor:: diff --git a/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/frame/support/procedural/src/pallet/expand/pallet_struct.rs index 800e23388c1af..e519e34d1dfd9 100644 --- a/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -54,7 +54,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { if let Some(field) = pallet_item.fields.iter_mut().next() { if field.ty == syn::parse_quote!(_) { field.ty = syn::parse_quote!( - #frame_support::sp_std::marker::PhantomData<(#type_use_gen)> + #frame_support::__private::sp_std::marker::PhantomData<(#type_use_gen)> ); } } @@ -82,9 +82,9 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { quote::quote_spanned!(def.pallet_struct.attr_span => impl<#type_impl_gen> #pallet_ident<#type_use_gen> #config_where_clause { #[doc(hidden)] - pub fn error_metadata() -> Option<#frame_support::metadata_ir::PalletErrorMetadataIR> { - Some(#frame_support::metadata_ir::PalletErrorMetadataIR { - ty: #frame_support::scale_info::meta_type::<#error_ident<#type_use_gen>>() + pub fn error_metadata() -> Option<#frame_support::__private::metadata_ir::PalletErrorMetadataIR> { + Some(#frame_support::__private::metadata_ir::PalletErrorMetadataIR { + ty: #frame_support::__private::scale_info::meta_type::<#error_ident<#type_use_gen>>() }) } } @@ -93,7 +93,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { quote::quote_spanned!(def.pallet_struct.attr_span => impl<#type_impl_gen> #pallet_ident<#type_use_gen> #config_where_clause { #[doc(hidden)] - pub fn error_metadata() -> Option<#frame_support::metadata_ir::PalletErrorMetadataIR> { + pub fn error_metadata() -> Option<#frame_support::__private::metadata_ir::PalletErrorMetadataIR> { None } } @@ -139,10 +139,10 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { #storages_where_clauses { fn storage_info() - -> #frame_support::sp_std::vec::Vec<#frame_support::traits::StorageInfo> + -> #frame_support::__private::sp_std::vec::Vec<#frame_support::traits::StorageInfo> { #[allow(unused_mut)] - let mut res = #frame_support::sp_std::vec![]; + let mut res = #frame_support::__private::sp_std::vec![]; #( #(#storage_cfg_attrs)* @@ -179,8 +179,8 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { let whitelisted_storage_keys_impl = quote::quote![ use #frame_support::traits::{StorageInfoTrait, TrackedStorageKey, WhitelistedStorageKeys}; impl<#type_impl_gen> WhitelistedStorageKeys for #pallet_ident<#type_use_gen> #storages_where_clauses { - fn whitelisted_storage_keys() -> #frame_support::sp_std::vec::Vec { - use #frame_support::sp_std::vec; + fn whitelisted_storage_keys() -> #frame_support::__private::sp_std::vec::Vec { + use #frame_support::__private::sp_std::vec; vec![#( TrackedStorageKey::new(#whitelisted_storage_idents::<#type_use_gen>::hashed_key().to_vec()) ),*] @@ -264,7 +264,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { #config_where_clause { fn count() -> usize { 1 } - fn infos() -> #frame_support::sp_std::vec::Vec<#frame_support::traits::PalletInfoData> { + fn infos() -> #frame_support::__private::sp_std::vec::Vec<#frame_support::traits::PalletInfoData> { use #frame_support::traits::PalletInfoAccess; let item = #frame_support::traits::PalletInfoData { index: Self::index(), @@ -272,7 +272,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { module_name: Self::module_name(), crate_version: Self::crate_version(), }; - #frame_support::sp_std::vec![item] + #frame_support::__private::sp_std::vec![item] } } diff --git a/frame/support/procedural/src/pallet/expand/storage.rs b/frame/support/procedural/src/pallet/expand/storage.rs index f3c394d731f5c..1a941f6cb3f5c 100644 --- a/frame/support/procedural/src/pallet/expand/storage.rs +++ b/frame/support/procedural/src/pallet/expand/storage.rs @@ -421,7 +421,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { #(#cfg_attrs)* { <#full_ident as #frame_support::storage::StorageEntryMetadataBuilder>::build_metadata( - #frame_support::sp_std::vec![ + #frame_support::__private::sp_std::vec![ #( #docs, )* ], &mut entries, @@ -492,7 +492,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause { #[doc = #getter_doc_line] pub fn #getter(k: KArg) -> #query where - KArg: #frame_support::codec::EncodeLike<#key>, + KArg: #frame_support::__private::codec::EncodeLike<#key>, { < #full_ident as #frame_support::storage::StorageMap<#key, #value> @@ -518,7 +518,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause { #[doc = #getter_doc_line] pub fn #getter(k: KArg) -> #query where - KArg: #frame_support::codec::EncodeLike<#key>, + KArg: #frame_support::__private::codec::EncodeLike<#key>, { // NOTE: we can't use any trait here because CountedStorageMap // doesn't implement any. @@ -544,8 +544,8 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause { #[doc = #getter_doc_line] pub fn #getter(k1: KArg1, k2: KArg2) -> #query where - KArg1: #frame_support::codec::EncodeLike<#key1>, - KArg2: #frame_support::codec::EncodeLike<#key2>, + KArg1: #frame_support::__private::codec::EncodeLike<#key1>, + KArg2: #frame_support::__private::codec::EncodeLike<#key2>, { < #full_ident as @@ -791,8 +791,8 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { #completed_where_clause { #[doc(hidden)] - pub fn storage_metadata() -> #frame_support::metadata_ir::PalletStorageMetadataIR { - #frame_support::metadata_ir::PalletStorageMetadataIR { + pub fn storage_metadata() -> #frame_support::__private::metadata_ir::PalletStorageMetadataIR { + #frame_support::__private::metadata_ir::PalletStorageMetadataIR { prefix: < ::PalletInfo as #frame_support::traits::PalletInfo @@ -800,7 +800,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { .expect("No name found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`."), entries: { #[allow(unused_mut)] - let mut entries = #frame_support::sp_std::vec![]; + let mut entries = #frame_support::__private::sp_std::vec![]; #( #entries_builder )* entries }, diff --git a/frame/support/procedural/src/pallet/expand/tt_default_parts.rs b/frame/support/procedural/src/pallet/expand/tt_default_parts.rs index 356bdbf67e923..86db56c776dfe 100644 --- a/frame/support/procedural/src/pallet/expand/tt_default_parts.rs +++ b/frame/support/procedural/src/pallet/expand/tt_default_parts.rs @@ -96,7 +96,7 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { $caller:tt frame_support = [{ $($frame_support:ident)::* }] } => { - $($frame_support)*::tt_return! { + $($frame_support)*::__private::tt_return! { $caller tokens = [{ expanded::{ @@ -126,7 +126,7 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { $caller:tt frame_support = [{ $($frame_support:ident)::* }] } => { - $($frame_support)*::tt_return! { + $($frame_support)*::__private::tt_return! { $caller tokens = [{ expanded::{ diff --git a/frame/support/procedural/src/pallet/parse/composite.rs b/frame/support/procedural/src/pallet/parse/composite.rs index 2bbfcd2e998ab..cb554a116175c 100644 --- a/frame/support/procedural/src/pallet/parse/composite.rs +++ b/frame/support/procedural/src/pallet/parse/composite.rs @@ -120,9 +120,9 @@ impl CompositeDef { let derive_attr: syn::Attribute = syn::parse_quote! { #[derive( Copy, Clone, Eq, PartialEq, Ord, PartialOrd, - #scrate::codec::Encode, #scrate::codec::Decode, #scrate::codec::MaxEncodedLen, - #scrate::scale_info::TypeInfo, - #scrate::RuntimeDebug, + #scrate::__private::codec::Encode, #scrate::__private::codec::Decode, #scrate::__private::codec::MaxEncodedLen, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, )] }; item.attrs.push(derive_attr); diff --git a/frame/support/procedural/src/pallet/parse/config.rs b/frame/support/procedural/src/pallet/parse/config.rs index c60bf1f3cbea7..e505f8b04119b 100644 --- a/frame/support/procedural/src/pallet/parse/config.rs +++ b/frame/support/procedural/src/pallet/parse/config.rs @@ -34,12 +34,16 @@ mod keyword { syn::custom_keyword!(frame_system); syn::custom_keyword!(disable_frame_system_supertrait_check); syn::custom_keyword!(no_default); + syn::custom_keyword!(no_default_bounds); syn::custom_keyword!(constant); } #[derive(Default)] pub struct DefaultTrait { - pub items: Vec, + /// A bool for each sub-trait item indicates whether the item has + /// `#[pallet::no_default_bounds]` attached to it. If true, the item will not have any bounds + /// in the generated default sub-trait. + pub items: Vec<(syn::TraitItem, bool)>, pub has_system: bool, } @@ -142,6 +146,8 @@ impl syn::parse::Parse for DisableFrameSystemSupertraitCheck { pub enum PalletAttrType { #[peek(keyword::no_default, name = "no_default")] NoDefault(keyword::no_default), + #[peek(keyword::no_default_bounds, name = "no_default_bounds")] + NoBounds(keyword::no_default_bounds), #[peek(keyword::constant, name = "constant")] Constant(keyword::constant), } @@ -366,6 +372,7 @@ impl ConfigDef { let mut already_no_default = false; let mut already_constant = false; + let mut already_no_default_bounds = false; while let Ok(Some(pallet_attr)) = helper::take_first_item_pallet_attr::(trait_item) @@ -403,15 +410,31 @@ impl ConfigDef { already_no_default = true; }, + (PalletAttrType::NoBounds(_), _) => { + if !enable_default { + return Err(syn::Error::new( + pallet_attr._bracket.span.join(), + "`#[pallet:no_default_bounds]` can only be used if `#[pallet::config(with_default)]` \ + has been specified" + )) + } + if already_no_default_bounds { + return Err(syn::Error::new( + pallet_attr._bracket.span.join(), + "Duplicate #[pallet::no_default_bounds] attribute not allowed.", + )) + } + already_no_default_bounds = true; + }, } } - if !already_no_default && !is_event && enable_default { + if !already_no_default && enable_default { default_sub_trait .as_mut() .expect("is 'Some(_)' if 'enable_default'; qed") .items - .push(trait_item.clone()); + .push((trait_item.clone(), already_no_default_bounds)); } } diff --git a/frame/support/procedural/src/pallet_error.rs b/frame/support/procedural/src/pallet_error.rs index 246a5bd4a219a..7fd02240a628a 100644 --- a/frame/support/procedural/src/pallet_error.rs +++ b/frame/support/procedural/src/pallet_error.rs @@ -124,7 +124,7 @@ fn generate_field_types( res = Some(None); } else if meta.path.is_ident("compact") { let field_ty = &field.ty; - res = Some(Some(quote::quote!(#scrate::codec::Compact<#field_ty>))); + res = Some(Some(quote::quote!(#scrate::__private::codec::Compact<#field_ty>))); } else if meta.path.is_ident("compact") { res = Some(Some(meta.value()?.parse()?)); } diff --git a/frame/support/procedural/src/storage_alias.rs b/frame/support/procedural/src/storage_alias.rs index d1d1aba47998e..a3f21806e18b9 100644 --- a/frame/support/procedural/src/storage_alias.rs +++ b/frame/support/procedural/src/storage_alias.rs @@ -622,7 +622,7 @@ fn generate_storage_instance( quote! { #visibility struct #counter_name< #impl_generics >( - #crate_::sp_std::marker::PhantomData<(#type_generics)> + #crate_::__private::sp_std::marker::PhantomData<(#type_generics)> ) #where_clause; impl<#impl_generics> #crate_::traits::StorageInstance @@ -647,7 +647,7 @@ fn generate_storage_instance( let code = quote! { #[allow(non_camel_case_types)] #visibility struct #name< #impl_generics >( - #crate_::sp_std::marker::PhantomData<(#type_generics)> + #crate_::__private::sp_std::marker::PhantomData<(#type_generics)> ) #where_clause; impl<#impl_generics> #crate_::traits::StorageInstance diff --git a/frame/support/procedural/src/tt_macro.rs b/frame/support/procedural/src/tt_macro.rs index 69b5eb3d5521a..01611f5dc4a4d 100644 --- a/frame/support/procedural/src/tt_macro.rs +++ b/frame/support/procedural/src/tt_macro.rs @@ -49,9 +49,9 @@ impl syn::parse::Parse for CreateTtReturnMacroDef { } /// A proc macro that accepts a name and any number of key-value pairs, to be used to create a -/// declarative macro that follows tt-call conventions and simply calls [`tt_call::tt_return`], -/// accepting an optional `frame-support` argument and returning the key-value pairs that were -/// supplied to the proc macro. +/// declarative macro that follows tt-call conventions and simply calls +/// [`tt_call::tt_return`], accepting an optional `frame-support` argument and returning +/// the key-value pairs that were supplied to the proc macro. /// /// # Example /// ```ignore @@ -67,7 +67,7 @@ impl syn::parse::Parse for CreateTtReturnMacroDef { /// $caller:tt /// $(frame_support = [{ $($frame_support:ident)::* }])? /// } => { -/// frame_support::tt_return! { +/// frame_support::__private::tt_return! { /// $caller /// foo = [{ bar }] /// } @@ -94,7 +94,7 @@ pub fn create_tt_return_macro(input: proc_macro::TokenStream) -> proc_macro::Tok $caller:tt $(frame_support = [{ $($frame_support:ident)::* }])? } => { - #frame_support::tt_return! { + #frame_support::__private::tt_return! { $caller #( #keys = [{ #values }] diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index e462066a84605..0388a9adb3948 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -18,31 +18,30 @@ //! Dispatch system. Contains a macro for defining runtime modules and //! generating values representing lazy module function calls. -pub use crate::{ - codec::{ - Codec, Decode, Encode, EncodeAsRef, EncodeLike, HasCompact, Input, MaxEncodedLen, Output, - }, - scale_info::TypeInfo, - sp_std::{ - fmt, marker, - prelude::{Clone, Eq, PartialEq, Vec}, - result, - }, - traits::{ - CallMetadata, GetCallIndex, GetCallMetadata, GetCallName, GetStorageVersion, - UnfilteredDispatchable, - }, +pub use crate::traits::{ + CallMetadata, GetCallIndex, GetCallMetadata, GetCallName, GetStorageVersion, + UnfilteredDispatchable, }; +pub use codec::{ + Codec, Decode, Encode, EncodeAsRef, EncodeLike, HasCompact, Input, MaxEncodedLen, Output, +}; +pub use scale_info::TypeInfo; +pub use sp_runtime::{ + traits::Dispatchable, transaction_validity::TransactionPriority, DispatchError, RuntimeDebug, +}; +pub use sp_std::{ + fmt, marker, + prelude::{Clone, Eq, PartialEq, Vec}, + result, +}; +pub use sp_weights::Weight; + #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_runtime::{ generic::{CheckedExtrinsic, UncheckedExtrinsic}, traits::SignedExtension, }; -pub use sp_runtime::{ - traits::Dispatchable, transaction_validity::TransactionPriority, DispatchError, RuntimeDebug, -}; -pub use sp_weights::Weight; /// The return type of a `Dispatchable` in frame. When returned explicitly from /// a dispatchable function it allows overriding the default `PostDispatchInfo` diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index 115ce605d542e..9c48f4b187ad3 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -17,9 +17,9 @@ //! Hash utilities. -use crate::metadata_ir; use codec::{Codec, MaxEncodedLen}; use sp_io::hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64}; +use sp_metadata_ir as metadata_ir; use sp_std::prelude::Vec; // This trait must be kept coherent with frame-support-procedural HasherKind usage diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 0c416c73766c8..a2a7e5ebc485f 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -32,38 +32,30 @@ /// Export ourself as `frame_support` to make tests happy. extern crate self as frame_support; +/// Private exports that are being used by macros. +/// +/// The exports are not stable and should not be relied on. #[doc(hidden)] -pub use sp_tracing; - -#[doc(hidden)] -pub use codec; -#[doc(hidden)] -pub use frame_metadata as metadata; -#[doc(hidden)] -pub use log; -#[doc(hidden)] -pub use paste; -#[doc(hidden)] -pub use scale_info; -pub use serde; -pub use sp_api::metadata_ir; -pub use sp_core::{OpaqueMetadata, Void}; -#[doc(hidden)] -pub use sp_core_hashing_proc_macro; -#[doc(hidden)] -pub use sp_io::{self, storage::root as storage_root}; -#[cfg(feature = "std")] -#[doc(hidden)] -pub use sp_runtime::{bounded_btree_map, bounded_vec}; -#[doc(hidden)] -pub use sp_runtime::{RuntimeDebug, StateVersion}; -#[cfg(feature = "std")] -#[doc(hidden)] -pub use sp_state_machine::BasicExternalities; -#[doc(hidden)] -pub use sp_std; -#[doc(hidden)] -pub use tt_call::*; +pub mod __private { + pub use codec; + pub use frame_metadata as metadata; + pub use log; + pub use paste; + pub use scale_info; + pub use serde; + pub use sp_core::{OpaqueMetadata, Void}; + pub use sp_core_hashing_proc_macro; + pub use sp_io::{self, storage::root as storage_root}; + pub use sp_metadata_ir as metadata_ir; + #[cfg(feature = "std")] + pub use sp_runtime::{bounded_btree_map, bounded_vec}; + pub use sp_runtime::{RuntimeDebug, StateVersion}; + #[cfg(feature = "std")] + pub use sp_state_machine::BasicExternalities; + pub use sp_std; + pub use sp_tracing; + pub use tt_call::*; +} #[macro_use] pub mod dispatch; @@ -255,7 +247,7 @@ macro_rules! parameter_types { ) => ( $( #[ $attr ] )* $vis struct $name $( - < $($ty_params),* >( $($crate::sp_std::marker::PhantomData<$ty_params>),* ) + < $($ty_params),* >( $($crate::__private::sp_std::marker::PhantomData<$ty_params>),* ) )?; $crate::parameter_types!(IMPL_CONST $name , $type , $value $( $(, $ty_params)* )?); $crate::parameter_types!( $( $rest )* ); @@ -267,7 +259,7 @@ macro_rules! parameter_types { ) => ( $( #[ $attr ] )* $vis struct $name $( - < $($ty_params),* >( $($crate::sp_std::marker::PhantomData<$ty_params>),* ) + < $($ty_params),* >( $($crate::__private::sp_std::marker::PhantomData<$ty_params>),* ) )?; $crate::parameter_types!(IMPL $name, $type, $value $( $(, $ty_params)* )?); $crate::parameter_types!( $( $rest )* ); @@ -279,7 +271,7 @@ macro_rules! parameter_types { ) => ( $( #[ $attr ] )* $vis struct $name $( - < $($ty_params),* >( $($crate::sp_std::marker::PhantomData<$ty_params>),* ) + < $($ty_params),* >( $($crate::__private::sp_std::marker::PhantomData<$ty_params>),* ) )?; $crate::parameter_types!(IMPL_STORAGE $name, $type, $value $( $(, $ty_params)* )?); $crate::parameter_types!( $( $rest )* ); @@ -332,7 +324,7 @@ macro_rules! parameter_types { impl< $($ty_params),* > $name< $($ty_params),* > { /// Returns the key for this parameter type. pub fn key() -> [u8; 16] { - $crate::sp_core_hashing_proc_macro::twox_128!(b":", $name, b":") + $crate::__private::sp_core_hashing_proc_macro::twox_128!(b":", $name, b":") } /// Set the value of this parameter type in the storage. @@ -397,7 +389,7 @@ macro_rules! parameter_types_impl_thread_local { $crate::parameter_types_impl_thread_local!( IMPL_THREAD_LOCAL $( $vis, $name, $type, $value, )* ); - $crate::paste::item! { + $crate::__private::paste::item! { $crate::parameter_types!( $( $( #[ $attr ] )* @@ -432,7 +424,7 @@ macro_rules! parameter_types_impl_thread_local { } }; (IMPL_THREAD_LOCAL $( $vis:vis, $name:ident, $type:ty, $value:expr, )* ) => { - $crate::paste::item! { + $crate::__private::paste::item! { thread_local! { $( pub static [<$name:snake:upper>]: std::cell::RefCell<$type> = @@ -462,7 +454,7 @@ macro_rules! ord_parameter_types { (IMPL $name:ident , $type:ty , $value:expr) => { impl $crate::traits::SortedMembers<$type> for $name { fn contains(t: &$type) -> bool { &$value == t } - fn sorted_members() -> $crate::sp_std::prelude::Vec<$type> { vec![$value] } + fn sorted_members() -> $crate::__private::sp_std::prelude::Vec<$type> { vec![$value] } fn count() -> usize { 1 } #[cfg(feature = "runtime-benchmarks")] fn add(_: &$type) {} @@ -485,9 +477,9 @@ macro_rules! runtime_print { ($($arg:tt)+) => { { use core::fmt::Write; - let mut w = $crate::sp_std::Writer::default(); + let mut w = $crate::__private::sp_std::Writer::default(); let _ = core::write!(&mut w, $($arg)+); - $crate::sp_io::misc::print_utf8(&w.inner()) + $crate::__private::sp_io::misc::print_utf8(&w.inner()) } } } @@ -684,9 +676,13 @@ macro_rules! assert_noop { $x:expr, $y:expr $(,)? ) => { - let h = $crate::storage_root($crate::StateVersion::V1); + let h = $crate::__private::storage_root($crate::__private::StateVersion::V1); $crate::assert_err!($x, $y); - assert_eq!(h, $crate::storage_root($crate::StateVersion::V1), "storage has been mutated"); + assert_eq!( + h, + $crate::__private::storage_root($crate::__private::StateVersion::V1), + "storage has been mutated" + ); }; } @@ -699,9 +695,9 @@ macro_rules! assert_storage_noop { ( $x:expr ) => { - let h = $crate::storage_root($crate::StateVersion::V1); + let h = $crate::__private::storage_root($crate::__private::StateVersion::V1); $x; - assert_eq!(h, $crate::storage_root($crate::StateVersion::V1)); + assert_eq!(h, $crate::__private::storage_root($crate::__private::StateVersion::V1)); }; } @@ -801,10 +797,10 @@ pub mod _private { pub mod testing_prelude { pub use super::{ assert_err, assert_err_ignore_postinfo, assert_err_with_weight, assert_error_encoded_size, - assert_noop, assert_ok, assert_storage_noop, bounded_btree_map, bounded_vec, - parameter_types, traits::Get, + assert_noop, assert_ok, assert_storage_noop, parameter_types, traits::Get, }; pub use sp_arithmetic::assert_eq_error_rate; + pub use sp_runtime::{bounded_btree_map, bounded_vec}; } /// Prelude to be used alongside pallet macro, for ease of use. @@ -830,10 +826,25 @@ pub mod pallet_prelude { IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, TypedGet, }, Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity, - PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, + PartialEqNoBound, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, }; pub use codec::{Decode, Encode, MaxEncodedLen}; pub use frame_support::pallet_macros::*; + /// The optional attribute `#[inject_runtime_type]` can be attached to `RuntimeCall`, + /// `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo` in an impl statement that has + /// `#[register_default_impl]` attached to indicate that this item is generated by + /// `construct_runtime`. + /// + /// Attaching this attribute to such an item ensures that the combined impl generated via + /// [`#[derive_impl(..)]`](`macro@super::derive_impl`) will use the correct type + /// auto-generated by `construct_runtime!`. + #[doc = docify::embed!("src/tests/inject_runtime_type.rs", derive_impl_works_with_runtime_type_injection)] + /// + /// However, if `no_aggregated_types` is specified while using + /// `[`#[derive_impl(..)]`](`macro@super::derive_impl`)`, then these items are attached + /// verbatim to the combined impl. + #[doc = docify::embed!("src/tests/inject_runtime_type.rs", derive_impl_works_with_no_aggregated_types)] + pub use frame_support_procedural::inject_runtime_type; pub use frame_support_procedural::register_default_impl; pub use scale_info::TypeInfo; pub use sp_inherents::MakeFatalError; @@ -844,7 +855,7 @@ pub mod pallet_prelude { TransactionTag, TransactionValidity, TransactionValidityError, UnknownTransaction, ValidTransaction, }, - MAX_MODULE_ERROR_ENCODED_SIZE, + RuntimeDebug, MAX_MODULE_ERROR_ENCODED_SIZE, }; pub use sp_std::marker::PhantomData; pub use sp_weights::Weight; @@ -2180,8 +2191,8 @@ pub mod pallet_macros { call_index, compact, composite_enum, config, constant, disable_frame_system_supertrait_check, error, event, extra_constants, generate_deposit, generate_store, genesis_build, genesis_config, getter, hooks, import_section, inherent, - no_default, origin, pallet_section, storage, storage_prefix, storage_version, type_value, - unbounded, validate_unsigned, weight, whitelist_storage, + no_default, no_default_bounds, origin, pallet_section, storage, storage_prefix, + storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage, }; } diff --git a/frame/support/src/storage/bounded_vec.rs b/frame/support/src/storage/bounded_vec.rs index 59b716b3ae5c6..06c58915a94d1 100644 --- a/frame/support/src/storage/bounded_vec.rs +++ b/frame/support/src/storage/bounded_vec.rs @@ -35,8 +35,9 @@ impl> StorageTryAppend for BoundedVec { #[cfg(test)] pub mod test { use super::*; - use crate::{bounded_vec, traits::ConstU32, Twox128}; + use crate::{traits::ConstU32, Twox128}; use sp_io::TestExternalities; + use sp_runtime::bounded_vec; #[crate::storage_alias] type Foo = StorageValue>>; diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index 76b9c554d65f9..e54002d18db3d 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -21,10 +21,10 @@ // NOTE: could replace unhashed by having only one kind of storage (top trie being the child info // of null length parent storage key). -pub use crate::sp_io::{KillStorageResult, MultiRemovalResults}; -use crate::sp_std::prelude::*; use codec::{Codec, Decode, Encode}; pub use sp_core::storage::{ChildInfo, ChildType, StateVersion}; +pub use sp_io::{KillStorageResult, MultiRemovalResults}; +use sp_std::prelude::*; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(child_info: &ChildInfo, key: &[u8]) -> Option { diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index 36e2c47383d19..d52908fa366c6 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -111,6 +111,15 @@ pub trait StorageValue { /// Mutate the value fn mutate R>(f: F) -> R; + /// Mutate the value under a key if the value already exists. Do nothing and return the default + /// value if not. + fn mutate_extant R>(f: F) -> R { + Self::mutate_exists(|maybe_v| match maybe_v { + Some(ref mut value) => f(value), + None => R::default(), + }) + } + /// Mutate the value if closure returns `Ok` fn try_mutate Result>(f: F) -> Result; diff --git a/frame/support/src/storage/storage_noop_guard.rs b/frame/support/src/storage/storage_noop_guard.rs index f2fb60027ec37..d00e6e18ecc48 100644 --- a/frame/support/src/storage/storage_noop_guard.rs +++ b/frame/support/src/storage/storage_noop_guard.rs @@ -41,7 +41,7 @@ pub struct StorageNoopGuard(sp_std::vec::Vec); impl Default for StorageNoopGuard { fn default() -> Self { - Self(frame_support::storage_root(frame_support::StateVersion::V1)) + Self(sp_io::storage::root(sp_runtime::StateVersion::V1)) } } @@ -52,7 +52,7 @@ impl Drop for StorageNoopGuard { return } assert_eq!( - frame_support::storage_root(frame_support::StateVersion::V1), + sp_io::storage::root(sp_runtime::StateVersion::V1), self.0, "StorageNoopGuard detected wrongful storage changes.", ); diff --git a/frame/support/src/storage/types/counted_map.rs b/frame/support/src/storage/types/counted_map.rs index 081f99fa16b0b..5b750a74098b8 100644 --- a/frame/support/src/storage/types/counted_map.rs +++ b/frame/support/src/storage/types/counted_map.rs @@ -18,7 +18,6 @@ //! Storage counted map type. use crate::{ - metadata_ir::StorageEntryMetadataIR, storage::{ generator::StorageMap as _, types::{ @@ -32,6 +31,7 @@ use crate::{ }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen, Ref}; use sp_io::MultiRemovalResults; +use sp_metadata_ir::StorageEntryMetadataIR; use sp_runtime::traits::Saturating; use sp_std::prelude::*; @@ -512,11 +512,11 @@ mod test { use super::*; use crate::{ hash::*, - metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}, storage::{bounded_vec::BoundedVec, types::ValueQuery}, traits::ConstU32, }; use sp_io::{hashing::twox_128, TestExternalities}; + use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}; struct Prefix; impl StorageInstance for Prefix { diff --git a/frame/support/src/storage/types/counted_nmap.rs b/frame/support/src/storage/types/counted_nmap.rs index 43a243cc5d681..7dbcb74f00053 100644 --- a/frame/support/src/storage/types/counted_nmap.rs +++ b/frame/support/src/storage/types/counted_nmap.rs @@ -29,7 +29,7 @@ use crate::{ Never, }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen, Ref}; -use sp_api::metadata_ir::StorageEntryMetadataIR; +use sp_metadata_ir::StorageEntryMetadataIR; use sp_runtime::traits::Saturating; use sp_std::prelude::*; @@ -638,8 +638,8 @@ mod test { hash::{StorageHasher as _, *}, storage::types::{Key as NMapKey, ValueQuery}, }; - use sp_api::metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}; use sp_io::{hashing::twox_128, TestExternalities}; + use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}; struct Prefix; impl StorageInstance for Prefix { diff --git a/frame/support/src/storage/types/double_map.rs b/frame/support/src/storage/types/double_map.rs index 08ac1709c4b68..e787921841032 100644 --- a/frame/support/src/storage/types/double_map.rs +++ b/frame/support/src/storage/types/double_map.rs @@ -19,7 +19,6 @@ //! StoragePrefixedDoubleMap traits and their methods directly. use crate::{ - metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}, storage::{ types::{OptionQuery, QueryKindTrait, StorageEntryMetadataBuilder}, KeyLenOf, StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend, @@ -29,6 +28,7 @@ use crate::{ }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen}; use sp_arithmetic::traits::SaturatedConversion; +use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}; use sp_std::prelude::*; /// A type that allow to store values for `(key1, key2)` couple. Similar to `StorageMap` but allow @@ -734,12 +734,9 @@ where #[cfg(test)] mod test { use super::*; - use crate::{ - hash::*, - metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}, - storage::types::ValueQuery, - }; + use crate::{hash::*, storage::types::ValueQuery}; use sp_io::{hashing::twox_128, TestExternalities}; + use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}; struct Prefix; impl StorageInstance for Prefix { diff --git a/frame/support/src/storage/types/key.rs b/frame/support/src/storage/types/key.rs index ec055aba803ec..90cf09dd1d341 100755 --- a/frame/support/src/storage/types/key.rs +++ b/frame/support/src/storage/types/key.rs @@ -41,7 +41,7 @@ pub trait KeyGenerator { type HashFn: FnOnce(&[u8]) -> Vec; type HArg; - const HASHER_METADATA: &'static [crate::metadata_ir::StorageHasherIR]; + const HASHER_METADATA: &'static [sp_metadata_ir::StorageHasherIR]; /// Given a `key` tuple, calculate the final key by encoding each element individually and /// hashing them using the corresponding hasher in the `KeyGenerator`. @@ -74,7 +74,7 @@ impl KeyGenerator for Key type HashFn = Box Vec>; type HArg = (Self::HashFn,); - const HASHER_METADATA: &'static [crate::metadata_ir::StorageHasherIR] = &[H::METADATA]; + const HASHER_METADATA: &'static [sp_metadata_ir::StorageHasherIR] = &[H::METADATA]; fn final_key + TupleToEncodedIter>(key: KArg) -> Vec { H::hash(&key.to_encoded_iter().next().expect("should have at least one element!")) @@ -114,7 +114,7 @@ impl KeyGenerator for Tuple { for_tuples!( type HArg = ( #(Tuple::HashFn),* ); ); type HashFn = Box Vec>; - const HASHER_METADATA: &'static [crate::metadata_ir::StorageHasherIR] = + const HASHER_METADATA: &'static [sp_metadata_ir::StorageHasherIR] = &[for_tuples!( #(Tuple::Hasher::METADATA),* )]; fn final_key + TupleToEncodedIter>(key: KArg) -> Vec { diff --git a/frame/support/src/storage/types/map.rs b/frame/support/src/storage/types/map.rs index c919dc6745d78..816b90162f644 100644 --- a/frame/support/src/storage/types/map.rs +++ b/frame/support/src/storage/types/map.rs @@ -19,7 +19,6 @@ //! methods directly. use crate::{ - metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}, storage::{ types::{OptionQuery, QueryKindTrait, StorageEntryMetadataBuilder}, KeyLenOf, StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend, @@ -29,6 +28,7 @@ use crate::{ }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen}; use sp_arithmetic::traits::SaturatedConversion; +use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}; use sp_std::prelude::*; /// A type that allow to store value for given key. Allowing to insert/remove/iterate on values. @@ -511,10 +511,10 @@ mod test { use super::*; use crate::{ hash::*, - metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}, storage::{types::ValueQuery, IterableStorageMap}, }; use sp_io::{hashing::twox_128, TestExternalities}; + use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR}; struct Prefix; impl StorageInstance for Prefix { diff --git a/frame/support/src/storage/types/mod.rs b/frame/support/src/storage/types/mod.rs index 99b0455fc6748..c7f2557099b36 100644 --- a/frame/support/src/storage/types/mod.rs +++ b/frame/support/src/storage/types/mod.rs @@ -18,8 +18,8 @@ //! Storage types to build abstraction on storage, they implements storage traits such as //! StorageMap and others. -use crate::metadata_ir::{StorageEntryMetadataIR, StorageEntryModifierIR}; use codec::FullCodec; +use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryModifierIR}; use sp_std::prelude::*; mod counted_map; diff --git a/frame/support/src/storage/types/nmap.rs b/frame/support/src/storage/types/nmap.rs index 0fac1fc933706..e9a4b12dd43a1 100755 --- a/frame/support/src/storage/types/nmap.rs +++ b/frame/support/src/storage/types/nmap.rs @@ -19,7 +19,6 @@ //! traits and their methods directly. use crate::{ - metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}, storage::{ types::{ EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OptionQuery, QueryKindTrait, @@ -30,6 +29,7 @@ use crate::{ traits::{Get, GetDefault, StorageInfo, StorageInstance}, }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen}; +use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}; use sp_runtime::SaturatedConversion; use sp_std::prelude::*; @@ -620,10 +620,10 @@ mod test { use super::*; use crate::{ hash::{StorageHasher as _, *}, - metadata_ir::{StorageEntryModifierIR, StorageHasherIR}, storage::types::{Key as NMapKey, ValueQuery}, }; use sp_io::{hashing::twox_128, TestExternalities}; + use sp_metadata_ir::{StorageEntryModifierIR, StorageHasherIR}; struct Prefix; impl StorageInstance for Prefix { diff --git a/frame/support/src/storage/types/value.rs b/frame/support/src/storage/types/value.rs index d5fbb0656bbd1..3c7f24715ac94 100644 --- a/frame/support/src/storage/types/value.rs +++ b/frame/support/src/storage/types/value.rs @@ -18,7 +18,6 @@ //! Storage value type. Implements StorageValue trait and its method directly. use crate::{ - metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}, storage::{ generator::StorageValue as StorageValueT, types::{OptionQuery, QueryKindTrait, StorageEntryMetadataBuilder}, @@ -28,6 +27,7 @@ use crate::{ }; use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen}; use sp_arithmetic::traits::SaturatedConversion; +use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR}; use sp_std::prelude::*; /// A type that allow to store a value. @@ -135,6 +135,11 @@ where >::mutate(f) } + /// Mutate the value under a key iff it exists. Do nothing and return the default value if not. + pub fn mutate_extant R>(f: F) -> R { + >::mutate_extant(f) + } + /// Mutate the value if closure returns `Ok` pub fn try_mutate Result>( f: F, @@ -278,8 +283,9 @@ where #[cfg(test)] mod test { use super::*; - use crate::{metadata_ir::StorageEntryModifierIR, storage::types::ValueQuery}; + use crate::storage::types::ValueQuery; use sp_io::{hashing::twox_128, TestExternalities}; + use sp_metadata_ir::StorageEntryModifierIR; struct Prefix; impl StorageInstance for Prefix { diff --git a/frame/support/src/tests/inject_runtime_type.rs b/frame/support/src/tests/inject_runtime_type.rs new file mode 100644 index 0000000000000..429a743d3b7b2 --- /dev/null +++ b/frame/support/src/tests/inject_runtime_type.rs @@ -0,0 +1,47 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::{Config, Runtime}; +use crate::{derive_impl, pallet_prelude::inject_runtime_type}; +use static_assertions::assert_type_eq_all; + +#[docify::export] +#[test] +fn derive_impl_works_with_runtime_type_injection() { + assert_type_eq_all!(::RuntimeOrigin, super::RuntimeOrigin); + assert_type_eq_all!(::RuntimeCall, super::RuntimeCall); + assert_type_eq_all!(::PalletInfo, super::PalletInfo); +} + +#[docify::export] +#[test] +fn derive_impl_works_with_no_aggregated_types() { + struct DummyRuntime; + + #[derive_impl( + super::frame_system::config_preludes::TestDefaultConfig as super::frame_system::DefaultConfig, + no_aggregated_types + )] + impl Config for DummyRuntime { + type Block = super::Block; + type AccountId = super::AccountId; + type PalletInfo = super::PalletInfo; + } + + assert_type_eq_all!(::RuntimeOrigin, ()); + assert_type_eq_all!(::RuntimeCall, ()); +} diff --git a/frame/support/src/tests/mod.rs b/frame/support/src/tests/mod.rs index cb4b4e82418b1..db458880db683 100644 --- a/frame/support/src/tests/mod.rs +++ b/frame/support/src/tests/mod.rs @@ -16,15 +16,16 @@ // limitations under the License. use super::*; -use crate::metadata_ir::{ +use sp_io::{MultiRemovalResults, TestExternalities}; +use sp_metadata_ir::{ PalletStorageMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR, }; -use sp_io::{MultiRemovalResults, TestExternalities}; use sp_runtime::{generic, traits::BlakeTwo256, BuildStorage}; pub use self::frame_system::{pallet_prelude::*, Config, Pallet}; +mod inject_runtime_type; mod storage_alias; #[pallet] @@ -34,17 +35,40 @@ pub mod frame_system { pub use crate::dispatch::RawOrigin; use crate::pallet_prelude::*; + pub mod config_preludes { + use super::{inject_runtime_type, DefaultConfig}; + pub struct TestDefaultConfig; + + #[crate::register_default_impl(TestDefaultConfig)] + impl DefaultConfig for TestDefaultConfig { + type AccountId = u64; + type BaseCallFilter = frame_support::traits::Everything; + #[inject_runtime_type] + type RuntimeOrigin = (); + #[inject_runtime_type] + type RuntimeCall = (); + #[inject_runtime_type] + type PalletInfo = (); + type DbWeight = (); + } + } + #[pallet::pallet] pub struct Pallet(_); - #[pallet::config] + #[pallet::config(with_default)] #[pallet::disable_frame_system_supertrait_check] pub trait Config: 'static { + #[pallet::no_default] type Block: Parameter + sp_runtime::traits::Block; type AccountId; + #[pallet::no_default_bounds] type BaseCallFilter: crate::traits::Contains; + #[pallet::no_default_bounds] type RuntimeOrigin; + #[pallet::no_default_bounds] type RuntimeCall; + #[pallet::no_default_bounds] type PalletInfo: crate::traits::PalletInfo; type DbWeight: Get; } @@ -168,14 +192,10 @@ crate::construct_runtime!( } ); +#[crate::derive_impl(self::frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl Config for Runtime { type Block = Block; type AccountId = AccountId; - type BaseCallFilter = crate::traits::Everything; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type PalletInfo = PalletInfo; - type DbWeight = (); } fn new_test_ext() -> TestExternalities { diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 27d16e133aa02..f669046f858f4 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -116,6 +116,12 @@ pub use messages::{ TransformOrigin, }; +mod safe_mode; +pub use safe_mode::{SafeMode, SafeModeError, SafeModeNotify}; + +mod tx_pause; +pub use tx_pause::{TransactionPause, TransactionPauseError}; + #[cfg(feature = "try-runtime")] mod try_runtime; #[cfg(feature = "try-runtime")] diff --git a/frame/support/src/traits/dispatch.rs b/frame/support/src/traits/dispatch.rs index 9ea58479a0dfe..d0cedb708cf1d 100644 --- a/frame/support/src/traits/dispatch.rs +++ b/frame/support/src/traits/dispatch.rs @@ -37,9 +37,35 @@ pub trait EnsureOrigin { Self::try_origin(o).map_err(|_| BadOrigin) } + /// The same as `ensure_origin` except that Root origin will always pass. This can only be + /// used if `Success` has a sensible impl of `Default` since that will be used in the result. + fn ensure_origin_or_root(o: OuterOrigin) -> Result, BadOrigin> + where + OuterOrigin: OriginTrait, + { + if o.caller().is_root() { + return Ok(None) + } else { + Self::ensure_origin(o).map(Some) + } + } + /// Perform the origin check. fn try_origin(o: OuterOrigin) -> Result; + /// The same as `try_origin` except that Root origin will always pass. This can only be + /// used if `Success` has a sensible impl of `Default` since that will be used in the result. + fn try_origin_or_root(o: OuterOrigin) -> Result, OuterOrigin> + where + OuterOrigin: OriginTrait, + { + if o.caller().is_root() { + return Ok(None) + } else { + Self::try_origin(o).map(Some) + } + } + /// Attempt to get an outer origin capable of passing `try_origin` check. May return `Err` if it /// is impossible. /// diff --git a/frame/support/src/traits/filter.rs b/frame/support/src/traits/filter.rs index 91efafef2f971..44f9f136cfc2a 100644 --- a/frame/support/src/traits/filter.rs +++ b/frame/support/src/traits/filter.rs @@ -103,7 +103,7 @@ macro_rules! impl_filter_stack { mod $module { #[allow(unused_imports)] use super::*; - use $crate::sp_std::{boxed::Box, cell::RefCell, mem::{swap, take}, vec::Vec}; + use $crate::__private::sp_std::{boxed::Box, cell::RefCell, mem::{swap, take}, vec::Vec}; use $crate::traits::filter::{Contains, FilterStack}; thread_local! { diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 85eb7b47e26da..eb704de4353c7 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -42,7 +42,7 @@ pub const DEFENSIVE_OP_INTERNAL_ERROR: &str = "Defensive failure has been trigge #[macro_export] macro_rules! defensive { () => { - frame_support::log::error!( + frame_support::__private::log::error!( target: "runtime", "{}", $crate::traits::DEFENSIVE_OP_PUBLIC_ERROR @@ -50,7 +50,7 @@ macro_rules! defensive { debug_assert!(false, "{}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR); }; ($error:expr $(,)?) => { - frame_support::log::error!( + frame_support::__private::log::error!( target: "runtime", "{}: {:?}", $crate::traits::DEFENSIVE_OP_PUBLIC_ERROR, @@ -59,7 +59,7 @@ macro_rules! defensive { debug_assert!(false, "{}: {:?}", $crate::traits::DEFENSIVE_OP_INTERNAL_ERROR, $error); }; ($error:expr, $proof:expr $(,)?) => { - frame_support::log::error!( + frame_support::__private::log::error!( target: "runtime", "{}: {:?}: {:?}", $crate::traits::DEFENSIVE_OP_PUBLIC_ERROR, diff --git a/frame/support/src/traits/preimages.rs b/frame/support/src/traits/preimages.rs index db8abdbdc79bb..3e78116202b4f 100644 --- a/frame/support/src/traits/preimages.rs +++ b/frame/support/src/traits/preimages.rs @@ -279,7 +279,8 @@ impl StorePreimage for () { #[cfg(test)] mod tests { use super::*; - use crate::{bounded_vec, BoundedVec}; + use crate::BoundedVec; + use sp_runtime::bounded_vec; #[test] fn bounded_size_is_correct() { diff --git a/frame/support/src/traits/safe_mode.rs b/frame/support/src/traits/safe_mode.rs new file mode 100644 index 0000000000000..332e28d6e52a9 --- /dev/null +++ b/frame/support/src/traits/safe_mode.rs @@ -0,0 +1,76 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Types to put the runtime into safe mode. + +/// Can put the runtime into a safe mode. +/// +/// When the runtime entered safe mode, transaction processing for most general transactions is +/// paused. +pub trait SafeMode { + /// Block number type. + type BlockNumber; + + /// Whether safe mode is entered. + fn is_entered() -> bool { + Self::remaining().is_some() + } + + /// How many more blocks safe mode will stay entered. + /// + /// If this returns `0`, then safe mode will exit in the next block. + fn remaining() -> Option; + + /// Enter safe mode for `duration` blocks. + /// + /// Should error when already entered with `AlreadyEntered`. + fn enter(duration: Self::BlockNumber) -> Result<(), SafeModeError>; + + /// Extend safe mode for `duration` blocks. + /// + /// Should error when not entered with `AlreadyExited`. + fn extend(duration: Self::BlockNumber) -> Result<(), SafeModeError>; + + /// Exit safe mode immediately. + /// + /// This takes effect already in the same block. + fn exit() -> Result<(), SafeModeError>; +} + +/// The error type for [`SafeMode`]. +pub enum SafeModeError { + /// Safe mode is already entered. + AlreadyEntered, + /// Safe mode is already exited. + AlreadyExited, + /// Unknown error. + Unknown, +} + +/// A trait to notify when the runtime enters or exits safe mode. +pub trait SafeModeNotify { + /// Called when the runtime enters safe mode. + fn entered(); + + /// Called when the runtime exits safe mode. + fn exited(); +} + +impl SafeModeNotify for () { + fn entered() {} + fn exited() {} +} diff --git a/frame/support/src/traits/storage.rs b/frame/support/src/traits/storage.rs index 829cd31e4c370..64eddf51b7fab 100644 --- a/frame/support/src/traits/storage.rs +++ b/frame/support/src/traits/storage.rs @@ -17,11 +17,10 @@ //! Traits for encoding data related to pallet's storage items. -use crate::sp_std::collections::btree_set::BTreeSet; use impl_trait_for_tuples::impl_for_tuples; pub use sp_core::storage::TrackedStorageKey; -use sp_runtime::traits::Saturating; -use sp_std::prelude::*; +use sp_runtime::{traits::Saturating, RuntimeDebug}; +use sp_std::{collections::btree_set::BTreeSet, prelude::*}; /// An instance of a pallet in the storage. /// @@ -61,7 +60,7 @@ pub trait StorageInstance { /// Metadata about storage from the runtime. #[derive( - codec::Encode, codec::Decode, crate::RuntimeDebug, Eq, PartialEq, Clone, scale_info::TypeInfo, + codec::Encode, codec::Decode, RuntimeDebug, Eq, PartialEq, Clone, scale_info::TypeInfo, )] pub struct StorageInfo { /// Encoded string of pallet name. diff --git a/frame/support/src/traits/tokens/fungible/hold.rs b/frame/support/src/traits/tokens/fungible/hold.rs index 3a0ff62e0965a..aa15e9df63a48 100644 --- a/frame/support/src/traits/tokens/fungible/hold.rs +++ b/frame/support/src/traits/tokens/fungible/hold.rs @@ -52,8 +52,10 @@ pub trait Inspect: super::Inspect { /// restrictions on the minimum amount of the account. Note: This cannot bring the account into /// an inconsistent state with regards any required existential deposit. /// - /// Always less than `total_balance_on_hold()`. - fn reducible_total_balance_on_hold(who: &AccountId, force: Fortitude) -> Self::Balance; + /// Never more than `total_balance_on_hold()`. + fn reducible_total_balance_on_hold(who: &AccountId, _force: Fortitude) -> Self::Balance { + Self::total_balance_on_hold(who) + } /// Amount of funds on hold (for the given reason) of `who`. fn balance_on_hold(reason: &Self::Reason, who: &AccountId) -> Self::Balance; @@ -65,7 +67,9 @@ pub trait Inspect: super::Inspect { /// NOTE: This does not take into account changes which could be made to the account of `who` /// (such as removing a provider reference) after this call is made. Any usage of this should /// therefore ensure the account is already in the appropriate state prior to calling it. - fn hold_available(reason: &Self::Reason, who: &AccountId) -> bool; + fn hold_available(_reason: &Self::Reason, _who: &AccountId) -> bool { + true + } /// Check to see if some `amount` of funds of `who` may be placed on hold with the given /// `reason`. Reasons why this may not be true: diff --git a/frame/support/src/traits/tokens/fungibles/hold.rs b/frame/support/src/traits/tokens/fungibles/hold.rs index 55f9d51c65564..c751a836d1f43 100644 --- a/frame/support/src/traits/tokens/fungibles/hold.rs +++ b/frame/support/src/traits/tokens/fungibles/hold.rs @@ -52,12 +52,14 @@ pub trait Inspect: super::Inspect { /// restrictions on the minimum amount of the account. Note: This cannot bring the account into /// an inconsistent state with regards any required existential deposit. /// - /// Always less than `total_balance_on_hold()`. + /// Never more than `total_balance_on_hold()`. fn reducible_total_balance_on_hold( asset: Self::AssetId, who: &AccountId, - force: Fortitude, - ) -> Self::Balance; + _force: Fortitude, + ) -> Self::Balance { + Self::total_balance_on_hold(asset, who) + } /// Amount of funds on hold (for the given reason) of `who`. fn balance_on_hold( @@ -73,7 +75,9 @@ pub trait Inspect: super::Inspect { /// NOTE: This does not take into account changes which could be made to the account of `who` /// (such as removing a provider reference) after this call is made. Any usage of this should /// therefore ensure the account is already in the appropriate state prior to calling it. - fn hold_available(asset: Self::AssetId, reason: &Self::Reason, who: &AccountId) -> bool; + fn hold_available(_asset: Self::AssetId, _reason: &Self::Reason, _who: &AccountId) -> bool { + true + } /// Check to see if some `amount` of funds of `who` may be placed on hold with the given /// `reason`. Reasons why this may not be true: diff --git a/frame/support/src/traits/try_runtime.rs b/frame/support/src/traits/try_runtime.rs index cb18f9d5b71c0..31aebeeb4d99b 100644 --- a/frame/support/src/traits/try_runtime.rs +++ b/frame/support/src/traits/try_runtime.rs @@ -175,7 +175,7 @@ impl TryState bool; + + /// Whether this call can be paused. + /// + /// This holds for the current block, but may change in the future. + fn can_pause(call: Self::CallIdentifier) -> bool; + + /// Pause this call immediately. + /// + /// This takes effect in the same block and must succeed if `can_pause` returns `true`. + fn pause(call: Self::CallIdentifier) -> Result<(), TransactionPauseError>; + + /// Unpause this call immediately. + /// + /// This takes effect in the same block and must succeed if `is_paused` returns `true`. This + /// invariant is important to not have un-resumable calls. + fn unpause(call: Self::CallIdentifier) -> Result<(), TransactionPauseError>; +} + +/// The error type for [`TransactionPause`]. +pub enum TransactionPauseError { + /// The call could not be found in the runtime. + /// + /// This is a permanent error but could change after a runtime upgrade. + NotFound, + /// Call cannot be paused. + /// + /// This may or may not resolve in a future block. + Unpausable, + /// Call is already paused. + AlreadyPaused, + /// Call is already unpaused. + AlreadyUnpaused, + /// Unknown error. + Unknown, +} diff --git a/frame/support/src/traits/validation.rs b/frame/support/src/traits/validation.rs index 84430901b9783..617cdb2d3f461 100644 --- a/frame/support/src/traits/validation.rs +++ b/frame/support/src/traits/validation.rs @@ -210,8 +210,8 @@ pub trait KeyOwnerProofSystem { impl KeyOwnerProofSystem for () { // The proof and identification tuples is any bottom type to guarantee that the methods of this // implementation can never be called or return anything other than `None`. - type Proof = crate::Void; - type IdentificationTuple = crate::Void; + type Proof = sp_core::Void; + type IdentificationTuple = sp_core::Void; fn prove(_key: Key) -> Option { None diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index af4d3afd4da98..ecb171244299a 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -16,6 +16,7 @@ static_assertions = "1.1.0" serde = { version = "1.0.163", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-metadata = { version = "16.0.0", default-features = false, features = ["current"] } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/api" } sp-arithmetic = { version = "16.0.0", default-features = false, path = "../../../primitives/arithmetic" } sp-io = { version = "23.0.0", path = "../../../primitives/io", default-features = false } @@ -26,6 +27,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../pr sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" } sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" } sp-version = { version = "22.0.0", default-features = false, path = "../../../primitives/version" } +sp-metadata-ir = { version = "0.1.0", default-features = false, path = "../../../primitives/metadata-ir" } trybuild = { version = "1.0.74", features = [ "diff" ] } pretty_assertions = "1.3.0" rustversion = "1.0.6" @@ -35,11 +37,12 @@ frame-executive = { version = "4.0.0-dev", default-features = false, path = "../ test-pallet = { package = "frame-support-test-pallet", default-features = false, path = "pallet" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking/std", "frame-executive/std", + "frame-metadata/std", "frame-support/std", "frame-system/std", "scale-info/std", @@ -48,18 +51,19 @@ std = [ "sp-arithmetic/std", "sp-core/std", "sp-io/std", + "sp-metadata-ir/std", "sp-runtime/std", + "sp-state-machine/std", "sp-std/std", "sp-version/std", "test-pallet/std", - "sp-state-machine/std" ] -experimental = ["frame-support/experimental"] +experimental = [ "frame-support/experimental" ] try-runtime = [ + "frame-executive/try-runtime", "frame-support/try-runtime", "frame-system/try-runtime", - "frame-executive/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] # WARNING: # Only CI runs with this feature enabled. This feature is for testing stuff related to the FRAME macros @@ -68,4 +72,4 @@ frame-feature-testing = [] frame-feature-testing-2 = [] # Disable ui tests disable-ui-tests = [] -no-metadata-docs = ["frame-support/no-metadata-docs"] +no-metadata-docs = [ "frame-support/no-metadata-docs" ] diff --git a/frame/support/test/compile_pass/Cargo.toml b/frame/support/test/compile_pass/Cargo.toml index 5d6caa002b372..151f7d8a5be0e 100644 --- a/frame/support/test/compile_pass/Cargo.toml +++ b/frame/support/test/compile_pass/Cargo.toml @@ -21,11 +21,11 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../.. sp-version = { version = "22.0.0", default-features = false, path = "../../../../primitives/version" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", - "renamed-frame-support/std", "frame-system/std", + "renamed-frame-support/std", "scale-info/std", "sp-core/std", "sp-runtime/std", diff --git a/frame/support/test/pallet/Cargo.toml b/frame/support/test/pallet/Cargo.toml index 6edfcd78968d1..073b751070152 100644 --- a/frame/support/test/pallet/Cargo.toml +++ b/frame/support/test/pallet/Cargo.toml @@ -20,12 +20,12 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../../ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../../primitives/runtime" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", "scale-info/std", "serde/std", - "sp-runtime/std" + "sp-runtime/std", ] diff --git a/frame/support/test/tests/construct_runtime.rs b/frame/support/test/tests/construct_runtime.rs index ff207ddf977c6..a14276fa4d2ff 100644 --- a/frame/support/test/tests/construct_runtime.rs +++ b/frame/support/test/tests/construct_runtime.rs @@ -636,7 +636,7 @@ fn call_subtype_conversion() { #[test] fn test_metadata() { - use frame_support::metadata::{v14::*, *}; + use frame_metadata::{v14::*, *}; use scale_info::meta_type; use sp_core::Encode; diff --git a/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index 946277e9068e3..0aee2cbceb9a1 100644 --- a/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -374,7 +374,7 @@ note: required by a bound in `Result` | | pub enum Result { | ^ required by this bound in `Result` - = note: this error originates in the derive macro `self::sp_api_hidden_includes_construct_runtime::hidden_include::codec::Decode` which comes from the expansion of the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `self::sp_api_hidden_includes_construct_runtime::hidden_include::__private::codec::Decode` which comes from the expansion of the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Runtime: Config` is not satisfied in `RuntimeEvent` --> tests/construct_runtime_ui/deprecated_where_block.rs:3:1 @@ -439,4 +439,4 @@ note: required by a bound in `Result` | | pub enum Result { | ^ required by this bound in `Result` - = note: this error originates in the derive macro `self::sp_api_hidden_includes_construct_runtime::hidden_include::codec::Decode` which comes from the expansion of the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `self::sp_api_hidden_includes_construct_runtime::hidden_include::__private::codec::Decode` which comes from the expansion of the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr b/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr index 55cef6704ee3f..75d0ce0546583 100644 --- a/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr +++ b/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr @@ -55,7 +55,9 @@ help: you might have meant to use the associated type | 38 | type PalletInfo = Self::PalletInfo; | ~~~~~~~~~~~~~~~~ -help: consider importing this trait +help: consider importing one of these items + | +1 + use frame_benchmarking::__private::traits::PalletInfo; | 1 + use frame_support::traits::PalletInfo; | diff --git a/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.rs b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.rs new file mode 100644 index 0000000000000..0d8dc8eb1d472 --- /dev/null +++ b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.rs @@ -0,0 +1,23 @@ +use frame_support::{*, pallet_prelude::inject_runtime_type}; +use static_assertions::assert_type_eq_all; + +pub trait Config { + type RuntimeCall; +} + +struct Pallet; + +#[register_default_impl(Pallet)] +impl Config for Pallet { + #[inject_runtime_type] + type RuntimeCall = (); +} + +struct SomePallet; + +#[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall; +impl Config for SomePallet {} + +assert_type_eq_all!(::RuntimeCall, u32); + +fn main() {} diff --git a/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr new file mode 100644 index 0000000000000..683131cceb8dc --- /dev/null +++ b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr @@ -0,0 +1,10 @@ +error[E0412]: cannot find type `RuntimeCall` in this scope + --> tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.rs:13:10 + | +13 | type RuntimeCall = (); + | ^^^^^^^^^^^ help: you might have meant to use the associated type: `Self::RuntimeCall` +... +18 | #[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall; + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `__export_tokens_tt_pallet` which comes from the expansion of the macro `frame_support::macro_magic::forward_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.rs b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.rs new file mode 100644 index 0000000000000..60ec710d0154c --- /dev/null +++ b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.rs @@ -0,0 +1,25 @@ +use frame_support::{*, pallet_prelude::inject_runtime_type}; +use static_assertions::assert_type_eq_all; + +pub trait Config { + type RuntimeInfo; +} + +type RuntimeInfo = u32; + +struct Pallet; + +#[register_default_impl(Pallet)] +impl Config for Pallet { + #[inject_runtime_type] + type RuntimeInfo = (); +} + +struct SomePallet; + +#[derive_impl(Pallet)] // Injects type RuntimeInfo = RuntimeInfo; +impl Config for SomePallet {} + +assert_type_eq_all!(::RuntimeInfo, u32); + +fn main() {} diff --git a/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr new file mode 100644 index 0000000000000..c3382510744a7 --- /dev/null +++ b/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr @@ -0,0 +1,14 @@ +error: `#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo` + --> tests/derive_impl_ui/inject_runtime_type_invalid.rs:15:5 + | +15 | type RuntimeInfo = (); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0046]: not all trait items implemented, missing: `RuntimeInfo` + --> tests/derive_impl_ui/inject_runtime_type_invalid.rs:13:1 + | +5 | type RuntimeInfo; + | ---------------- `RuntimeInfo` from trait +... +13 | impl Config for Pallet { + | ^^^^^^^^^^^^^^^^^^^^^^ missing `RuntimeInfo` in implementation diff --git a/frame/support/test/tests/derive_impl_ui/pass/runtime_type_working.rs b/frame/support/test/tests/derive_impl_ui/pass/runtime_type_working.rs new file mode 100644 index 0000000000000..04ad008944682 --- /dev/null +++ b/frame/support/test/tests/derive_impl_ui/pass/runtime_type_working.rs @@ -0,0 +1,25 @@ +use frame_support::{*, pallet_prelude::inject_runtime_type}; +use static_assertions::assert_type_eq_all; + +pub trait Config { + type RuntimeCall; +} + +type RuntimeCall = u32; + +struct Pallet; + +#[register_default_impl(Pallet)] +impl Config for Pallet { + #[inject_runtime_type] + type RuntimeCall = (); +} + +struct SomePallet; + +#[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall; +impl Config for SomePallet {} + +assert_type_eq_all!(::RuntimeCall, u32); + +fn main() {} diff --git a/frame/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs index 2fb6d7658d6ab..43a93df9dea49 100644 --- a/frame/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -20,14 +20,14 @@ use frame_support::{ derive_impl, inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent}, - metadata_ir::{ - PalletStorageMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR, - StorageEntryTypeIR, StorageHasherIR, - }, traits::ConstU32, }; use frame_system::pallet_prelude::BlockNumberFor; use sp_core::sr25519; +use sp_metadata_ir::{ + PalletStorageMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, + StorageHasherIR, +}; use sp_runtime::{ generic, traits::{BlakeTwo256, Verify}, diff --git a/frame/support/test/tests/pallet.rs b/frame/support/test/tests/pallet.rs index cb78bded1a358..8c85cd5695953 100644 --- a/frame/support/test/tests/pallet.rs +++ b/frame/support/test/tests/pallet.rs @@ -1378,7 +1378,7 @@ fn migrate_from_pallet_version_to_storage_version() { #[test] fn metadata() { use codec::Decode; - use frame_support::metadata::{v15::*, *}; + use frame_metadata::{v15::*, *}; fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { if cfg!(feature = "no-metadata-docs") { @@ -1860,7 +1860,7 @@ fn metadata() { #[test] fn metadata_at_version() { - use frame_support::metadata::*; + use frame_metadata::*; use sp_core::Decode; // Metadata always returns the V14.3 diff --git a/frame/support/test/tests/pallet_instance.rs b/frame/support/test/tests/pallet_instance.rs index 4ecb9bcb58ae9..be675a562cec5 100644 --- a/frame/support/test/tests/pallet_instance.rs +++ b/frame/support/test/tests/pallet_instance.rs @@ -721,7 +721,7 @@ fn pallet_on_genesis() { #[test] fn metadata() { - use frame_support::metadata::{v14::*, *}; + use frame_metadata::{v14::*, *}; let system_pallet_metadata = PalletMetadata { index: 0, diff --git a/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.rs b/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.rs index 7127ecf78594e..026b74c914a13 100644 --- a/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.rs +++ b/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.rs @@ -5,7 +5,7 @@ mod pallet { #[pallet::config(with_default)] pub trait Config: frame_system::Config { #[pallet::constant] - type MyGetParam2: Get; + type MyGetParam2: Get; } #[pallet::pallet] diff --git a/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.stderr b/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.stderr index bc657f8f654ec..17d8181135674 100644 --- a/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.stderr +++ b/frame/support/test/tests/pallet_ui/default_config_with_no_default_in_system.stderr @@ -1,5 +1,5 @@ -error[E0220]: associated type `RuntimeCall` not found for `Self` +error[E0220]: associated type `Block` not found for `Self` --> tests/pallet_ui/default_config_with_no_default_in_system.rs:8:31 | -8 | type MyGetParam2: Get; - | ^^^^^^^^^^^ associated type `RuntimeCall` not found +8 | type MyGetParam2: Get; + | ^^^^^ there is a similarly named associated type `Block` in the trait `frame_system::Config` diff --git a/frame/support/test/tests/pallet_ui/no_default_bounds_but_missing_with_default.rs b/frame/support/test/tests/pallet_ui/no_default_bounds_but_missing_with_default.rs new file mode 100644 index 0000000000000..123d791417498 --- /dev/null +++ b/frame/support/test/tests/pallet_ui/no_default_bounds_but_missing_with_default.rs @@ -0,0 +1,23 @@ +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + #[pallet::constant] + #[pallet::no_default_bounds] + type MyGetParam2: Get; + } + + #[pallet::pallet] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::call] + impl Pallet {} +} + +fn main() {} diff --git a/frame/support/test/tests/pallet_ui/no_default_bounds_but_missing_with_default.stderr b/frame/support/test/tests/pallet_ui/no_default_bounds_but_missing_with_default.stderr new file mode 100644 index 0000000000000..cbed14bca2cd4 --- /dev/null +++ b/frame/support/test/tests/pallet_ui/no_default_bounds_but_missing_with_default.stderr @@ -0,0 +1,5 @@ +error: `#[pallet:no_default_bounds]` can only be used if `#[pallet::config(with_default)]` has been specified + --> tests/pallet_ui/no_default_bounds_but_missing_with_default.rs:9:4 + | +9 | #[pallet::no_default_bounds] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index 50bad87d32eb0..a545735f2b1e8 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -15,13 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use frame_support::{ - metadata_ir::{ - RuntimeApiMetadataIR, RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, - }, - traits::ConstU32, -}; +use frame_support::traits::ConstU32; use scale_info::{form::MetaForm, meta_type}; +use sp_metadata_ir::{ + RuntimeApiMetadataIR, RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, +}; use sp_runtime::traits::Block as BlockT; pub type BlockNumber = u64; diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index d1a0124d9923f..6530862832c3f 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -32,7 +32,7 @@ sp-externalities = { version = "0.19.0", path = "../../primitives/externalities" substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -40,21 +40,18 @@ std = [ "scale-info/std", "serde/std", "sp-core/std", + "sp-externalities/std", "sp-io/std", "sp-runtime/std", "sp-std/std", "sp-version/std", "sp-weights/std", - "sp-externalities/std" ] runtime-benchmarks = [ "frame-support/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] -try-runtime = [ - "frame-support/try-runtime", - "sp-runtime/try-runtime" -] +try-runtime = [ "frame-support/try-runtime", "sp-runtime/try-runtime" ] [[bench]] name = "bench" diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 0d8165a3a44ca..098edbaa8bcd0 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -28,7 +28,7 @@ sp-externalities = { version = "0.19.0", path = "../../../primitives/externaliti sp-version = { version = "22.0.0", path = "../../../primitives/version" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking/std", @@ -36,16 +36,16 @@ std = [ "frame-system/std", "scale-info/std", "sp-core/std", - "sp-runtime/std", - "sp-std/std", "sp-externalities/std", "sp-io/std", - "sp-version/std" + "sp-runtime/std", + "sp-std/std", + "sp-version/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml index aef2cfc6e25f4..ec8348123cbb8 100644 --- a/frame/system/rpc/runtime-api/Cargo.toml +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -17,8 +17,5 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = sp-api = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/api" } [features] -default = ["std"] -std = [ - "codec/std", - "sp-api/std", -] +default = [ "std" ] +std = [ "codec/std", "sp-api/std" ] diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index c5a36c5059e95..84b6dc031457d 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -205,7 +205,7 @@ pub mod pallet { /// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`]. pub mod config_preludes { - use super::DefaultConfig; + use super::{inject_runtime_type, DefaultConfig}; /// Provides a viable default config that can be used with /// [`derive_impl`](`frame_support::derive_impl`) to derive a testing pallet config @@ -232,6 +232,17 @@ pub mod pallet { type BlockWeights = (); type BlockLength = (); type DbWeight = (); + #[inject_runtime_type] + type RuntimeEvent = (); + #[inject_runtime_type] + type RuntimeOrigin = (); + #[inject_runtime_type] + type RuntimeCall = (); + #[inject_runtime_type] + type PalletInfo = (); + type BaseCallFilter = frame_support::traits::Everything; + type BlockHashCount = frame_support::traits::ConstU64<10>; + type OnSetCode = (); } } @@ -240,6 +251,7 @@ pub mod pallet { #[pallet::disable_frame_system_supertrait_check] pub trait Config: 'static + Eq + Clone { /// The aggregated event type of the runtime. + #[pallet::no_default_bounds] type RuntimeEvent: Parameter + Member + From> @@ -248,7 +260,15 @@ pub mod pallet { /// The basic call filter to use in Origin. All origins are built with this filter as base, /// except Root. - #[pallet::no_default] + /// + /// This works as a filter for each incoming call. The call needs to pass this filter in + /// order to dispatch. Otherwise it will be rejected with `CallFiltered`. This can be + /// bypassed via `dispatch_bypass_filter` which should only be accessible by root. The + /// filter can be composed of sub-filters by nesting for example + /// [`frame_support::traits::InsideBoth`], [`frame_support::traits::TheseExcept`] or + /// [`frame_support::traits::EverythingBut`] et al. The default would be + /// [`frame_support::traits::Everything`]. + #[pallet::no_default_bounds] type BaseCallFilter: Contains; /// Block & extrinsics weights: base values and limits. @@ -260,14 +280,14 @@ pub mod pallet { type BlockLength: Get; /// The `RuntimeOrigin` type used by dispatchable calls. - #[pallet::no_default] + #[pallet::no_default_bounds] type RuntimeOrigin: Into, Self::RuntimeOrigin>> + From> + Clone + OriginTrait; /// The aggregated `RuntimeCall` type. - #[pallet::no_default] + #[pallet::no_default_bounds] type RuntimeCall: Parameter + Dispatchable + Debug @@ -327,7 +347,7 @@ pub mod pallet { /// Maximum number of block number to block hash mappings to keep (oldest pruned first). #[pallet::constant] - #[pallet::no_default] + #[pallet::no_default_bounds] type BlockHashCount: Get>; /// The weight of runtime database operations the runtime can invoke. @@ -342,7 +362,9 @@ pub mod pallet { /// /// Expects the `PalletInfo` type that is being generated by `construct_runtime!` in the /// runtime. - #[pallet::no_default] + /// + /// For tests it is okay to use `()` as type, however it will provide "useless" data. + #[pallet::no_default_bounds] type PalletInfo: PalletInfo; /// Data to be associated with an account (other than nonce/transaction counter, which this @@ -374,7 +396,7 @@ pub mod pallet { /// [`Pallet::update_code_in_storage`]). /// It's unlikely that this needs to be customized, unless you are writing a parachain using /// `Cumulus`, where the actual code change is deferred. - #[pallet::no_default] + #[pallet::no_default_bounds] type OnSetCode: SetCode; /// The maximum number of consumers allowed on a single account. diff --git a/frame/system/src/migrations/mod.rs b/frame/system/src/migrations/mod.rs index 6f873061dbab9..945bbc5395525 100644 --- a/frame/system/src/migrations/mod.rs +++ b/frame/system/src/migrations/mod.rs @@ -22,8 +22,8 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode, FullCodec}; use frame_support::{ pallet_prelude::ValueQuery, traits::PalletInfoAccess, weights::Weight, Blake2_128Concat, - RuntimeDebug, }; +use sp_runtime::RuntimeDebug; use sp_std::prelude::*; /// Type used to encode the number of references an account has. diff --git a/frame/system/src/offchain.rs b/frame/system/src/offchain.rs index 313a557c44d76..dd4ac6782a55e 100644 --- a/frame/system/src/offchain.rs +++ b/frame/system/src/offchain.rs @@ -57,10 +57,10 @@ #![warn(missing_docs)] use codec::Encode; -use frame_support::RuntimeDebug; use sp_runtime::{ app_crypto::RuntimeAppPublic, traits::{Extrinsic as ExtrinsicT, IdentifyAccount, One}, + RuntimeDebug, }; use sp_std::{collections::btree_set::BTreeSet, prelude::*}; diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index c92fb6b75b1b9..76896ae9411b4 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -24,6 +24,7 @@ sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../ sp-io = { version = "23.0.0", default-features = false, optional = true, path = "../../primitives/io" } sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } +sp-storage = { version = "13.0.0", default-features = false, path = "../../primitives/storage" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../primitives/timestamp" } [dev-dependencies] @@ -31,30 +32,31 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ - "sp-io?/std", "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", "scale-info/std", + "sp-core/std", "sp-inherents/std", + "sp-io?/std", "sp-runtime/std", "sp-std/std", + "sp-storage/std", "sp-timestamp/std", - "sp-core/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "sp-io", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-io", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/timestamp/src/benchmarking.rs b/frame/timestamp/src/benchmarking.rs index 8a7febed4d12f..82dfdfa8b3120 100644 --- a/frame/timestamp/src/benchmarking.rs +++ b/frame/timestamp/src/benchmarking.rs @@ -20,9 +20,10 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::v1::{benchmarks, TrackedStorageKey}; +use frame_benchmarking::v1::benchmarks; use frame_support::{ensure, traits::OnFinalize}; use frame_system::RawOrigin; +use sp_storage::TrackedStorageKey; use crate::Pallet as Timestamp; diff --git a/frame/tips/Cargo.toml b/frame/tips/Cargo.toml index aed4f6f96176d..61ecc681ec596 100644 --- a/frame/tips/Cargo.toml +++ b/frame/tips/Cargo.toml @@ -31,13 +31,14 @@ pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-storage = { version = "13.0.0", path = "../../primitives/storage" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "pallet-treasury/std", "scale-info/std", "serde", @@ -45,8 +46,7 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-storage/std" + "sp-storage/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -54,12 +54,12 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-treasury/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index 3f953d4eefe6e..8d4c0e55f798a 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -30,22 +30,22 @@ serde_json = "1.0.85" pallet-balances = { version = "4.0.0-dev", path = "../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "serde", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml b/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml index 69118cec04bcf..51ff136d8ae14 100644 --- a/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml @@ -31,21 +31,21 @@ pallet-assets = { version = "4.0.0-dev", path = "../../assets" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ - "scale-info/std", "codec/std", - "sp-std/std", - "sp-runtime/std", "frame-support/std", "frame-system/std", - "sp-io/std", - "sp-core/std", "pallet-asset-conversion/std", - "pallet-transaction-payment/std", "pallet-assets/std", "pallet-balances/std", - "sp-storage/std" + "pallet-transaction-payment/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "sp-storage/std", ] try-runtime = [ "frame-support/try-runtime", @@ -54,5 +54,5 @@ try-runtime = [ "pallet-assets/try-runtime", "pallet-balances/try-runtime", "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/transaction-payment/asset-tx-payment/Cargo.toml b/frame/transaction-payment/asset-tx-payment/Cargo.toml index 056880423f2a8..42dd65beddb5c 100644 --- a/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -39,31 +39,31 @@ pallet-authorship = { version = "4.0.0-dev", path = "../../authorship" } pallet-balances = { version = "4.0.0-dev", path = "../../balances" } [features] -default = ["std"] +default = [ "std" ] std = [ - "scale-info/std", - "serde", "codec/std", - "sp-std/std", - "sp-runtime/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "sp-io/std", - "sp-core/std", - "pallet-transaction-payment/std", - "frame-benchmarking?/std", "pallet-assets/std", "pallet-authorship/std", "pallet-balances/std", - "sp-storage/std" + "pallet-transaction-payment/std", + "scale-info/std", + "serde", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "sp-storage/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -72,5 +72,5 @@ try-runtime = [ "pallet-authorship/try-runtime", "pallet-balances/try-runtime", "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 5cb7ebd7a2b8b..27b8417b1f3b4 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -20,7 +20,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../../.. sp-weights = { version = "20.0.0", default-features = false, path = "../../../../primitives/weights" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "pallet-transaction-payment/std", diff --git a/frame/transaction-storage/Cargo.toml b/frame/transaction-storage/Cargo.toml index ae94e4a9bf013..6456e3002866c 100644 --- a/frame/transaction-storage/Cargo.toml +++ b/frame/transaction-storage/Cargo.toml @@ -33,34 +33,34 @@ sp-core = { version = "21.0.0", default-features = false, path = "../../primitiv sp-transaction-storage-proof = { version = "4.0.0-dev", default-features = true, path = "../../primitives/transaction-storage-proof" } [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ "array-bytes", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] std = [ - "log/std", - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "log/std", "pallet-balances/std", "scale-info/std", "serde", + "sp-core/std", "sp-inherents/std", "sp-io/std", "sp-runtime/std", "sp-std/std", "sp-transaction-storage-proof/std", - "sp-core/std" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index f692f204b9b3c..f49f3ccf756ce 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -33,20 +33,20 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } pallet-utility = { version = "4.0.0-dev", path = "../utility" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "pallet-balances/std", + "pallet-utility/std", "scale-info/std", "serde", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-utility/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -54,12 +54,12 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-utility/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-utility/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/try-runtime/Cargo.toml b/frame/try-runtime/Cargo.toml index f9b99ba598994..afd97632b3242 100644 --- a/frame/try-runtime/Cargo.toml +++ b/frame/try-runtime/Cargo.toml @@ -27,7 +27,4 @@ std = [ "sp-runtime/std", "sp-std/std", ] -try-runtime = [ - "frame-support/try-runtime", - "sp-runtime/try-runtime" -] +try-runtime = [ "frame-support/try-runtime", "sp-runtime/try-runtime" ] diff --git a/frame/tx-pause/Cargo.toml b/frame/tx-pause/Cargo.toml new file mode 100644 index 0000000000000..24ac55909ca91 --- /dev/null +++ b/frame/tx-pause/Cargo.toml @@ -0,0 +1,66 @@ +[package] +name = "pallet-tx-pause" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME transaction pause pallet" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "8.0.0", default-features = false, path = "../../primitives/std" } +pallet-balances = { version = "4.0.0-dev", path = "../balances", default-features = false, optional = true } +pallet-utility = { version = "4.0.0-dev", path = "../utility", default-features = false, optional = true } +pallet-proxy = { version = "4.0.0-dev", path = "../proxy", default-features = false, optional = true } + +[dev-dependencies] +sp-core = { version = "21.0.0", path = "../../primitives/core" } +sp-io = { version = "23.0.0", path = "../../primitives/io" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-utility = { version = "4.0.0-dev", path = "../utility" } +pallet-proxy = { version = "4.0.0-dev", path = "../proxy" } + +[features] +default = [ "std" ] +std = [ + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "pallet-balances?/std", + "pallet-proxy?/std", + "pallet-utility?/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances?/try-runtime", + "pallet-proxy?/try-runtime", + "pallet-utility?/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/frame/tx-pause/src/benchmarking.rs b/frame/tx-pause/src/benchmarking.rs new file mode 100644 index 0000000000000..81595ef9f7280 --- /dev/null +++ b/frame/tx-pause/src/benchmarking.rs @@ -0,0 +1,59 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(feature = "runtime-benchmarks")] + +use super::{Pallet as TxPause, *}; +use frame_benchmarking::v2::*; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn pause() { + let origin = T::PauseOrigin::try_successful_origin() + .expect("Tx-pause pallet is not usable without pause origin"); + let full_name = name::(); + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, full_name.clone()); + + assert!(PausedCalls::::get(full_name).is_some()); + } + + #[benchmark] + fn unpause() { + let unpause_origin = T::UnpauseOrigin::try_successful_origin() + .expect("Tx-pause pallet is not usable without pause origin"); + let full_name = name::(); + TxPause::::do_pause(full_name.clone()).unwrap(); + + #[extrinsic_call] + _(unpause_origin as T::RuntimeOrigin, full_name.clone()); + + assert!(PausedCalls::::get(full_name).is_none()); + } + + impl_benchmark_test_suite!(TxPause, crate::mock::new_test_ext(), crate::mock::Test); +} + +/// Longest possible name. +fn name() -> RuntimeCallNameOf { + let max_len = T::MaxNameLen::get() as usize; + (vec![1; max_len].try_into().unwrap(), vec![1; max_len].try_into().unwrap()) +} diff --git a/frame/tx-pause/src/lib.rs b/frame/tx-pause/src/lib.rs new file mode 100644 index 0000000000000..36147d32a2f0e --- /dev/null +++ b/frame/tx-pause/src/lib.rs @@ -0,0 +1,277 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(rustdoc::broken_intra_doc_links)] + +mod benchmarking; +pub mod mock; +mod tests; +pub mod weights; + +use frame_support::{ + dispatch::GetDispatchInfo, + pallet_prelude::*, + traits::{CallMetadata, Contains, GetCallMetadata, IsSubType, IsType}, + DefaultNoBound, +}; +use frame_system::pallet_prelude::*; +use sp_runtime::{traits::Dispatchable, DispatchResult}; +use sp_std::{convert::TryInto, prelude::*}; + +pub use pallet::*; +pub use weights::*; + +/// The stringy name of a pallet from [`GetCallMetadata`] for [`Config::RuntimeCall`] variants. +pub type PalletNameOf = BoundedVec::MaxNameLen>; + +/// The stringy name of a call (within a pallet) from [`GetCallMetadata`] for +/// [`Config::RuntimeCall`] variants. +pub type PalletCallNameOf = BoundedVec::MaxNameLen>; + +/// A fully specified pallet ([`PalletNameOf`]) and optional call ([`PalletCallNameOf`]) +/// to partially or fully specify an item a variant of a [`Config::RuntimeCall`]. +pub type RuntimeCallNameOf = (PalletNameOf, PalletCallNameOf); + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// The overarching call type. + type RuntimeCall: Parameter + + Dispatchable + + GetDispatchInfo + + GetCallMetadata + + From> + + IsSubType> + + IsType<::RuntimeCall>; + + /// The only origin that can pause calls. + type PauseOrigin: EnsureOrigin; + + /// The only origin that can un-pause calls. + type UnpauseOrigin: EnsureOrigin; + + /// Contains all calls that cannot be paused. + /// + /// The `TxMode` pallet cannot pause its own calls, and does not need to be explicitly + /// added here. + type WhitelistedCalls: Contains>; + + /// Maximum length for pallet name and call name SCALE encoded string names. + /// + /// TOO LONG NAMES WILL BE TREATED AS PAUSED. + #[pallet::constant] + type MaxNameLen: Get; + + // Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + /// The set of calls that are explicitly paused. + #[pallet::storage] + pub type PausedCalls = + StorageMap<_, Blake2_128Concat, RuntimeCallNameOf, (), OptionQuery>; + + #[pallet::error] + pub enum Error { + /// The call is paused. + IsPaused, + + /// The call is unpaused. + IsUnpaused, + + /// The call is whitelisted and cannot be paused. + Unpausable, + + // The pallet or call does not exist in the runtime. + NotFound, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// This pallet, or a specific call is now paused. + CallPaused { full_name: RuntimeCallNameOf }, + /// This pallet, or a specific call is now unpaused. + CallUnpaused { full_name: RuntimeCallNameOf }, + } + + /// Configure the initial state of this pallet in the genesis block. + #[pallet::genesis_config] + #[derive(DefaultNoBound)] + pub struct GenesisConfig { + /// Initially paused calls. + pub paused: Vec>, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + for call in &self.paused { + Pallet::::ensure_can_pause(&call).expect("Genesis data is known good; qed"); + PausedCalls::::insert(&call, ()); + } + } + } + + #[pallet::call] + impl Pallet { + /// Pause a call. + /// + /// Can only be called by [`Config::PauseOrigin`]. + /// Emits an [`Event::CallPaused`] event on success. + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::pause())] + pub fn pause(origin: OriginFor, full_name: RuntimeCallNameOf) -> DispatchResult { + T::PauseOrigin::ensure_origin(origin)?; + + Self::do_pause(full_name).map_err(Into::into) + } + + /// Un-pause a call. + /// + /// Can only be called by [`Config::UnpauseOrigin`]. + /// Emits an [`Event::CallUnpaused`] event on success. + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::unpause())] + pub fn unpause(origin: OriginFor, ident: RuntimeCallNameOf) -> DispatchResult { + T::UnpauseOrigin::ensure_origin(origin)?; + + Self::do_unpause(ident).map_err(Into::into) + } + } +} + +impl Pallet { + pub(crate) fn do_pause(ident: RuntimeCallNameOf) -> Result<(), Error> { + Self::ensure_can_pause(&ident)?; + PausedCalls::::insert(&ident, ()); + Self::deposit_event(Event::CallPaused { full_name: ident }); + + Ok(()) + } + + pub(crate) fn do_unpause(ident: RuntimeCallNameOf) -> Result<(), Error> { + Self::ensure_can_unpause(&ident)?; + PausedCalls::::remove(&ident); + Self::deposit_event(Event::CallUnpaused { full_name: ident }); + + Ok(()) + } + + /// Return whether this call is paused. + pub fn is_paused(full_name: &RuntimeCallNameOf) -> bool { + if T::WhitelistedCalls::contains(full_name) { + return false + } + + >::contains_key(full_name) + } + + /// Same as [`Self::is_paused`] but for inputs unbound by max-encoded-len. + pub fn is_paused_unbound(pallet: Vec, call: Vec) -> bool { + let pallet = PalletNameOf::::try_from(pallet); + let call = PalletCallNameOf::::try_from(call); + + match (pallet, call) { + (Ok(pallet), Ok(call)) => Self::is_paused(&(pallet, call)), + _ => true, + } + } + + /// Ensure that this call can be paused. + pub fn ensure_can_pause(full_name: &RuntimeCallNameOf) -> Result<(), Error> { + // SAFETY: The `TxPause` pallet can never pause itself. + if full_name.0.as_ref() == ::name().as_bytes().to_vec() { + return Err(Error::::Unpausable) + } + + if T::WhitelistedCalls::contains(&full_name) { + return Err(Error::::Unpausable) + } + if Self::is_paused(&full_name) { + return Err(Error::::IsPaused) + } + Ok(()) + } + + /// Ensure that this call can be un-paused. + pub fn ensure_can_unpause(full_name: &RuntimeCallNameOf) -> Result<(), Error> { + if Self::is_paused(&full_name) { + // SAFETY: Everything that is paused, can be un-paused. + Ok(()) + } else { + Err(Error::IsUnpaused) + } + } +} + +impl Contains<::RuntimeCall> for Pallet +where + ::RuntimeCall: GetCallMetadata, +{ + /// Return whether the call is allowed to be dispatched. + fn contains(call: &::RuntimeCall) -> bool { + let CallMetadata { pallet_name, function_name } = call.get_call_metadata(); + !Pallet::::is_paused_unbound(pallet_name.into(), function_name.into()) + } +} + +impl frame_support::traits::TransactionPause for Pallet { + type CallIdentifier = RuntimeCallNameOf; + + fn is_paused(full_name: Self::CallIdentifier) -> bool { + Self::is_paused(&full_name) + } + + fn can_pause(full_name: Self::CallIdentifier) -> bool { + Self::ensure_can_pause(&full_name).is_ok() + } + + fn pause( + full_name: Self::CallIdentifier, + ) -> Result<(), frame_support::traits::TransactionPauseError> { + Self::do_pause(full_name).map_err(Into::into) + } + + fn unpause( + full_name: Self::CallIdentifier, + ) -> Result<(), frame_support::traits::TransactionPauseError> { + Self::do_unpause(full_name).map_err(Into::into) + } +} + +impl From> for frame_support::traits::TransactionPauseError { + fn from(err: Error) -> Self { + match err { + Error::::NotFound => Self::NotFound, + Error::::Unpausable => Self::Unpausable, + Error::::IsPaused => Self::AlreadyPaused, + Error::::IsUnpaused => Self::AlreadyUnpaused, + _ => Self::Unknown, + } + } +} diff --git a/frame/tx-pause/src/mock.rs b/frame/tx-pause/src/mock.rs new file mode 100644 index 0000000000000..70c888f3c38da --- /dev/null +++ b/frame/tx-pause/src/mock.rs @@ -0,0 +1,226 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests and test utilities for transaction pause pallet. + +#![cfg(test)] + +use super::*; +use crate as pallet_tx_pause; + +use frame_support::{ + parameter_types, + traits::{ConstU64, Everything, InsideBoth, InstanceFilter}, +}; +use frame_system::EnsureSignedBy; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +parameter_types! { + pub const BlockHashCount: u64 = 250; +} +impl frame_system::Config for Test { + type BaseCallFilter = InsideBoth; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type Block = Block; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const MaxLocks: u32 = 10; +} +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type FreezeIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; +} + +impl pallet_utility::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + +/// Mocked proxies to check that tx-pause also works with the proxy pallet. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, +)] +pub enum ProxyType { + Any, + JustTransfer, + JustUtility, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::JustTransfer => { + matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) + }, + ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), + } + } + fn is_superset(&self, o: &Self) -> bool { + self == &ProxyType::Any || self == o + } +} + +impl pallet_proxy::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ConstU64<1>; + type ProxyDepositFactor = ConstU64<1>; + type MaxProxies = ConstU32<4>; + type WeightInfo = (); + type CallHasher = BlakeTwo256; + type MaxPending = ConstU32<2>; + type AnnouncementDepositBase = ConstU64<1>; + type AnnouncementDepositFactor = ConstU64<1>; +} + +parameter_types! { + pub const MaxNameLen: u32 = 50; +} + +frame_support::ord_parameter_types! { + pub const PauseOrigin: u64 = 1; + pub const UnpauseOrigin: u64 = 2; +} + +/// Calls that are never allowed to be paused. +pub struct WhitelistedCalls; +impl Contains> for WhitelistedCalls { + fn contains(full_name: &RuntimeCallNameOf) -> bool { + match (full_name.0.as_slice(), full_name.1.as_slice()) { + (b"Balances", b"transfer_keep_alive") => true, + _ => false, + } + } +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureSignedBy; + type UnpauseOrigin = EnsureSignedBy; + type WhitelistedCalls = WhitelistedCalls; + type MaxNameLen = MaxNameLen; + type WeightInfo = (); +} + +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + Balances: pallet_balances, + Utility: pallet_utility, + Proxy: pallet_proxy, + TxPause: pallet_tx_pause, + } +); + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { + // The 0 account is NOT a special origin. The rest may be: + balances: vec![(0, 1234), (1, 5678), (2, 5678), (3, 5678), (4, 5678)], + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_tx_pause::GenesisConfig:: { paused: vec![] } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} + +pub fn next_block() { + TxPause::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + TxPause::on_initialize(System::block_number()); +} + +pub fn run_to(n: u64) { + while System::block_number() < n { + next_block(); + } +} diff --git a/frame/tx-pause/src/tests.rs b/frame/tx-pause/src/tests.rs new file mode 100644 index 0000000000000..ca259315726b0 --- /dev/null +++ b/frame/tx-pause/src/tests.rs @@ -0,0 +1,222 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(test)] + +use super::*; +use crate::mock::{RuntimeCall, *}; + +use frame_support::{assert_err, assert_noop, assert_ok, dispatch::Dispatchable}; + +// GENERAL SUCCESS/POSITIVE TESTS --------------------- + +#[test] +fn can_pause_specific_call() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer") + )); + + assert_err!( + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), + frame_system::Error::::CallFiltered + ); + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); + }); +} + +#[test] +fn can_pause_all_calls_in_pallet_except_on_whitelist() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); + + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Utility", b"batch") + ),); + + assert_err!( + batch_call.clone().dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn can_unpause_specific_call() { + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + )); + assert_err!( + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), + frame_system::Error::::CallFiltered + ); + + assert_ok!(TxPause::unpause( + RuntimeOrigin::signed(mock::UnpauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + )); + assert_ok!(call_transfer(4, 1).dispatch(RuntimeOrigin::signed(0))); + }); +} + +#[test] +fn can_filter_balance_in_batch_when_paused() { + new_test_ext().execute_with(|| { + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + )); + + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + System::assert_last_event( + pallet_utility::Event::BatchInterrupted { + index: 0, + error: frame_system::Error::::CallFiltered.into(), + } + .into(), + ); + }); +} + +#[test] +fn can_filter_balance_in_proxy_when_paused() { + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + )); + + assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); + + assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer(1, 1)))); + System::assert_last_event( + pallet_proxy::Event::ProxyExecuted { + result: DispatchError::from(frame_system::Error::::CallFiltered).into(), + } + .into(), + ); + }); +} + +// GENERAL FAIL/NEGATIVE TESTS --------------------- + +#[test] +fn fails_to_pause_self() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"TxPause", b"pause"), + ), + Error::::Unpausable + ); + }); +} + +#[test] +fn fails_to_pause_unpausable_call_when_other_call_is_paused() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); + + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + )); + + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); + assert_err!( + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn fails_to_pause_unpausable_call() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer_keep_alive"), + ), + Error::::Unpausable + ); + }); +} + +#[test] +fn fails_to_pause_already_paused_pallet() { + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + )); + + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", b"transfer"), + ), + Error::::IsPaused + ); + }); +} + +#[test] +fn fails_to_unpause_not_paused_pallet() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::unpause( + RuntimeOrigin::signed(mock::UnpauseOrigin::get()), + full_name::(b"Balances", b"transfer_keep_alive"), + ), + Error::::IsUnpaused + ); + }); +} + +pub fn call_transfer(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(pallet_balances::Call::transfer { dest, value }) +} + +pub fn call_transfer_keep_alive(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { dest, value }) +} + +pub fn full_name(pallet_name: &[u8], call_name: &[u8]) -> RuntimeCallNameOf { + >::from(( + pallet_name.to_vec().try_into().unwrap(), + call_name.to_vec().try_into().unwrap(), + )) +} diff --git a/frame/tx-pause/src/weights.rs b/frame/tx-pause/src/weights.rs new file mode 100644 index 0000000000000..b733e64b159dc --- /dev/null +++ b/frame/tx-pause/src/weights.rs @@ -0,0 +1,107 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for `pallet_tx_pause` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-aahe6cbd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// target/production/substrate-node +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_tx_pause +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/tx-pause/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_tx_pause`. +pub trait WeightInfo { + fn pause() -> Weight; + fn unpause() -> Weight; +} + +/// Weights for `pallet_tx_pause` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `TxPause::PausedCalls` (r:1 w:1) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + fn pause() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3997` + // Minimum execution time: 15_096_000 picoseconds. + Weight::from_parts(15_437_000, 3997) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `TxPause::PausedCalls` (r:1 w:1) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + fn unpause() -> Weight { + // Proof Size summary in bytes: + // Measured: `565` + // Estimated: `3997` + // Minimum execution time: 21_546_000 picoseconds. + Weight::from_parts(22_178_000, 3997) + .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: `TxPause::PausedCalls` (r:1 w:1) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + fn pause() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3997` + // Minimum execution time: 15_096_000 picoseconds. + Weight::from_parts(15_437_000, 3997) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `TxPause::PausedCalls` (r:1 w:1) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + fn unpause() -> Weight { + // Proof Size summary in bytes: + // Measured: `565` + // Estimated: `3997` + // Minimum execution time: 21_546_000 picoseconds. + Weight::from_parts(22_178_000, 3997) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} diff --git a/frame/uniques/Cargo.toml b/frame/uniques/Cargo.toml index 9ddcef1e7b10b..28ebc1ff50fe5 100644 --- a/frame/uniques/Cargo.toml +++ b/frame/uniques/Cargo.toml @@ -29,30 +29,30 @@ sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-std = { version = "8.0.0", path = "../../primitives/std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "pallet-balances/runtime-benchmarks" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index 87281f0abdf19..76eafeb2db57b 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -31,30 +31,30 @@ pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" } sp-core = { version = "21.0.0", path = "../../primitives/core" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", + "pallet-collective/std", + "pallet-root-testing/std", + "pallet-timestamp/std", "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "pallet-collective/std", - "pallet-root-testing/std", - "pallet-timestamp/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-collective/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", @@ -63,5 +63,5 @@ try-runtime = [ "pallet-collective/try-runtime", "pallet-root-testing/try-runtime", "pallet-timestamp/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 1bf4491f3495b..e6826903c9dfb 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -30,30 +30,30 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", default-features = false, path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/frame/whitelist/Cargo.toml b/frame/whitelist/Cargo.toml index ba05859df2913..f82900340f386 100644 --- a/frame/whitelist/Cargo.toml +++ b/frame/whitelist/Cargo.toml @@ -28,34 +28,34 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-io = { version = "23.0.0", path = "../../primitives/io" } [features] -default = ["std"] +default = [ "std" ] std = [ - "frame-benchmarking?/std", "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", + "pallet-preimage/std", "scale-info/std", "sp-api/std", + "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std", - "pallet-preimage/std", - "sp-core/std", - "sp-io/std" ] runtime-benchmarks = [ "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-preimage/try-runtime", - "sp-runtime/try-runtime" + "sp-runtime/try-runtime", ] diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index 2f0fe5d5d93cb..544afe6980fa3 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -32,24 +32,24 @@ log = { version = "0.4.17", default-features = false } sp-test-primitives = { version = "2.0.0", path = "../test-primitives" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", + "hash-db", + "log/std", + "scale-info/std", + "sp-api-proc-macro/std", "sp-core/std", "sp-externalities", - "sp-std/std", + "sp-externalities?/std", + "sp-metadata-ir?/std", "sp-runtime/std", "sp-state-machine/std", + "sp-std/std", + "sp-test-primitives/std", "sp-trie/std", "sp-version/std", - "hash-db", "thiserror", - "log/std", - "scale-info/std", - "sp-metadata-ir?/std", - "sp-api-proc-macro/std", - "sp-externalities?/std", - "sp-test-primitives/std" ] # Special feature to disable logging completely. # @@ -58,10 +58,7 @@ std = [ # building a runtime for registering it on chain. # # This sets the max logging level to `off` for `log`. -disable-logging = ["log/max_level_off"] +disable-logging = [ "log/max_level_off" ] # Do not report the documentation in the metadata. -no-metadata-docs = ["sp-api-proc-macro/no-metadata-docs"] -frame-metadata = [ - "sp-metadata-ir", - "sp-api-proc-macro/frame-metadata" -] +no-metadata-docs = [ "sp-api-proc-macro/no-metadata-docs" ] +frame-metadata = [ "sp-api-proc-macro/frame-metadata", "sp-metadata-ir" ] diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index fb6513806c812..862cf00fdd67c 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -29,7 +29,7 @@ assert_matches = "1.3.0" [features] # Required for the doc tests -default = ["std"] +default = [ "std" ] std = [] no-metadata-docs = [] frame-metadata = [] diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index 66bc5b0e9e5e3..74cfa0980623b 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -31,10 +31,11 @@ use quote::quote; use syn::{ fold::{self, Fold}, + parenthesized, parse::{Error, Parse, ParseStream, Result}, parse_macro_input, parse_quote, spanned::Spanned, - Attribute, Ident, ImplItem, ItemImpl, Path, Signature, Type, TypePath, + Attribute, Ident, ImplItem, ItemImpl, LitInt, LitStr, Path, Signature, Type, TypePath, }; use std::collections::HashSet; @@ -67,6 +68,7 @@ fn generate_impl_call( runtime: &Type, input: &Ident, impl_trait: &Path, + api_version: &ApiVersion, ) -> Result { let params = extract_parameter_names_types_and_borrows(signature, AllowSelfRefInParameters::No)?; @@ -111,11 +113,40 @@ fn generate_impl_call( ) }; + let fn_calls = if let Some(feature_gated) = &api_version.feature_gated { + let pnames = pnames2; + let pnames2 = pnames.clone(); + let pborrow2 = pborrow.clone(); + + let feature_name = &feature_gated.0; + let impl_trait_fg = extend_with_api_version(impl_trait.clone(), Some(feature_gated.1)); + let impl_trait = extend_with_api_version(impl_trait.clone(), api_version.custom); + + quote!( + #[cfg(feature = #feature_name)] + #[allow(deprecated)] + let r = <#runtime as #impl_trait_fg>::#fn_name(#( #pborrow #pnames ),*); + + #[cfg(not(feature = #feature_name))] + #[allow(deprecated)] + let r = <#runtime as #impl_trait>::#fn_name(#( #pborrow2 #pnames2 ),*); + + r + ) + } else { + let pnames = pnames2; + let impl_trait = extend_with_api_version(impl_trait.clone(), api_version.custom); + + quote!( + #[allow(deprecated)] + <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames ),*) + ) + }; + Ok(quote!( #decode_params - #[allow(deprecated)] - <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*) + #fn_calls )) } @@ -130,7 +161,6 @@ fn generate_impl_calls( let trait_api_ver = extract_api_version(&impl_.attrs, impl_.span())?; let impl_trait_path = extract_impl_trait(impl_, RequireQualifiedTraitPath::Yes)?; let impl_trait = extend_with_runtime_decl_path(impl_trait_path.clone()); - let impl_trait = extend_with_api_version(impl_trait, trait_api_ver); let impl_trait_ident = &impl_trait_path .segments .last() @@ -139,14 +169,23 @@ fn generate_impl_calls( for item in &impl_.items { if let ImplItem::Fn(method) = item { - let impl_call = - generate_impl_call(&method.sig, &impl_.self_ty, input, &impl_trait)?; + let impl_call = generate_impl_call( + &method.sig, + &impl_.self_ty, + input, + &impl_trait, + &trait_api_ver, + )?; + let mut attrs = filter_cfg_attrs(&impl_.attrs); + + // Add any `#[cfg(feature = X)]` attributes of the method to result + attrs.extend(filter_cfg_attrs(&method.attrs)); impl_calls.push(( impl_trait_ident.clone(), method.sig.ident.clone(), impl_call, - filter_cfg_attrs(&impl_.attrs), + attrs, )); } } @@ -441,6 +480,18 @@ fn extend_with_api_version(mut trait_: Path, version: Option) -> Path { trait_ } +/// Adds a feature guard to `attributes`. +/// +/// Depending on `enable`, the feature guard either enables ('feature = "something"`) or disables +/// (`not(feature = "something")`). +fn add_feature_guard(attrs: &mut Vec, feature_name: &str, enable: bool) { + let attr = match enable { + true => parse_quote!(#[cfg(feature = #feature_name)]), + false => parse_quote!(#[cfg(not(feature = #feature_name))]), + }; + attrs.push(attr); +} + /// Generates the implementations of the apis for the runtime. fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result { let mut impls_prepared = Vec::new(); @@ -451,12 +502,29 @@ fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result { let trait_api_ver = extract_api_version(&impl_.attrs, impl_.span())?; let mut impl_ = impl_.clone(); + impl_.attrs = filter_cfg_attrs(&impl_.attrs); + let trait_ = extract_impl_trait(&impl_, RequireQualifiedTraitPath::Yes)?.clone(); let trait_ = extend_with_runtime_decl_path(trait_); - let trait_ = extend_with_api_version(trait_, trait_api_ver); + // If the trait api contains feature gated version - there are staging methods in it. Handle + // them explicitly here by adding staging implementation with `#cfg(feature = ...)` and + // stable implementation with `#[cfg(not(feature = ...))]`. + if let Some(feature_gated) = trait_api_ver.feature_gated { + let mut feature_gated_impl = impl_.clone(); + add_feature_guard(&mut feature_gated_impl.attrs, &feature_gated.0, true); + feature_gated_impl.trait_.as_mut().unwrap().1 = + extend_with_api_version(trait_.clone(), Some(feature_gated.1)); + + impls_prepared.push(feature_gated_impl); + + // Finally add `#[cfg(not(feature = ...))]` for the stable implementation (which is + // generated outside this if). + add_feature_guard(&mut impl_.attrs, &feature_gated.0, false); + } + // Generate stable trait implementation. + let trait_ = extend_with_api_version(trait_, trait_api_ver.custom); impl_.trait_.as_mut().unwrap().1 = trait_; - impl_.attrs = filter_cfg_attrs(&impl_.attrs); impls_prepared.push(impl_); } @@ -663,7 +731,8 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result { let c = generate_crate_access(); for impl_ in impls { - let api_ver = extract_api_version(&impl_.attrs, impl_.span())?.map(|a| a as u32); + let versions = extract_api_version(&impl_.attrs, impl_.span())?; + let api_ver = versions.custom.map(|a| a as u32); let mut path = extend_with_runtime_decl_path( extract_impl_trait(impl_, RequireQualifiedTraitPath::Yes)?.clone(), @@ -687,11 +756,34 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result { } let id: Path = parse_quote!( #path ID ); - let version = quote!( #path VERSION ); - let attrs = filter_cfg_attrs(&impl_.attrs); + let mut attrs = filter_cfg_attrs(&impl_.attrs); + + // Handle API versioning + // If feature gated version is set - handle it first + if let Some(feature_gated) = versions.feature_gated { + let feature_gated_version = feature_gated.1 as u32; + // the attributes for the feature gated staging api + let mut feature_gated_attrs = attrs.clone(); + add_feature_guard(&mut feature_gated_attrs, &feature_gated.0, true); + populate_runtime_api_versions( + &mut result, + &mut sections, + feature_gated_attrs, + id.clone(), + quote!( #feature_gated_version ), + &c, + ); + + // Add `#[cfg(not(feature ...))]` to the initial attributes. If the staging feature flag + // is not set we want to set the stable api version + add_feature_guard(&mut attrs, &feature_gated.0, false); + } - let api_ver = api_ver.map(|a| quote!( #a )).unwrap_or_else(|| version); - populate_runtime_api_versions(&mut result, &mut sections, attrs, id, api_ver, &c) + // Now add the stable api version to the versions list. If the api has got staging functions + // there might be a `#[cfg(not(feature ...))]` attribute attached to the stable version. + let base_api_version = quote!( #path VERSION ); + let api_ver = api_ver.map(|a| quote!( #a )).unwrap_or_else(|| base_api_version); + populate_runtime_api_versions(&mut result, &mut sections, attrs, id, api_ver, &c); } Ok(quote!( @@ -758,12 +850,64 @@ fn filter_cfg_attrs(attrs: &[Attribute]) -> Vec { attrs.iter().filter(|a| a.path().is_ident("cfg")).cloned().collect() } +/// Parse feature flagged api_version. +/// E.g. `#[cfg_attr(feature = "enable-staging-api", api_version(99))]` +fn extract_cfg_api_version(attrs: &Vec, span: Span) -> Result> { + let cfg_attrs = attrs.iter().filter(|a| a.path().is_ident("cfg_attr")).collect::>(); + + let mut cfg_api_version_attr = Vec::new(); + for cfg_attr in cfg_attrs { + let mut feature_name = None; + let mut api_version = None; + cfg_attr.parse_nested_meta(|m| { + if m.path.is_ident("feature") { + let a = m.value()?; + let b: LitStr = a.parse()?; + feature_name = Some(b.value()); + } else if m.path.is_ident(API_VERSION_ATTRIBUTE) { + let content; + parenthesized!(content in m.input); + let ver: LitInt = content.parse()?; + api_version = Some(ver.base10_parse::()?); + } + Ok(()) + })?; + + // If there is a cfg attribute containing api_version - save if for processing + if let (Some(feature_name), Some(api_version)) = (feature_name, api_version) { + cfg_api_version_attr.push((feature_name, api_version, cfg_attr.span())); + } + } + + if cfg_api_version_attr.len() > 1 { + let mut err = Error::new(span, format!("Found multiple feature gated api versions (cfg attribute with nested `{}` attribute). This is not supported.", API_VERSION_ATTRIBUTE)); + for (_, _, attr_span) in cfg_api_version_attr { + err.combine(Error::new(attr_span, format!("`{}` found here", API_VERSION_ATTRIBUTE))); + } + + return Err(err) + } + + Ok(cfg_api_version_attr + .into_iter() + .next() + .map(|(feature, name, _)| (feature, name))) +} + +/// Represents an API version. +struct ApiVersion { + /// Corresponds to `#[api_version(X)]` attribute. + pub custom: Option, + /// Corresponds to `#[cfg_attr(feature = "enable-staging-api", api_version(99))]` + /// attribute. `String` is the feature name, `u64` the staging api version. + pub feature_gated: Option<(String, u64)>, +} + // Extracts the value of `API_VERSION_ATTRIBUTE` and handles errors. // Returns: // - Err if the version is malformed -// - Some(u64) if the version is set -// - None if the version is not set (this is valid). -fn extract_api_version(attrs: &Vec, span: Span) -> Result> { +// - `ApiVersion` on success. If a version is set or not is determined by the fields of `ApiVersion` +fn extract_api_version(attrs: &Vec, span: Span) -> Result { // First fetch all `API_VERSION_ATTRIBUTE` values (should be only one) let api_ver = attrs .iter() @@ -782,7 +926,10 @@ fn extract_api_version(attrs: &Vec, span: Span) -> Result } // Parse the runtime version if there exists one. - api_ver.first().map(|v| parse_runtime_api_version(v)).transpose() + Ok(ApiVersion { + custom: api_ver.first().map(|v| parse_runtime_api_version(v)).transpose()?, + feature_gated: extract_cfg_api_version(attrs, span)?, + }) } #[cfg(test)] diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index e575f6b9bbff5..c3f80acf09ae5 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -344,6 +344,54 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// ``` /// In this case `Balance` api version 3 is being implemented for `Runtime`. The `impl` block /// must contain all methods declared in version 3 and below. +/// +/// # Conditional version implementation +/// +/// `impl_runtime_apis!` supports `cfg_attr` attribute for conditional compilation. For example +/// let's say you want to implement a staging version of the runtime api and put it behind a +/// feature flag. You can do it this way: +/// ```ignore +/// pub struct Runtime {} +/// sp_api::decl_runtime_apis! { +/// pub trait ApiWithStagingMethod { +/// fn stable_one(data: u64); +/// +/// #[api_version(99)] +/// fn staging_one(); +/// } +/// } +/// +/// sp_api::impl_runtime_apis! { +/// #[cfg_attr(feature = "enable-staging-api", api_version(99))] +/// impl self::ApiWithStagingMethod for Runtime { +/// fn stable_one(_: u64) {} +/// +/// #[cfg(feature = "enable-staging-api")] +/// fn staging_one() {} +/// } +/// } +/// ``` +/// +/// [`decl_runtime_apis!`] declares two version of the api - 1 (the default one, which is +/// considered stable in our example) and 99 (which is considered staging). In +/// `impl_runtime_apis!` a `cfg_attr` attribute is attached to the `ApiWithStagingMethod` +/// implementation. If the code is compiled with `enable-staging-api` feature a version 99 of +/// the runtime api will be built which will include `staging_one`. Note that `staging_one` +/// implementation is feature gated by `#[cfg(feature = ... )]` attribute. +/// +/// If the code is compiled without `enable-staging-api` version 1 (the default one) will be +/// built which doesn't include `staging_one`. +/// +/// `cfg_attr` can also be used together with `api_version`. For the next snippet will build +/// version 99 if `enable-staging-api` is enabled and version 2 otherwise because both +/// `cfg_attr` and `api_version` are attached to the impl block: +/// ```ignore +/// #[cfg_attr(feature = "enable-staging-api", api_version(99))] +/// #[api_version(2)] +/// impl self::ApiWithStagingAndVersionedMethods for Runtime { +/// // impl skipped +/// } +/// ``` pub use sp_api_proc_macro::impl_runtime_apis; /// Mocks given trait implementations as runtime apis. diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 87c5eb6199efe..48eb067e4e474 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -35,3 +35,6 @@ static_assertions = "1.1.0" [[bench]] name = "bench" harness = false + +[features] +"enable-staging-api" = [] diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 274f80bd1b465..6e895680e41c4 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -50,6 +50,29 @@ decl_runtime_apis! { #[api_version(4)] fn glory_one(); } + + pub trait ApiWithStagingMethod { + fn stable_one(data: u64); + #[api_version(99)] + fn staging_one(); + } + + pub trait ApiWithStagingAndVersionedMethods { + fn stable_one(data: u64); + #[api_version(2)] + fn new_one(); + #[api_version(99)] + fn staging_one(); + } + + #[api_version(2)] + pub trait ApiWithStagingAndChangedBase { + fn stable_one(data: u64); + fn new_one(); + #[api_version(99)] + fn staging_one(); + } + } impl_runtime_apis! { @@ -82,6 +105,33 @@ impl_runtime_apis! { fn new_one() {} } + #[cfg_attr(feature = "enable-staging-api", api_version(99))] + impl self::ApiWithStagingMethod for Runtime { + fn stable_one(_: u64) {} + + #[cfg(feature = "enable-staging-api")] + fn staging_one() { } + } + + #[cfg_attr(feature = "enable-staging-api", api_version(99))] + #[api_version(2)] + impl self::ApiWithStagingAndVersionedMethods for Runtime { + fn stable_one(_: u64) {} + fn new_one() {} + + #[cfg(feature = "enable-staging-api")] + fn staging_one() {} + } + + #[cfg_attr(feature = "enable-staging-api", api_version(99))] + impl self::ApiWithStagingAndChangedBase for Runtime { + fn stable_one(_: u64) {} + fn new_one() {} + + #[cfg(feature = "enable-staging-api")] + fn staging_one() {} + } + impl sp_api::Core for Runtime { fn version() -> sp_version::RuntimeVersion { unimplemented!() @@ -179,12 +229,38 @@ fn check_runtime_api_info() { // The stable version of the API assert_eq!(>::VERSION, 2); + + assert_eq!(>::VERSION, 1); + assert_eq!(>::VERSION, 1); + assert_eq!(>::VERSION, 2); } fn check_runtime_api_versions_contains() { assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, T::VERSION))); } +fn check_staging_runtime_api_versions(_staging_ver: u32) { + // Staging APIs should contain staging version if the feature is set... + #[cfg(feature = "enable-staging-api")] + assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, _staging_ver))); + //... otherwise the base version should be set + #[cfg(not(feature = "enable-staging-api"))] + check_runtime_api_versions_contains::>(); +} + +#[allow(unused_assignments)] +fn check_staging_multiver_runtime_api_versions( + _staging_ver: u32, + _stable_ver: u32, +) { + // Staging APIs should contain staging version if the feature is set... + #[cfg(feature = "enable-staging-api")] + assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, _staging_ver))); + //... otherwise the base version should be set + #[cfg(not(feature = "enable-staging-api"))] + assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, _stable_ver))); +} + #[test] fn check_runtime_api_versions() { check_runtime_api_versions_contains::>(); @@ -192,6 +268,13 @@ fn check_runtime_api_versions() { assert!(RUNTIME_API_VERSIONS .iter() .any(|v| v == &(>::ID, 3))); + + check_staging_runtime_api_versions::>(99); + check_staging_multiver_runtime_api_versions::>( + 99, 2, + ); + check_staging_runtime_api_versions::>(99); + check_runtime_api_versions_contains::>(); } diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index f27ec881e1961..e4daebd51c197 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -25,40 +25,33 @@ sp-io = { version = "23.0.0", default-features = false, path = "../io" } [features] default = [ "std" ] std = [ - "full_crypto", - "sp-core/std", "codec/std", + "full_crypto", "scale-info/std", "serde/std", - "sp-std/std", + "sp-core/std", "sp-io/std", + "sp-std/std", ] # Serde support without relying on std features. -serde = [ - "dep:serde", - "sp-core/serde", - "scale-info/serde", -] +serde = [ "dep:serde", "scale-info/serde", "sp-core/serde" ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers # or Intel SGX. # For the regular wasm runtime builds this should not be used. full_crypto = [ "sp-core/full_crypto", + "sp-io/disable_oom", # Don't add `panic_handler` and `alloc_error_handler` since they are expected to be provided # by the user anyway. "sp-io/disable_panic_handler", - "sp-io/disable_oom", ] # This feature adds BLS crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bls-experimental = [ - "sp-core/bls-experimental", - "sp-io/bls-experimental", -] +bls-experimental = [ "sp-core/bls-experimental", "sp-io/bls-experimental" ] # This feature adds Bandersnatch crypto primitives. # It should not be used in production since the implementation and interface may still diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 972dfee29d12b..d7b9b2bf74791 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -32,20 +32,17 @@ sp-core = { version = "21.0.0", features = ["full_crypto"], path = "../core" } rand = "0.8.5" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "num-traits/std", "scale-info/std", "serde/std", + "sp-core/std", "sp-std/std", - "sp-core/std" ] # Serde support without relying on std features. -serde = [ - "dep:serde", - "scale-info/serde", -] +serde = [ "dep:serde", "scale-info/serde" ] [[bench]] name = "bench" diff --git a/primitives/arithmetic/src/fixed_point.rs b/primitives/arithmetic/src/fixed_point.rs index d3e75f6f781cd..ce14d2957b5e2 100644 --- a/primitives/arithmetic/src/fixed_point.rs +++ b/primitives/arithmetic/src/fixed_point.rs @@ -45,7 +45,7 @@ pub trait FixedPointOperand: + Bounded + Zero + Saturating - + PartialOrd + + PartialOrd + UniqueSaturatedInto + TryFrom + CheckedNeg @@ -58,7 +58,7 @@ impl FixedPointOperand for T where + Bounded + Zero + Saturating - + PartialOrd + + PartialOrd + UniqueSaturatedInto + TryFrom + CheckedNeg diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 03c9ef2c7d26b..8e47208238a39 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -21,7 +21,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../runtime" sp-std = { version = "8.0.0", default-features = false, path = "../std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "scale-info/std", diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index ba0e1f041e0da..1b62747770a6e 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -20,9 +20,4 @@ sp-std = { version = "8.0.0", default-features = false, path = "../std" } [features] default = [ "std" ] -std = [ - "sp-api/std", - "sp-inherents/std", - "sp-runtime/std", - "sp-std/std", -] +std = [ "sp-api/std", "sp-inherents/std", "sp-runtime/std", "sp-std/std" ] diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index b50e43acfd653..f841a65a7d6cf 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -25,7 +25,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../std" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } [features] -default = ["std"] +default = [ "std" ] std = [ "async-trait", "codec/std", diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index 3e22c89a29d64..ca502c2c6ddb3 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -27,7 +27,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../std" } sp-timestamp = { version = "4.0.0-dev", optional = true, path = "../../timestamp" } [features] -default = ["std"] +default = [ "std" ] std = [ "async-trait", "codec/std", @@ -40,7 +40,7 @@ std = [ "sp-inherents/std", "sp-runtime/std", "sp-std/std", - "sp-timestamp/std", + "sp-timestamp/std", ] # Serde support without relying on std features. diff --git a/primitives/consensus/beefy/Cargo.toml b/primitives/consensus/beefy/Cargo.toml index e6445919e2a1a..bbc69cef7466d 100644 --- a/primitives/consensus/beefy/Cargo.toml +++ b/primitives/consensus/beefy/Cargo.toml @@ -30,7 +30,7 @@ array-bytes = "6.1" w3f-bls = { version = "0.1.3", features = ["std"]} [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "scale-info/std", @@ -56,6 +56,6 @@ serde = [ # This feature adds BLS crypto primitives. It should not be used in production since # the BLS implementation and interface may still be subject to significant change. bls-experimental = [ - "sp-core/bls-experimental", - "sp-application-crypto/bls-experimental", + "sp-application-crypto/bls-experimental", + "sp-core/bls-experimental", ] diff --git a/primitives/consensus/beefy/src/mmr.rs b/primitives/consensus/beefy/src/mmr.rs index 991dc07c5a7f3..660506b8763f1 100644 --- a/primitives/consensus/beefy/src/mmr.rs +++ b/primitives/consensus/beefy/src/mmr.rs @@ -162,6 +162,12 @@ mod mmr_root_provider { _phantom: PhantomData, } + impl Clone for MmrRootProvider { + fn clone(&self) -> Self { + Self { runtime: self.runtime.clone(), _phantom: PhantomData } + } + } + impl MmrRootProvider where B: Block, diff --git a/primitives/consensus/grandpa/Cargo.toml b/primitives/consensus/grandpa/Cargo.toml index 2d0ff26f89702..1bbbbe61bb541 100644 --- a/primitives/consensus/grandpa/Cargo.toml +++ b/primitives/consensus/grandpa/Cargo.toml @@ -27,7 +27,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../runti sp-std = { version = "8.0.0", default-features = false, path = "../../std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "grandpa/std", @@ -37,9 +37,9 @@ std = [ "sp-api/std", "sp-application-crypto/std", "sp-core/std", - "sp-keystore/std", - "sp-runtime/std", - "sp-std/std" + "sp-keystore/std", + "sp-runtime/std", + "sp-std/std", ] # Serde support without relying on std features. diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index 1c8c75c4b1934..491486fe0c396 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -20,7 +20,7 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../../runti sp-std = { version = "8.0.0", default-features = false, path = "../../std" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "sp-api/std", diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index a0404f46abffa..ffc347a78697e 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -20,7 +20,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../../std" } sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "scale-info/std", @@ -30,7 +30,4 @@ std = [ ] # Serde support without relying on std features. -serde = [ - "dep:serde", - "scale-info/serde", -] +serde = [ "dep:serde", "scale-info/serde" ] diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index ee4bf8924186c..85952b355464d 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -73,67 +73,67 @@ harness = false bench = false [features] -default = ["std"] +default = [ "std" ] std = [ + "array-bytes", "arrayvec/std", - "merlin/std", + "bandersnatch_vrfs/getrandom", + "blake2/std", + "bounded-collections/std", + "bs58/std", + "codec/std", + "dyn-clonable", + "ed25519-zebra/std", "full_crypto", - "log/std", - "thiserror", + "futures", + "futures/thread-pool", + "hash-db/std", + "hash256-std-hasher/std", + "impl-serde/std", "lazy_static", + "libsecp256k1/std", + "log/std", + "merlin/std", "parking_lot", - "bandersnatch_vrfs/getrandom", - "bounded-collections/std", - "primitive-types/std", - "primitive-types/serde", "primitive-types/byteorder", "primitive-types/rustc-hex", - "impl-serde/std", - "codec/std", - "scale-info/std", - "hash256-std-hasher/std", - "hash-db/std", - "sp-std/std", - "serde/std", - "blake2/std", - "array-bytes", - "ed25519-zebra/std", - "bs58/std", - "substrate-bip39", - "tiny-bip39", + "primitive-types/serde", + "primitive-types/std", "rand", - "schnorrkel/std", "regex", - "secp256k1/std", + "scale-info/std", + "schnorrkel/std", "secp256k1/global-context", + "secp256k1/std", + "secrecy/alloc", + "serde/std", "sp-core-hashing/std", "sp-debug-derive/std", - "sp-storage/std", + "sp-externalities/std", "sp-runtime-interface/std", + "sp-std/std", + "sp-storage/std", "ss58-registry/std", - "zeroize/alloc", - "secrecy/alloc", - "futures", - "futures/thread-pool", - "libsecp256k1/std", - "dyn-clonable", + "substrate-bip39", + "thiserror", + "tiny-bip39", "tracing", - "sp-externalities/std" + "zeroize/alloc", ] # Serde support without relying on std features. serde = [ - "dep:serde", "array-bytes", "blake2", "bounded-collections/serde", "bs58/alloc", - "scale-info/serde", - "secrecy/alloc", + "dep:serde", "impl-serde", "primitive-types/serde_no_std", - "sp-storage/serde", + "scale-info/serde", + "secrecy/alloc", "sp-core-hashing", + "sp-storage/serde", ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers @@ -141,8 +141,8 @@ serde = [ # For the regular wasm runtime builds this should not be used. full_crypto = [ "array-bytes", - "ed25519-zebra", "blake2", + "ed25519-zebra", "libsecp256k1", "secp256k1", "sp-core-hashing", @@ -152,9 +152,9 @@ full_crypto = [ # This feature adds BLS crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bls-experimental = ["w3f-bls"] +bls-experimental = [ "w3f-bls" ] # This feature adds Bandersnatch crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bandersnatch-experimental = ["bandersnatch_vrfs"] +bandersnatch-experimental = [ "bandersnatch_vrfs" ] diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index 43a13883358ea..a4ddb6363f774 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -21,11 +21,11 @@ sha3 = { version = "0.10.0", default-features = false } twox-hash = { version = "1.6.3", default-features = false, features = ["digest_0_10"] } [features] -default = ["std"] +default = [ "std" ] std = [ - "digest/std", "blake2b_simd/std", "byteorder/std", + "digest/std", "sha2/std", "sha3/std", "twox-hash/std", diff --git a/primitives/crypto/ec-utils/Cargo.toml b/primitives/crypto/ec-utils/Cargo.toml index 9c28c9af9f3bb..90cd38722e0e1 100644 --- a/primitives/crypto/ec-utils/Cargo.toml +++ b/primitives/crypto/ec-utils/Cargo.toml @@ -39,24 +39,24 @@ sp-ark-ed-on-bls12-381-bandersnatch = { version = "0.4.0-beta", default-features [features] default = [ "std" ] std = [ - "ark-serialize/std", - "ark-ff/std", - "ark-ec/std", - "ark-std/std", + "ark-algebra-test-templates/std", "ark-bls12-377/std", "ark-bls12-381/std", "ark-bw6-761/std", - "ark-ed-on-bls12-381-bandersnatch/std", + "ark-ec/std", "ark-ed-on-bls12-377/std", - "sp-std/std", - "codec/std", + "ark-ed-on-bls12-381-bandersnatch/std", + "ark-ff/std", "ark-scale/std", - "sp-runtime-interface/std", - "sp-io/std", - "ark-algebra-test-templates/std", + "ark-serialize/std", + "ark-std/std", + "codec/std", "sp-ark-bls12-377/std", "sp-ark-bls12-381/std", - "sp-ark-bw6-761/std", - "sp-ark-ed-on-bls12-377/std", - "sp-ark-ed-on-bls12-381-bandersnatch/std", + "sp-ark-bw6-761/std", + "sp-ark-ed-on-bls12-377/std", + "sp-ark-ed-on-bls12-381-bandersnatch/std", + "sp-io/std", + "sp-runtime-interface/std", + "sp-std/std", ] diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 71dbd122bebec..58edbf83a3cef 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -20,10 +20,5 @@ sp-std = { version = "8.0.0", default-features = false, path = "../std" } sp-storage = { version = "13.0.0", default-features = false, path = "../storage" } [features] -default = ["std"] -std = [ - "codec/std", - "environmental/std", - "sp-std/std", - "sp-storage/std", -] +default = [ "std" ] +std = [ "codec/std", "environmental/std", "sp-std/std", "sp-storage/std" ] diff --git a/primitives/genesis-builder/Cargo.toml b/primitives/genesis-builder/Cargo.toml index d17c6b5da8024..7760ceb3b6dbd 100644 --- a/primitives/genesis-builder/Cargo.toml +++ b/primitives/genesis-builder/Cargo.toml @@ -20,9 +20,4 @@ serde_json = { version = "1.0.85", default-features = false, features = ["alloc" [features] default = [ "std" ] -std = [ - "sp-api/std", - "sp-std/std", - "serde_json/std", - "sp-runtime/std" -] +std = [ "serde_json/std", "sp-api/std", "sp-runtime/std", "sp-std/std" ] diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 3a9a573456668..8ff06596efba9 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -39,29 +39,27 @@ ed25519-dalek = { version = "2.0.0", default-features = false, optional = true } rustversion = "1.0.6" [features] -default = ["std"] +default = [ "std" ] std = [ "bytes/std", - "sp-externalities/std", - "sp-core/std", "codec/std", - "sp-std/std", - "sp-trie/std", - "sp-state-machine/std", + "ed25519-dalek", "libsecp256k1", + "log", "secp256k1", + "sp-core/std", + "sp-externalities/std", + "sp-keystore/std", "sp-runtime-interface/std", + "sp-state-machine/std", + "sp-std/std", "sp-tracing/std", - "tracing/std", + "sp-trie/std", "tracing-core/std", - "log", - "ed25519-dalek", - "sp-keystore/std" + "tracing/std", ] -with-tracing = [ - "sp-tracing/with-tracing" -] +with-tracing = [ "sp-tracing/with-tracing" ] # These two features are used for `no_std` builds for the environments which already provides # `#[panic_handler]`, `#[alloc_error_handler]` and `#[global_allocator]`. @@ -93,13 +91,9 @@ improved_panic_error_reporting = [] # This feature adds BLS crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bls-experimental = [ - "sp-keystore/bls-experimental", -] +bls-experimental = [ "sp-keystore/bls-experimental" ] # This feature adds Bandersnatch crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bandersnatch-experimental = [ - "sp-keystore/bandersnatch-experimental", -] +bandersnatch-experimental = [ "sp-keystore/bandersnatch-experimental" ] diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 8e9f793636066..c2d20dba49014 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -23,4 +23,4 @@ sp-runtime = { version = "24.0.0", path = "../runtime" } # This feature adds Bandersnatch crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bandersnatch-experimental = ["sp-core/bandersnatch-experimental"] +bandersnatch-experimental = [ "sp-core/bandersnatch-experimental" ] diff --git a/primitives/keystore/Cargo.toml b/primitives/keystore/Cargo.toml index 7e551b7cbf268..e9e699f4cc6c0 100644 --- a/primitives/keystore/Cargo.toml +++ b/primitives/keystore/Cargo.toml @@ -24,19 +24,15 @@ rand = "0.7.2" rand_chacha = "0.2.2" [features] -default = ["std"] -std = [ - "codec/std", - "sp-core/std", - "sp-externalities/std", -] +default = [ "std" ] +std = [ "codec/std", "sp-core/std", "sp-externalities/std" ] # This feature adds BLS crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bls-experimental = ["sp-core/bls-experimental"] +bls-experimental = [ "sp-core/bls-experimental" ] # This feature adds Bandersnatch crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. -bandersnatch-experimental = ["sp-core/bandersnatch-experimental"] +bandersnatch-experimental = [ "sp-core/bandersnatch-experimental" ] diff --git a/primitives/merkle-mountain-range/Cargo.toml b/primitives/merkle-mountain-range/Cargo.toml index 9ede77ba40be2..606774d12d5b3 100644 --- a/primitives/merkle-mountain-range/Cargo.toml +++ b/primitives/merkle-mountain-range/Cargo.toml @@ -28,7 +28,7 @@ thiserror = "1.0" array-bytes = "6.1" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "log/std", @@ -42,9 +42,4 @@ std = [ ] # Serde support without relying on std features. -serde = [ - "dep:serde", - "scale-info/serde", - "sp-core/serde", - "sp-runtime/serde", -] +serde = [ "dep:serde", "scale-info/serde", "sp-core/serde", "sp-runtime/serde" ] diff --git a/primitives/metadata-ir/Cargo.toml b/primitives/metadata-ir/Cargo.toml index 49fd23e208e41..c06aaa5c48b69 100644 --- a/primitives/metadata-ir/Cargo.toml +++ b/primitives/metadata-ir/Cargo.toml @@ -19,10 +19,5 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" sp-std = { version = "8.0.0", default-features = false, path = "../std" } [features] -default = ["std"] -std = [ - "codec/std", - "frame-metadata/std", - "scale-info/std", - "sp-std/std", -] +default = [ "std" ] +std = [ "codec/std", "frame-metadata/std", "scale-info/std", "sp-std/std" ] diff --git a/primitives/npos-elections/Cargo.toml b/primitives/npos-elections/Cargo.toml index cd704082f5713..7faab23b04fbd 100644 --- a/primitives/npos-elections/Cargo.toml +++ b/primitives/npos-elections/Cargo.toml @@ -26,7 +26,7 @@ rand = "0.8.5" substrate-test-utils = { version = "4.0.0-dev", path = "../../test-utils" } [features] -default = ["std"] +default = [ "std" ] bench = [] std = [ "codec/std", diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index 6d73bf9212138..0e1c98fb1cf17 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -18,5 +18,5 @@ sp-core = { version = "21.0.0", default-features = false, path = "../core" } sp-runtime = { version = "24.0.0", default-features = false, path = "../runtime" } [features] -default = ["std"] -std = ["sp-api/std", "sp-core/std", "sp-runtime/std"] +default = [ "std" ] +std = [ "sp-api/std", "sp-core/std", "sp-runtime/std" ] diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index e0d6d9d89bd31..49ed49e1b417e 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -37,18 +37,18 @@ trybuild = "1.0.74" [features] default = [ "std" ] std = [ - "sp-storage/std", "bytes/std", - "sp-wasm-interface/std", - "sp-std/std", - "sp-tracing/std", "codec/std", - "sp-externalities/std", "primitive-types/std", "sp-core/std", + "sp-externalities/std", "sp-io/std", "sp-runtime-interface-test-wasm/std", - "sp-state-machine/std" + "sp-state-machine/std", + "sp-std/std", + "sp-storage/std", + "sp-tracing/std", + "sp-wasm-interface/std", ] # ATTENTION diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index 2ff86086a890b..d2fd8a2f2c5c4 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -23,8 +23,8 @@ substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-bu [features] default = [ "std" ] std = [ - "sp-core/std", - "sp-io/std", - "sp-runtime-interface/std", - "substrate-wasm-builder", + "sp-core/std", + "sp-io/std", + "sp-runtime-interface/std", + "substrate-wasm-builder", ] diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index 82fa35267cf51..b1ab8531b0e7d 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -25,9 +25,9 @@ substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-bu [features] default = [ "std" ] std = [ - "sp-core/std", - "sp-io/std", - "sp-runtime-interface/std", - "sp-std/std", - "substrate-wasm-builder", + "sp-core/std", + "sp-io/std", + "sp-runtime-interface/std", + "sp-std/std", + "substrate-wasm-builder", ] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 246b2a2ed2eb0..52affa6aa70c4 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -42,7 +42,7 @@ substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/ru [features] runtime-benchmarks = [] try-runtime = [] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "either/use_std", @@ -51,15 +51,15 @@ std = [ "rand", "scale-info/std", "serde/std", + "sp-api/std", "sp-application-crypto/std", "sp-arithmetic/std", "sp-core/std", "sp-io/std", + "sp-state-machine/std", "sp-std/std", + "sp-tracing/std", "sp-weights/std", - "sp-api/std", - "sp-state-machine/std", - "sp-tracing/std" ] # Serde support without relying on std features. diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml index f547608fe51e7..79ccc110aa781 100644 --- a/primitives/session/Cargo.toml +++ b/primitives/session/Cargo.toml @@ -29,8 +29,8 @@ std = [ "scale-info/std", "sp-api/std", "sp-core/std", + "sp-keystore/std", "sp-runtime/std", "sp-staking/std", "sp-std/std", - "sp-keystore/std" ] diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml index 43ee307aa109a..8fe2f19ad19f6 100644 --- a/primitives/staking/Cargo.toml +++ b/primitives/staking/Cargo.toml @@ -23,15 +23,13 @@ sp-runtime = { default-features = false, path = "../runtime" } sp-std = { default-features = false, path = "../std" } [features] -default = ["std"] +default = [ "std" ] std = [ - "serde/std", "codec/std", "scale-info/std", + "serde/std", "sp-core/std", "sp-runtime/std", "sp-std/std", ] -runtime-benchmarks = [ - "sp-runtime/runtime-benchmarks" -] +runtime-benchmarks = [ "sp-runtime/runtime-benchmarks" ] diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml index 32be8e518f49f..0f5613545b5dc 100644 --- a/primitives/state-machine/Cargo.toml +++ b/primitives/state-machine/Cargo.toml @@ -37,7 +37,7 @@ sp-runtime = { version = "24.0.0", path = "../runtime" } assert_matches = "1.5" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "hash-db/std", @@ -47,10 +47,10 @@ std = [ "sp-core/std", "sp-externalities/std", "sp-panic-handler", + "sp-runtime/std", "sp-std/std", "sp-trie/std", - "trie-db/std", "thiserror", "tracing", - "sp-runtime/std" + "trie-db/std", ] diff --git a/primitives/statement-store/Cargo.toml b/primitives/statement-store/Cargo.toml index d5612eaca8c19..fffb110195d7e 100644 --- a/primitives/statement-store/Cargo.toml +++ b/primitives/statement-store/Cargo.toml @@ -34,30 +34,29 @@ sha2 = { version = "0.10.7", optional = true } rand = { version = "0.8.5", features = ["small_rng"], optional = true } [features] -default = ["std"] +default = [ "std" ] std = [ + "aes-gcm", "codec/std", + "curve25519-dalek", + "ed25519-dalek", + "hkdf", + "rand", "scale-info/std", + "sha2", + "sp-api/std", + "sp-application-crypto/std", "sp-core/std", - "sp-runtime/std", + "sp-externalities/std", "sp-runtime-interface/std", + "sp-runtime/std", "sp-std/std", - "sp-api/std", - "sp-application-crypto/std", "thiserror", - - "ed25519-dalek", "x25519-dalek", - "curve25519-dalek", - "aes-gcm", - "hkdf", - "sha2", - "rand", - "sp-externalities/std" ] serde = [ - "scale-info/serde", - "sp-application-crypto/serde", - "sp-core/serde", - "sp-runtime/serde", + "scale-info/serde", + "sp-application-crypto/serde", + "sp-core/serde", + "sp-runtime/serde", ] diff --git a/primitives/std/Cargo.toml b/primitives/std/Cargo.toml index d16b15f0e6189..4c58d147c7a7a 100644 --- a/primitives/std/Cargo.toml +++ b/primitives/std/Cargo.toml @@ -14,5 +14,5 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [features] -default = ["std"] +default = [ "std" ] std = [] diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml index 412a2b15e0599..42fa01184ff3e 100644 --- a/primitives/storage/Cargo.toml +++ b/primitives/storage/Cargo.toml @@ -32,7 +32,4 @@ std = [ ] # Serde support without relying on std features. -serde = [ - "dep:serde", - "impl-serde", -] +serde = [ "dep:serde", "impl-serde" ] diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml index 8a1ae4d01e405..a14f3fb9b8a47 100644 --- a/primitives/test-primitives/Cargo.toml +++ b/primitives/test-primitives/Cargo.toml @@ -21,17 +21,15 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../runtime" sp-std = { version = "8.0.0", default-features = false, path = "../std" } [features] -default = [ - "std", -] +default = [ "std" ] std = [ "codec/std", + "scale-info/std", "serde/std", "sp-application-crypto/std", "sp-core/std", "sp-runtime/std", "sp-std/std", - "scale-info/std", ] # Serde support without relying on std features. diff --git a/primitives/tracing/Cargo.toml b/primitives/tracing/Cargo.toml index 1ef0a0e73ac14..106e3a725cd06 100644 --- a/primitives/tracing/Cargo.toml +++ b/primitives/tracing/Cargo.toml @@ -29,13 +29,13 @@ tracing-subscriber = { version = "0.2.25", optional = true, features = [ ] } [features] -default = ["std"] -with-tracing = ["codec/derive", "codec/full"] +default = [ "std" ] +with-tracing = [ "codec/derive", "codec/full" ] std = [ - "with-tracing", - "tracing/std", - "tracing-core/std", "codec/std", "sp-std/std", + "tracing-core/std", "tracing-subscriber", + "tracing/std", + "with-tracing", ] diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml index d65db6a1d32fe..cef4a908cc31a 100644 --- a/primitives/transaction-pool/Cargo.toml +++ b/primitives/transaction-pool/Cargo.toml @@ -19,7 +19,4 @@ sp-runtime = { version = "24.0.0", default-features = false, path = "../runtime" [features] default = [ "std" ] -std = [ - "sp-api/std", - "sp-runtime/std", -] +std = [ "sp-api/std", "sp-runtime/std" ] diff --git a/primitives/transaction-storage-proof/Cargo.toml b/primitives/transaction-storage-proof/Cargo.toml index b687f63c2fe2d..5854eb78a4b75 100644 --- a/primitives/transaction-storage-proof/Cargo.toml +++ b/primitives/transaction-storage-proof/Cargo.toml @@ -28,9 +28,9 @@ std = [ "async-trait", "codec/std", "scale-info/std", + "sp-core/std", "sp-inherents/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", - "sp-core/std" ] diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml index 546d6786fc632..5b6877592c315 100644 --- a/primitives/trie/Cargo.toml +++ b/primitives/trie/Cargo.toml @@ -43,23 +43,23 @@ trie-standardmap = "0.16.0" sp-runtime = { version = "24.0.0", path = "../runtime" } [features] -default = ["std"] +default = [ "std" ] std = [ "ahash", "codec/std", - "hashbrown", "hash-db/std", + "hashbrown", "lazy_static", - "schnellru", "memory-db/std", "nohash-hasher", "parking_lot", "scale-info/std", + "schnellru", "sp-core/std", + "sp-runtime/std", "sp-std/std", "thiserror", "tracing", "trie-db/std", "trie-root/std", - "sp-runtime/std" ] diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml index fc59a367ba385..f53a1e2e0c1a4 100644 --- a/primitives/version/Cargo.toml +++ b/primitives/version/Cargo.toml @@ -26,7 +26,7 @@ sp-std = { version = "8.0.0", default-features = false, path = "../std" } sp-version-proc-macro = { version = "8.0.0", default-features = false, path = "proc-macro" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "impl-serde/std", @@ -39,8 +39,4 @@ std = [ ] # Serde support without relying on std features. -serde = [ - "dep:serde", - "impl-serde", - "sp-runtime/serde", -] +serde = [ "dep:serde", "impl-serde", "sp-runtime/serde" ] diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml index 50efd6d9d22d7..cac78fc2521be 100644 --- a/primitives/wasm-interface/Cargo.toml +++ b/primitives/wasm-interface/Cargo.toml @@ -22,6 +22,6 @@ anyhow = { version = "1.0.68", optional = true } sp-std = { version = "8.0.0", default-features = false, path = "../std" } [features] -default = ["std"] -std = ["codec/std", "log", "sp-std/std", "wasmtime"] -wasmtime = ["dep:wasmtime", "anyhow"] +default = [ "std" ] +std = [ "codec/std", "log", "sp-std/std", "wasmtime" ] +wasmtime = [ "anyhow", "dep:wasmtime" ] diff --git a/primitives/weights/Cargo.toml b/primitives/weights/Cargo.toml index 05fc58a10e105..0ee32fbd8d6ea 100644 --- a/primitives/weights/Cargo.toml +++ b/primitives/weights/Cargo.toml @@ -31,11 +31,11 @@ std = [ "sp-arithmetic/std", "sp-core/std", "sp-debug-derive/std", - "sp-std/std" + "sp-std/std", ] # By default some types have documentation, `full-metadata-docs` allows to add documentation to # more types in the metadata. -full-metadata-docs = ["scale-info/docs"] +full-metadata-docs = [ "scale-info/docs" ] # Serde support without relying on std features. serde = [ diff --git a/scripts/ci/gitlab/pipeline/test.yml b/scripts/ci/gitlab/pipeline/test.yml index 61c1aa876f306..ab294ccb436d8 100644 --- a/scripts/ci/gitlab/pipeline/test.yml +++ b/scripts/ci/gitlab/pipeline/test.yml @@ -58,6 +58,17 @@ cargo-fmt: - cargo +nightly fmt --all -- --check - rusty-cachier cache upload +cargo-fmt-manifest: + stage: test + extends: + - .docker-env + - .test-refs + script: + - cargo install zepter --locked --version 0.10.0 -q -f --no-default-features && zepter --version + - echo "👉 Hello developer! If you see this CI check failing then it means that one of the your changes in a Cargo.toml file introduced ill-formatted or unsorted features. Please take a look at 'docs/STYLE_GUIDE.md#manifest-formatting' to find out more." + - zepter format features --check + allow_failure: true # Experimental + cargo-clippy: stage: test # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs @@ -223,9 +234,11 @@ test-linux-stable: --locked --release --verbose - --features runtime-benchmarks,try-runtime,experimental,unsafe-debug + --features runtime-benchmarks,try-runtime,experimental --manifest-path ./bin/node/cli/Cargo.toml --partition count:${CI_NODE_INDEX}/${CI_NODE_TOTAL} + # run runtime-api tests with `enable-staging-api` feature + - time cargo nextest run -p sp-api-test --features enable-staging-api # we need to update cache only from one job - if [ ${CI_NODE_INDEX} == 1 ]; then rusty-cachier cache upload; fi # Upload tests results to Elasticsearch diff --git a/test-utils/cli/Cargo.toml b/test-utils/cli/Cargo.toml index 314fe7ad568f2..20418d602886d 100644 --- a/test-utils/cli/Cargo.toml +++ b/test-utils/cli/Cargo.toml @@ -26,4 +26,4 @@ sc-service = { path = "../../client/service" } futures = "0.3.28" [features] -try-runtime = ["node-cli/try-runtime"] +try-runtime = [ "node-cli/try-runtime" ] diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml index 43ab0da98bd6a..fe517843aff73 100644 --- a/test-utils/runtime/Cargo.toml +++ b/test-utils/runtime/Cargo.toml @@ -65,47 +65,45 @@ json-patch = { version = "1.0.0", default-features = false } substrate-wasm-builder = { version = "5.0.0-dev", path = "../../utils/wasm-builder", optional = true } [features] -default = [ - "std", -] +default = [ "std" ] std = [ "array-bytes", - "sp-genesis-builder/std", + "codec/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "log/std", + "pallet-babe/std", + "pallet-balances/std", + "pallet-timestamp/std", + "sc-executor/std", + "sc-service", + "scale-info/std", + "sp-api/std", "sp-application-crypto/std", + "sp-block-builder/std", "sp-consensus-aura/std", "sp-consensus-babe/std", - "sp-block-builder/std", - "codec/std", - "scale-info/std", + "sp-consensus-grandpa/std", + "sp-core/std", + "sp-externalities/std", + "sp-genesis-builder/std", "sp-inherents/std", + "sp-io/std", "sp-keyring", - "log/std", "sp-offchain/std", - "sp-core/std", - "sp-std/std", - "sp-io/std", - "frame-support/std", - "sp-version/std", - "sp-session/std", - "sp-api/std", "sp-runtime/std", - "sp-externalities/std", + "sp-session/std", "sp-state-machine/std", - "pallet-babe/std", - "pallet-timestamp/std", - "pallet-balances/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "sc-service", - "sp-consensus-grandpa/std", - "sp-trie/std", + "sp-std/std", + "sp-tracing/std", "sp-transaction-pool/std", - "trie-db/std", + "sp-trie/std", + "sp-version/std", "substrate-wasm-builder", - "frame-executive/std", - "sc-executor/std", - "sp-tracing/std" + "trie-db/std", ] # Special feature to disable logging disable-logging = [ "sp-api/disable-logging" ] diff --git a/utils/binary-merkle-tree/Cargo.toml b/utils/binary-merkle-tree/Cargo.toml index 4b7b9e53ef872..f619a5ab5503b 100644 --- a/utils/binary-merkle-tree/Cargo.toml +++ b/utils/binary-merkle-tree/Cargo.toml @@ -20,13 +20,6 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" } [features] -debug = ["array-bytes", "log"] -default = ["debug", "std"] -std = [ - - "log/std", - - "hash-db/std", - "sp-core/std", - "sp-runtime/std" -] +debug = [ "array-bytes", "log" ] +default = [ "debug", "std" ] +std = [ "hash-db/std", "log/std", "sp-core/std", "sp-runtime/std" ] diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml index b7970613d1a11..4b142c205c4d7 100644 --- a/utils/frame/benchmarking-cli/Cargo.toml +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -17,7 +17,7 @@ array-bytes = "6.1" chrono = "0.4" clap = { version = "4.2.5", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.1" } -comfy-table = { version = "7.0.0", default-features = false } +comfy-table = { version = "7.0.1", default-features = false } handlebars = "4.2.2" Inflector = "0.11.4" itertools = "0.10.3" @@ -56,13 +56,13 @@ sp-wasm-interface = { version = "14.0.0", path = "../../../primitives/wasm-inter gethostname = "0.2.3" [features] -default = ["rocksdb"] +default = [ "rocksdb" ] runtime-benchmarks = [ - "sc-client-db/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", - "sp-runtime/runtime-benchmarks" + "sp-runtime/runtime-benchmarks", ] -rocksdb = ["sc-cli/rocksdb", "sc-client-db/rocksdb"] +rocksdb = [ "sc-cli/rocksdb", "sc-client-db/rocksdb" ] diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index 84b9460d137e0..2d8d9b476a450 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -53,8 +53,8 @@ tokio = "1.27.0" [features] try-runtime = [ - "sp-debug-derive/force-debug", "frame-try-runtime/try-runtime", + "sp-debug-derive/force-debug", "sp-runtime/try-runtime", - "substrate-cli-test-utils/try-runtime" + "substrate-cli-test-utils/try-runtime", ]