mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-08 13:38:11 +00:00
c1ed1901e1
* fix online/offline confusion * unified cache file * multi-threaded babyyy * checkpoint for niklas * compiles * all tests pass with --test-threads 1 * child-tree scrape is also multi-threaded now. * better thread splitting * some suggestions (#12532) * some suggestions * tokio multithread * move unused dependencies * snapshot command * fix rem * a bit of cleanup * support optional checks * fix * OCW command migrated to wasm-only, as an example * state-version management fully in remote-ext * almost everything move to wasm executor, some CLI flags reduced * follow-chain works as well * Master.into() * everything builds now * concurrent insertion and download for remote builds * minor fix * fix a bug * checkpoint * some updates * fmt * review comments * fmt * fix * fmt * update * fmt * rename * fix the damn UI tests * fmt * remoe the thread abstraction for the time being * cleanup * fix CI * fmt * fix * fix a few more things * tweak log levels * better error handling * address grumbles: use futures::mpsc * review comments * fmt * Apply suggestions from code review Co-authored-by: Bastian Köcher <git@kchr.de> * Update utils/frame/try-runtime/cli/src/lib.rs Co-authored-by: Bastian Köcher <git@kchr.de> * better api version stuff * some doc update * a whole lot of docs * fmt * fix all docs * fmt * rpc rebase: Try-runtime Revamp and Facelift (#12921) * Introduce sensible weight constants (#12868) * Introduce sensible weight constants * cargo fmt * Remove unused import * Add missing import * ".git/.scripts/bench-bot.sh" pallet dev pallet_lottery Co-authored-by: command-bot <> * Checkout to the branch HEAD explicitly in `build-linux-substrate` (#12876) * cli: Improve pruning documentation (#12819) * cli: Improve pruning documentation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Keep `finalized` notation and remove `canonical` one * cli: Fix cargo doc * cli: `PruningModeClap` IR enum Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Convert PruningModeClap into pruning modes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Use `PruningModeClap` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Rename to `DatabasePruningMode` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Implement `FromStr` instead of `clap::ValueEnum` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update client/cli/src/params/pruning_params.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Add option documentation back Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Apply suggestions from code review Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Bastian Köcher <git@kchr.de> * Revert "Move LockableCurrency trait to fungibles::Lockable and deprecate LockableCurrency (#12798)" (#12882) This reverts commit9a014d1ecd. * Don't indefinitely block on shutting down Tokio (#12885) * Don't indefinitely on shutting down Tokio Now we wait in maximum 60 seconds before we shutdown the node. Tasks are may be leaked and leading to some data corruption. * Drink less :thinking_face: * General Message Queue Pallet (#12485) * The message queue * Make fully generic * Refactor * Docs * Refactor * Use iter not slice * Per-origin queues * Multi-queue processing * Introduce MaxReady * Remove MaxReady in favour of ready ring * Cleanups * ReadyRing and tests * Stale page reaping * from_components -> from_parts Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Move WeightCounter to sp_weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add MockedWeightInfo Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Deploy to kitchensink Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use WeightCounter Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Small fixes and logging Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add service_page Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Typo Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Move service_page below service_queue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add service_message Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use correct weight function Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Overweight execution * Refactor * Missing file * Fix WeightCounter usage in scheduler Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix peek_index Take into account that decoding from a mutable slice modifies it. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add tests and bench service_page_item Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add debug_info Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add no-progress check to service_queues Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add more benches Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Bound from_message and try_append_message Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add PageReaped event Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename BookStateOf and BookStateFor Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update tests and remove logging Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove redundant per-message origins; add footprint() and sweep_queue() * Move testing stuff to mock.rs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add integration test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix no-progress check Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix debug_info Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup merge and tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix footprint tracking * Introduce * Formatting * OverweightEnqueued event, auto-servicing config item * Update tests and benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Provide change handler * Add missing BookStateFor::insert and call QueueChangeHandler Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update benchmarks and weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use weight metering functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * weightInfo::process_message_payload is gone Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add defensive_saturating_accrue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename WeightCounter to WeightMeter Ctr+Shift+H should do the trick. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test on_initialize Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add module docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove origin from MaxMessageLen The message origin is not encoded into the heap and does therefore not influence the max message length anymore. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add BoundedVec::as_slice Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test Page::{from_message, try_append_message} Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Do nothing in sweep_queue if the queue does not exist ... otherwise it inserts default values into the storage. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test ring (un)knitting Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Upgrade stress-test Change the test to not assume that all queued messages will be processed in the next block but split it over multiple. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename BoundedVec::as_slice to as_bounded_slice Conflicts with deref().as_slice() otherwise. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix imports Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove ReadyRing struct Was used for testing only. Instead use 'fn assert_ring' which also check the service head and backlinks. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix stale page watermark Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test feature and clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * QueueChanged handler is called correctly Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update benches Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Abstract testing functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Simplify tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make stuff compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Extend overweight execution benchmark Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove TODOs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test service queue with faulty MessageProcessor Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update pallet ui tests to 1.65 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Review doc fixes Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add weight_limit to extrinsic weight of execute_overweight * Correctly return unused weight * Return actual weight consumed in do_execute_overweight * Review fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Set version 7.0.0-dev Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make it compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Switch message_size to u64 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Switch message_count to u64 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make CI green Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Update tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * ".git/.scripts/bench-bot.sh" pallet dev pallet_message_queue * Dont mention README.md in the Cargo.toml Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove reference to readme Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: parity-processbot <> Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * zombienet timings adjusted (#12890) * zombinet tests: add some timeout to allow net spin-up Sometimes tests are failing at first try, as the pods were not up yet. Adding timeout should allow the network to spin up properly. * initial timeout increased to 30s * Move import queue out of `sc-network` (#12764) * Move import queue out of `sc-network` Add supplementary asynchronous API for the import queue which means it can be run as an independent task and communicated with through the `ImportQueueService`. This commit removes removes block and justification imports from `sc-network` and provides `ChainSync` with a handle to import queue so it can import blocks and justifications. Polling of the import queue is moved complete out of `sc-network` and `sc_consensus::Link` is implemented for `ChainSyncInterfaceHandled` so the import queue can still influence the syncing process. * Fix tests * Apply review comments * Apply suggestions from code review Co-authored-by: Bastian Köcher <git@kchr.de> * Update client/network/sync/src/lib.rs Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Bastian Köcher <git@kchr.de> * Trace response payload in default `jsonrpsee` middleware (#12886) * Trace result in default `jsonrpsee` middleware * `rpc_metrics::extra` Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Bastian Köcher <git@kchr.de> * Ensure that we inform all tasks to stop before starting the 60 seconds shutdown (#12897) * Ensure that we inform all tasks to stop before starting the 60 seconds shutdown The change of waiting in maximum 60 seconds for the node to shutdown actually introduced a bug. We were actually waiting always 60 seconds as we didn't informed our tasks to shutdown. The solution to this problem is to drop the task manager as this will then inform all tasks to end. It also adds tests to ensure that the behaviors work as expected. (This should already have been done in the first pr! :() * ".git/.scripts/fmt.sh" 1 Co-authored-by: command-bot <> * Safe desired targets call (#12826) * checked call for desired targets * fix compile * fmt * fix tests * cleaner with and_then * Fix typo (#12900) * ValidateUnsigned: Improve docs. (#12870) * ValidateUnsigned: Improve docs. * Review comments * rpc server with HTTP/WS on the same socket (#12663) * jsonrpsee v0.16 add backwards compatibility run old http server on http only * cargo fmt * update jsonrpsee 0.16.1 * less verbose cors log * fix nit in log: WS -> HTTP * revert needless changes in Cargo.lock * remove unused features in tower * fix nits; add client-core feature * jsonrpsee v0.16.2 * `pallet-message-queue`: Fix license (#12895) * Fix license Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add mock doc Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use explicit call indices (#12891) * frame-system: explicit call index Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use explicit call indices Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * pallet-template: explicit call index Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * DNM: Temporarily require call_index Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "DNM: Temporarily require call_index" This reverts commit c4934e312e12af72ca05a8029d7da753a9c99346. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Pin canonincalized block (#12902) * Remove implicit approval chilling upon slash. (#12420) * don't read slashing spans when taking election snapshot * update cargo.toml * bring back remote test * fix merge stuff * fix npos-voters function sig * remove as much redundant diff as you can * Update frame/staking/src/pallet/mod.rs Co-authored-by: Andronik <write@reusable.software> * fix * Update frame/staking/src/pallet/impls.rs * update lock * fix all tests * review comments * fmt * fix offence bench * clippy * ".git/.scripts/bench-bot.sh" pallet dev pallet_staking Co-authored-by: Andronik <write@reusable.software> Co-authored-by: Ankan <ankan.anurag@gmail.com> Co-authored-by: command-bot <> * bounties calls docs fix (#12909) Co-authored-by: parity-processbot <> * pallet-contracts migration pre-upgrade fix for v8 (#12905) * Only run pre-v8 migration check for versions older than 8 * Logix fix * use custom environment for publishing crates (#12912) * [contracts] Add debug buffer limit + enforcement (#12845) * Add debug buffer limit + enforcement Add debug buffer limit + enforcement * use BoundedVec for the debug buffer * revert schedule (debug buf len limit not needed anymore) * return DispatchError * addressed review comments * frame/remote-externalities: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/rpc: Add previous export Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Fixup some wrong dependencies (#12899) * Fixup some wrong dependencies Dev dependencies should not appear in the feature list. If features are required, they should be directly enabled for the `dev-dependency`. * More fixups * Fix fix * Remove deprecated feature * Make all work properly and nice!! * FMT * Fix formatting * add numerator and denominator to Rational128 Debug impl and increase precision of float representation (#12914) * Fix state-db pinning (#12927) * Pin all canonicalized blocks * Added a test * Docs * [ci] add job switcher (#12922) Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Vlad <vladimir@parity.io> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Anthony Alaribe <anthonyalaribe@gmail.com> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com> Co-authored-by: tgmichel <telmo@purestake.com> Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> Co-authored-by: Luke Schoen <ltfschoen@users.noreply.github.com> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Andronik <write@reusable.software> Co-authored-by: Ankan <ankan.anurag@gmail.com> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: Dino Pačandi <3002868+Dinonard@users.noreply.github.com> Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> * Revert "rpc rebase: Try-runtime Revamp and Facelift (#12921)" This reverts commit 4ce770a9cb8daf1401529bda7d974b8c703f6b3e. * Lexnv/kiz revamp try runtime stuff (#12932) * Introduce sensible weight constants (#12868) * Introduce sensible weight constants * cargo fmt * Remove unused import * Add missing import * ".git/.scripts/bench-bot.sh" pallet dev pallet_lottery Co-authored-by: command-bot <> * Checkout to the branch HEAD explicitly in `build-linux-substrate` (#12876) * cli: Improve pruning documentation (#12819) * cli: Improve pruning documentation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Keep `finalized` notation and remove `canonical` one * cli: Fix cargo doc * cli: `PruningModeClap` IR enum Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Convert PruningModeClap into pruning modes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Use `PruningModeClap` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Rename to `DatabasePruningMode` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Implement `FromStr` instead of `clap::ValueEnum` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update client/cli/src/params/pruning_params.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Add option documentation back Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Apply suggestions from code review Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Bastian Köcher <git@kchr.de> * Revert "Move LockableCurrency trait to fungibles::Lockable and deprecate LockableCurrency (#12798)" (#12882) This reverts commit9a014d1ecd. * Don't indefinitely block on shutting down Tokio (#12885) * Don't indefinitely on shutting down Tokio Now we wait in maximum 60 seconds before we shutdown the node. Tasks are may be leaked and leading to some data corruption. * Drink less :thinking_face: * General Message Queue Pallet (#12485) * The message queue * Make fully generic * Refactor * Docs * Refactor * Use iter not slice * Per-origin queues * Multi-queue processing * Introduce MaxReady * Remove MaxReady in favour of ready ring * Cleanups * ReadyRing and tests * Stale page reaping * from_components -> from_parts Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Move WeightCounter to sp_weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add MockedWeightInfo Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Deploy to kitchensink Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use WeightCounter Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Small fixes and logging Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add service_page Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Typo Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Move service_page below service_queue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add service_message Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use correct weight function Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Overweight execution * Refactor * Missing file * Fix WeightCounter usage in scheduler Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix peek_index Take into account that decoding from a mutable slice modifies it. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add tests and bench service_page_item Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add debug_info Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add no-progress check to service_queues Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add more benches Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Bound from_message and try_append_message Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add PageReaped event Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename BookStateOf and BookStateFor Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update tests and remove logging Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove redundant per-message origins; add footprint() and sweep_queue() * Move testing stuff to mock.rs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add integration test Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix no-progress check Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix debug_info Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup merge and tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix footprint tracking * Introduce * Formatting * OverweightEnqueued event, auto-servicing config item * Update tests and benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Provide change handler * Add missing BookStateFor::insert and call QueueChangeHandler Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update benchmarks and weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use weight metering functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * weightInfo::process_message_payload is gone Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add defensive_saturating_accrue Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename WeightCounter to WeightMeter Ctr+Shift+H should do the trick. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test on_initialize Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add module docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove origin from MaxMessageLen The message origin is not encoded into the heap and does therefore not influence the max message length anymore. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add BoundedVec::as_slice Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test Page::{from_message, try_append_message} Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixup docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Do nothing in sweep_queue if the queue does not exist ... otherwise it inserts default values into the storage. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test ring (un)knitting Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Upgrade stress-test Change the test to not assume that all queued messages will be processed in the next block but split it over multiple. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests... Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Rename BoundedVec::as_slice to as_bounded_slice Conflicts with deref().as_slice() otherwise. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix imports Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove ReadyRing struct Was used for testing only. Instead use 'fn assert_ring' which also check the service head and backlinks. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix stale page watermark Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix test feature and clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * QueueChanged handler is called correctly Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update benches Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Abstract testing functions Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clippy Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Simplify tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make stuff compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Extend overweight execution benchmark Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove TODOs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test service queue with faulty MessageProcessor Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update pallet ui tests to 1.65 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * More docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Review doc fixes Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add weight_limit to extrinsic weight of execute_overweight * Correctly return unused weight * Return actual weight consumed in do_execute_overweight * Review fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Set version 7.0.0-dev Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make it compile Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Switch message_size to u64 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Switch message_count to u64 Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix benchmarks Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Make CI green Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Update tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * ".git/.scripts/bench-bot.sh" pallet dev pallet_message_queue * Dont mention README.md in the Cargo.toml Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Remove reference to readme Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: parity-processbot <> Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * zombienet timings adjusted (#12890) * zombinet tests: add some timeout to allow net spin-up Sometimes tests are failing at first try, as the pods were not up yet. Adding timeout should allow the network to spin up properly. * initial timeout increased to 30s * Move import queue out of `sc-network` (#12764) * Move import queue out of `sc-network` Add supplementary asynchronous API for the import queue which means it can be run as an independent task and communicated with through the `ImportQueueService`. This commit removes removes block and justification imports from `sc-network` and provides `ChainSync` with a handle to import queue so it can import blocks and justifications. Polling of the import queue is moved complete out of `sc-network` and `sc_consensus::Link` is implemented for `ChainSyncInterfaceHandled` so the import queue can still influence the syncing process. * Fix tests * Apply review comments * Apply suggestions from code review Co-authored-by: Bastian Köcher <git@kchr.de> * Update client/network/sync/src/lib.rs Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Bastian Köcher <git@kchr.de> * Trace response payload in default `jsonrpsee` middleware (#12886) * Trace result in default `jsonrpsee` middleware * `rpc_metrics::extra` Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Bastian Köcher <git@kchr.de> * Ensure that we inform all tasks to stop before starting the 60 seconds shutdown (#12897) * Ensure that we inform all tasks to stop before starting the 60 seconds shutdown The change of waiting in maximum 60 seconds for the node to shutdown actually introduced a bug. We were actually waiting always 60 seconds as we didn't informed our tasks to shutdown. The solution to this problem is to drop the task manager as this will then inform all tasks to end. It also adds tests to ensure that the behaviors work as expected. (This should already have been done in the first pr! :() * ".git/.scripts/fmt.sh" 1 Co-authored-by: command-bot <> * Safe desired targets call (#12826) * checked call for desired targets * fix compile * fmt * fix tests * cleaner with and_then * Fix typo (#12900) * ValidateUnsigned: Improve docs. (#12870) * ValidateUnsigned: Improve docs. * Review comments * rpc server with HTTP/WS on the same socket (#12663) * jsonrpsee v0.16 add backwards compatibility run old http server on http only * cargo fmt * update jsonrpsee 0.16.1 * less verbose cors log * fix nit in log: WS -> HTTP * revert needless changes in Cargo.lock * remove unused features in tower * fix nits; add client-core feature * jsonrpsee v0.16.2 * `pallet-message-queue`: Fix license (#12895) * Fix license Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add mock doc Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use explicit call indices (#12891) * frame-system: explicit call index Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use explicit call indices Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * pallet-template: explicit call index Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * DNM: Temporarily require call_index Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "DNM: Temporarily require call_index" This reverts commit c4934e312e12af72ca05a8029d7da753a9c99346. Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Pin canonincalized block (#12902) * Remove implicit approval chilling upon slash. (#12420) * don't read slashing spans when taking election snapshot * update cargo.toml * bring back remote test * fix merge stuff * fix npos-voters function sig * remove as much redundant diff as you can * Update frame/staking/src/pallet/mod.rs Co-authored-by: Andronik <write@reusable.software> * fix * Update frame/staking/src/pallet/impls.rs * update lock * fix all tests * review comments * fmt * fix offence bench * clippy * ".git/.scripts/bench-bot.sh" pallet dev pallet_staking Co-authored-by: Andronik <write@reusable.software> Co-authored-by: Ankan <ankan.anurag@gmail.com> Co-authored-by: command-bot <> * bounties calls docs fix (#12909) Co-authored-by: parity-processbot <> * pallet-contracts migration pre-upgrade fix for v8 (#12905) * Only run pre-v8 migration check for versions older than 8 * Logix fix * use custom environment for publishing crates (#12912) * [contracts] Add debug buffer limit + enforcement (#12845) * Add debug buffer limit + enforcement Add debug buffer limit + enforcement * use BoundedVec for the debug buffer * revert schedule (debug buf len limit not needed anymore) * return DispatchError * addressed review comments * frame/remote-externalities: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/rpc: Add previous export Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Fixup some wrong dependencies (#12899) * Fixup some wrong dependencies Dev dependencies should not appear in the feature list. If features are required, they should be directly enabled for the `dev-dependency`. * More fixups * Fix fix * Remove deprecated feature * Make all work properly and nice!! * FMT * Fix formatting * add numerator and denominator to Rational128 Debug impl and increase precision of float representation (#12914) * Fix state-db pinning (#12927) * Pin all canonicalized blocks * Added a test * Docs * [ci] add job switcher (#12922) * Use LOG_TARGET in consensus related crates (#12875) * Use shared LOG_TARGET in consensus related crates * Rename target from "afg" to "grandpa" Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Vlad <vladimir@parity.io> Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Anthony Alaribe <anthonyalaribe@gmail.com> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com> Co-authored-by: tgmichel <telmo@purestake.com> Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> Co-authored-by: Luke Schoen <ltfschoen@users.noreply.github.com> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com> Co-authored-by: Andronik <write@reusable.software> Co-authored-by: Ankan <ankan.anurag@gmail.com> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: Dino Pačandi <3002868+Dinonard@users.noreply.github.com> Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> Co-authored-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Co-authored-by: Davide Galassi <davxy@datawok.net> * Revert "Lexnv/kiz revamp try runtime stuff (#12932)" This reverts commit 378cfb26d984bcde467781f07ef8ddb6998212cb. * fmt * update * fix publish Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Vlad <vladimir@parity.io> Co-authored-by: Anthony Alaribe <anthonyalaribe@gmail.com> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Robert Klotzner <eskimor@users.noreply.github.com> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com> Co-authored-by: tgmichel <telmo@purestake.com> Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> Co-authored-by: Luke Schoen <ltfschoen@users.noreply.github.com> Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com> Co-authored-by: Andronik <write@reusable.software> Co-authored-by: Ankan <ankan.anurag@gmail.com> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: Dino Pačandi <3002868+Dinonard@users.noreply.github.com> Co-authored-by: João Paulo Silva de Souza <77391175+joao-paulo-parity@users.noreply.github.com> Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Co-authored-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Davide Galassi <davxy@datawok.net>
3696 lines
115 KiB
Rust
3696 lines
115 KiB
Rust
// This file is part of Substrate.
|
|
|
|
// Copyright (C) 2017-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.
|
|
|
|
//! 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, GetCallMetadata, GetCallName, GetStorageVersion, UnfilteredDispatchable,
|
|
},
|
|
};
|
|
#[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`
|
|
/// returned from a dispatch.
|
|
pub type DispatchResultWithPostInfo = sp_runtime::DispatchResultWithInfo<PostDispatchInfo>;
|
|
|
|
/// Unaugmented version of `DispatchResultWithPostInfo` that can be returned from
|
|
/// dispatchable functions and is automatically converted to the augmented type. Should be
|
|
/// used whenever the `PostDispatchInfo` does not need to be overwritten. As this should
|
|
/// be the common case it is the implicit return type when none is specified.
|
|
pub type DispatchResult = Result<(), sp_runtime::DispatchError>;
|
|
|
|
/// The error type contained in a `DispatchResultWithPostInfo`.
|
|
pub type DispatchErrorWithPostInfo = sp_runtime::DispatchErrorWithPostInfo<PostDispatchInfo>;
|
|
|
|
/// Serializable version of pallet dispatchable.
|
|
pub trait Callable<T> {
|
|
type RuntimeCall: UnfilteredDispatchable + Codec + Clone + PartialEq + Eq;
|
|
}
|
|
|
|
// dirty hack to work around serde_derive issue
|
|
// https://github.com/rust-lang/rust/issues/51331
|
|
pub type CallableCallFor<A, R> = <A as Callable<R>>::RuntimeCall;
|
|
|
|
/// Origin for the System pallet.
|
|
#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
|
|
pub enum RawOrigin<AccountId> {
|
|
/// The system itself ordained this dispatch to happen: this is the highest privilege level.
|
|
Root,
|
|
/// It is signed by some public key and we provide the `AccountId`.
|
|
Signed(AccountId),
|
|
/// It is signed by nobody, can be either:
|
|
/// * included and agreed upon by the validators anyway,
|
|
/// * or unsigned transaction validated by a pallet.
|
|
None,
|
|
}
|
|
|
|
impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
|
|
fn from(s: Option<AccountId>) -> RawOrigin<AccountId> {
|
|
match s {
|
|
Some(who) => RawOrigin::Signed(who),
|
|
None => RawOrigin::None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A type that can be used as a parameter in a dispatchable function.
|
|
///
|
|
/// When using `decl_module` all arguments for call functions must implement this trait.
|
|
pub trait Parameter: Codec + EncodeLike + Clone + Eq + fmt::Debug + scale_info::TypeInfo {}
|
|
impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug + scale_info::TypeInfo {}
|
|
|
|
/// Means of classifying a dispatchable function.
|
|
pub trait ClassifyDispatch<T> {
|
|
/// Classify the dispatch function based on input data `target` of type `T`. When implementing
|
|
/// this for a dispatchable, `T` will be a tuple of all arguments given to the function (except
|
|
/// origin).
|
|
fn classify_dispatch(&self, target: T) -> DispatchClass;
|
|
}
|
|
|
|
/// Indicates if dispatch function should pay fees or not.
|
|
///
|
|
/// If set to `Pays::No`, the block resource limits are applied, yet no fee is deducted.
|
|
pub trait PaysFee<T> {
|
|
fn pays_fee(&self, _target: T) -> Pays;
|
|
}
|
|
|
|
/// Explicit enum to denote if a transaction pays fee or not.
|
|
#[derive(Clone, Copy, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
|
|
pub enum Pays {
|
|
/// Transactor will pay related fees.
|
|
Yes,
|
|
/// Transactor will NOT pay related fees.
|
|
No,
|
|
}
|
|
|
|
impl Default for Pays {
|
|
fn default() -> Self {
|
|
Self::Yes
|
|
}
|
|
}
|
|
|
|
impl From<Pays> for PostDispatchInfo {
|
|
fn from(pays_fee: Pays) -> Self {
|
|
Self { actual_weight: None, pays_fee }
|
|
}
|
|
}
|
|
|
|
/// A generalized group of dispatch types.
|
|
///
|
|
/// NOTE whenever upgrading the enum make sure to also update
|
|
/// [DispatchClass::all] and [DispatchClass::non_mandatory] helper functions.
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
|
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)]
|
|
pub enum DispatchClass {
|
|
/// A normal dispatch.
|
|
Normal,
|
|
/// An operational dispatch.
|
|
Operational,
|
|
/// A mandatory dispatch. These kinds of dispatch are always included regardless of their
|
|
/// weight, therefore it is critical that they are separately validated to ensure that a
|
|
/// malicious validator cannot craft a valid but impossibly heavy block. Usually this just
|
|
/// means ensuring that the extrinsic can only be included once and that it is always very
|
|
/// light.
|
|
///
|
|
/// Do *NOT* use it for extrinsics that can be heavy.
|
|
///
|
|
/// The only real use case for this is inherent extrinsics that are required to execute in a
|
|
/// block for the block to be valid, and it solves the issue in the case that the block
|
|
/// initialization is sufficiently heavy to mean that those inherents do not fit into the
|
|
/// block. Essentially, we assume that in these exceptional circumstances, it is better to
|
|
/// allow an overweight block to be created than to not allow any block at all to be created.
|
|
Mandatory,
|
|
}
|
|
|
|
impl Default for DispatchClass {
|
|
fn default() -> Self {
|
|
Self::Normal
|
|
}
|
|
}
|
|
|
|
impl DispatchClass {
|
|
/// Returns an array containing all dispatch classes.
|
|
pub fn all() -> &'static [DispatchClass] {
|
|
&[DispatchClass::Normal, DispatchClass::Operational, DispatchClass::Mandatory]
|
|
}
|
|
|
|
/// Returns an array of all dispatch classes except `Mandatory`.
|
|
pub fn non_mandatory() -> &'static [DispatchClass] {
|
|
&[DispatchClass::Normal, DispatchClass::Operational]
|
|
}
|
|
}
|
|
|
|
/// A trait that represents one or many values of given type.
|
|
///
|
|
/// Useful to accept as parameter type to let the caller pass either a single value directly
|
|
/// or an iterator.
|
|
pub trait OneOrMany<T> {
|
|
/// The iterator type.
|
|
type Iter: Iterator<Item = T>;
|
|
/// Convert this item into an iterator.
|
|
fn into_iter(self) -> Self::Iter;
|
|
}
|
|
|
|
impl OneOrMany<DispatchClass> for DispatchClass {
|
|
type Iter = sp_std::iter::Once<DispatchClass>;
|
|
fn into_iter(self) -> Self::Iter {
|
|
sp_std::iter::once(self)
|
|
}
|
|
}
|
|
|
|
impl<'a> OneOrMany<DispatchClass> for &'a [DispatchClass] {
|
|
type Iter = sp_std::iter::Cloned<sp_std::slice::Iter<'a, DispatchClass>>;
|
|
fn into_iter(self) -> Self::Iter {
|
|
self.iter().cloned()
|
|
}
|
|
}
|
|
|
|
/// A bundle of static information collected from the `#[pallet::weight]` attributes.
|
|
#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
|
|
pub struct DispatchInfo {
|
|
/// Weight of this transaction.
|
|
pub weight: Weight,
|
|
/// Class of this transaction.
|
|
pub class: DispatchClass,
|
|
/// Does this transaction pay fees.
|
|
pub pays_fee: Pays,
|
|
}
|
|
|
|
/// A `Dispatchable` function (aka transaction) that can carry some static information along with
|
|
/// it, using the `#[pallet::weight]` attribute.
|
|
pub trait GetDispatchInfo {
|
|
/// Return a `DispatchInfo`, containing relevant information of this dispatch.
|
|
///
|
|
/// This is done independently of its encoded size.
|
|
fn get_dispatch_info(&self) -> DispatchInfo;
|
|
}
|
|
|
|
impl GetDispatchInfo for () {
|
|
fn get_dispatch_info(&self) -> DispatchInfo {
|
|
DispatchInfo::default()
|
|
}
|
|
}
|
|
|
|
/// Extract the actual weight from a dispatch result if any or fall back to the default weight.
|
|
pub fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Weight {
|
|
match result {
|
|
Ok(post_info) => post_info,
|
|
Err(err) => &err.post_info,
|
|
}
|
|
.calc_actual_weight(info)
|
|
}
|
|
|
|
/// Extract the actual pays_fee from a dispatch result if any or fall back to the default weight.
|
|
pub fn extract_actual_pays_fee(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Pays {
|
|
match result {
|
|
Ok(post_info) => post_info,
|
|
Err(err) => &err.post_info,
|
|
}
|
|
.pays_fee(info)
|
|
}
|
|
|
|
/// Weight information that is only available post dispatch.
|
|
/// NOTE: This can only be used to reduce the weight or fee, not increase it.
|
|
#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
|
|
pub struct PostDispatchInfo {
|
|
/// Actual weight consumed by a call or `None` which stands for the worst case static weight.
|
|
pub actual_weight: Option<Weight>,
|
|
/// Whether this transaction should pay fees when all is said and done.
|
|
pub pays_fee: Pays,
|
|
}
|
|
|
|
impl PostDispatchInfo {
|
|
/// Calculate how much (if any) weight was not used by the `Dispatchable`.
|
|
pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight {
|
|
info.weight - self.calc_actual_weight(info)
|
|
}
|
|
|
|
/// Calculate how much weight was actually spent by the `Dispatchable`.
|
|
pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight {
|
|
if let Some(actual_weight) = self.actual_weight {
|
|
actual_weight.min(info.weight)
|
|
} else {
|
|
info.weight
|
|
}
|
|
}
|
|
|
|
/// Determine if user should actually pay fees at the end of the dispatch.
|
|
pub fn pays_fee(&self, info: &DispatchInfo) -> Pays {
|
|
// If they originally were not paying fees, or the post dispatch info
|
|
// says they should not pay fees, then they don't pay fees.
|
|
// This is because the pre dispatch information must contain the
|
|
// worst case for weight and fees paid.
|
|
if info.pays_fee == Pays::No || self.pays_fee == Pays::No {
|
|
Pays::No
|
|
} else {
|
|
// Otherwise they pay.
|
|
Pays::Yes
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<()> for PostDispatchInfo {
|
|
fn from(_: ()) -> Self {
|
|
Self { actual_weight: None, pays_fee: Default::default() }
|
|
}
|
|
}
|
|
|
|
impl sp_runtime::traits::Printable for PostDispatchInfo {
|
|
fn print(&self) {
|
|
"actual_weight=".print();
|
|
match self.actual_weight {
|
|
Some(weight) => weight.print(),
|
|
None => "max-weight".print(),
|
|
};
|
|
"pays_fee=".print();
|
|
match self.pays_fee {
|
|
Pays::Yes => "Yes".print(),
|
|
Pays::No => "No".print(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Allows easy conversion from `DispatchError` to `DispatchErrorWithPostInfo` for dispatchables
|
|
/// that want to return a custom a posterior weight on error.
|
|
pub trait WithPostDispatchInfo {
|
|
/// Call this on your modules custom errors type in order to return a custom weight on error.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```ignore
|
|
/// let who = ensure_signed(origin).map_err(|e| e.with_weight(Weight::from_ref_time(100)))?;
|
|
/// ensure!(who == me, Error::<T>::NotMe.with_weight(200_000));
|
|
/// ```
|
|
fn with_weight(self, actual_weight: Weight) -> DispatchErrorWithPostInfo;
|
|
}
|
|
|
|
impl<T> WithPostDispatchInfo for T
|
|
where
|
|
T: Into<DispatchError>,
|
|
{
|
|
fn with_weight(self, actual_weight: Weight) -> DispatchErrorWithPostInfo {
|
|
DispatchErrorWithPostInfo {
|
|
post_info: PostDispatchInfo {
|
|
actual_weight: Some(actual_weight),
|
|
pays_fee: Default::default(),
|
|
},
|
|
error: self.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Implementation for unchecked extrinsic.
|
|
impl<Address, Call, Signature, Extra> GetDispatchInfo
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Call: GetDispatchInfo,
|
|
Extra: SignedExtension,
|
|
{
|
|
fn get_dispatch_info(&self) -> DispatchInfo {
|
|
self.function.get_dispatch_info()
|
|
}
|
|
}
|
|
|
|
/// Implementation for checked extrinsic.
|
|
impl<AccountId, Call, Extra> GetDispatchInfo for CheckedExtrinsic<AccountId, Call, Extra>
|
|
where
|
|
Call: GetDispatchInfo,
|
|
{
|
|
fn get_dispatch_info(&self) -> DispatchInfo {
|
|
self.function.get_dispatch_info()
|
|
}
|
|
}
|
|
|
|
/// Implementation for test extrinsic.
|
|
#[cfg(feature = "std")]
|
|
impl<Call: Encode + GetDispatchInfo, Extra: Encode> GetDispatchInfo
|
|
for sp_runtime::testing::TestXt<Call, Extra>
|
|
{
|
|
fn get_dispatch_info(&self) -> DispatchInfo {
|
|
// for testing: weight == size.
|
|
DispatchInfo {
|
|
weight: Weight::from_ref_time(self.encode().len() as _),
|
|
pays_fee: Pays::Yes,
|
|
class: self.call.get_dispatch_info().class,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A struct holding value for each `DispatchClass`.
|
|
#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
|
|
pub struct PerDispatchClass<T> {
|
|
/// Value for `Normal` extrinsics.
|
|
normal: T,
|
|
/// Value for `Operational` extrinsics.
|
|
operational: T,
|
|
/// Value for `Mandatory` extrinsics.
|
|
mandatory: T,
|
|
}
|
|
|
|
impl<T> PerDispatchClass<T> {
|
|
/// Create new `PerDispatchClass` with the same value for every class.
|
|
pub fn new(val: impl Fn(DispatchClass) -> T) -> Self {
|
|
Self {
|
|
normal: val(DispatchClass::Normal),
|
|
operational: val(DispatchClass::Operational),
|
|
mandatory: val(DispatchClass::Mandatory),
|
|
}
|
|
}
|
|
|
|
/// Get a mutable reference to current value of given class.
|
|
pub fn get_mut(&mut self, class: DispatchClass) -> &mut T {
|
|
match class {
|
|
DispatchClass::Operational => &mut self.operational,
|
|
DispatchClass::Normal => &mut self.normal,
|
|
DispatchClass::Mandatory => &mut self.mandatory,
|
|
}
|
|
}
|
|
|
|
/// Get current value for given class.
|
|
pub fn get(&self, class: DispatchClass) -> &T {
|
|
match class {
|
|
DispatchClass::Normal => &self.normal,
|
|
DispatchClass::Operational => &self.operational,
|
|
DispatchClass::Mandatory => &self.mandatory,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: Clone> PerDispatchClass<T> {
|
|
/// Set the value of given class.
|
|
pub fn set(&mut self, new: T, class: impl OneOrMany<DispatchClass>) {
|
|
for class in class.into_iter() {
|
|
*self.get_mut(class) = new.clone();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PerDispatchClass<Weight> {
|
|
/// Returns the total weight consumed by all extrinsics in the block.
|
|
pub fn total(&self) -> Weight {
|
|
let mut sum = Weight::zero();
|
|
for class in DispatchClass::all() {
|
|
sum = sum.saturating_add(*self.get(*class));
|
|
}
|
|
sum
|
|
}
|
|
|
|
/// Add some weight of a specific dispatch class, saturating at the numeric bounds of `Weight`.
|
|
pub fn add(&mut self, weight: Weight, class: DispatchClass) {
|
|
let value = self.get_mut(class);
|
|
*value = value.saturating_add(weight);
|
|
}
|
|
|
|
/// Try to add some weight of a specific dispatch class, returning Err(()) if overflow would
|
|
/// occur.
|
|
pub fn checked_add(&mut self, weight: Weight, class: DispatchClass) -> Result<(), ()> {
|
|
let value = self.get_mut(class);
|
|
*value = value.checked_add(&weight).ok_or(())?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Subtract some weight of a specific dispatch class, saturating at the numeric bounds of
|
|
/// `Weight`.
|
|
pub fn sub(&mut self, weight: Weight, class: DispatchClass) {
|
|
let value = self.get_mut(class);
|
|
*value = value.saturating_sub(weight);
|
|
}
|
|
}
|
|
|
|
/// Means of weighing some particular kind of data (`T`).
|
|
pub trait WeighData<T> {
|
|
/// Weigh the data `T` given by `target`. When implementing this for a dispatchable, `T` will be
|
|
/// a tuple of all arguments given to the function (except origin).
|
|
fn weigh_data(&self, target: T) -> Weight;
|
|
}
|
|
|
|
impl<T> WeighData<T> for Weight {
|
|
fn weigh_data(&self, _: T) -> Weight {
|
|
return *self
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for (Weight, DispatchClass, Pays) {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
self.2
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for (Weight, DispatchClass) {
|
|
fn weigh_data(&self, args: T) -> Weight {
|
|
return self.0.weigh_data(args)
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for (Weight, DispatchClass, Pays) {
|
|
fn weigh_data(&self, args: T) -> Weight {
|
|
return self.0.weigh_data(args)
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for (Weight, DispatchClass) {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for (Weight, DispatchClass) {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
Pays::Yes
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for (Weight, Pays) {
|
|
fn weigh_data(&self, args: T) -> Weight {
|
|
return self.0.weigh_data(args)
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for (Weight, Pays) {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
DispatchClass::Normal
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for (Weight, Pays) {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
impl From<(Option<Weight>, Pays)> for PostDispatchInfo {
|
|
fn from(post_weight_info: (Option<Weight>, Pays)) -> Self {
|
|
let (actual_weight, pays_fee) = post_weight_info;
|
|
Self { actual_weight, pays_fee }
|
|
}
|
|
}
|
|
|
|
impl From<Option<Weight>> for PostDispatchInfo {
|
|
fn from(actual_weight: Option<Weight>) -> Self {
|
|
Self { actual_weight, pays_fee: Default::default() }
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for Weight {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
DispatchClass::Normal
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for Weight {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
Pays::Yes
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for (Weight, DispatchClass, Pays) {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
// TODO: Eventually remove these
|
|
|
|
impl From<Option<u64>> for PostDispatchInfo {
|
|
fn from(maybe_actual_computation: Option<u64>) -> Self {
|
|
let actual_weight = match maybe_actual_computation {
|
|
Some(actual_computation) => Some(Weight::zero().set_ref_time(actual_computation)),
|
|
None => None,
|
|
};
|
|
Self { actual_weight, pays_fee: Default::default() }
|
|
}
|
|
}
|
|
|
|
impl From<(Option<u64>, Pays)> for PostDispatchInfo {
|
|
fn from(post_weight_info: (Option<u64>, Pays)) -> Self {
|
|
let (maybe_actual_time, pays_fee) = post_weight_info;
|
|
let actual_weight = match maybe_actual_time {
|
|
Some(actual_time) => Some(Weight::zero().set_ref_time(actual_time)),
|
|
None => None,
|
|
};
|
|
Self { actual_weight, pays_fee }
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for u64 {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
DispatchClass::Normal
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for u64 {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
Pays::Yes
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for u64 {
|
|
fn weigh_data(&self, _: T) -> Weight {
|
|
return Weight::zero().set_ref_time(*self)
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for (u64, DispatchClass, Pays) {
|
|
fn weigh_data(&self, args: T) -> Weight {
|
|
return self.0.weigh_data(args)
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for (u64, DispatchClass, Pays) {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for (u64, DispatchClass, Pays) {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
self.2
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for (u64, DispatchClass) {
|
|
fn weigh_data(&self, args: T) -> Weight {
|
|
return self.0.weigh_data(args)
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for (u64, DispatchClass) {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for (u64, DispatchClass) {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
Pays::Yes
|
|
}
|
|
}
|
|
|
|
impl<T> WeighData<T> for (u64, Pays) {
|
|
fn weigh_data(&self, args: T) -> Weight {
|
|
return self.0.weigh_data(args)
|
|
}
|
|
}
|
|
|
|
impl<T> ClassifyDispatch<T> for (u64, Pays) {
|
|
fn classify_dispatch(&self, _: T) -> DispatchClass {
|
|
DispatchClass::Normal
|
|
}
|
|
}
|
|
|
|
impl<T> PaysFee<T> for (u64, Pays) {
|
|
fn pays_fee(&self, _: T) -> Pays {
|
|
self.1
|
|
}
|
|
}
|
|
|
|
// END TODO
|
|
|
|
/// Declares a `Module` struct and a `Call` enum, which implements the dispatch logic.
|
|
///
|
|
/// ## Declaration
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::{Config, ensure_signed};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {
|
|
///
|
|
/// // Private functions are dispatchable, but not available to other
|
|
/// // FRAME pallets.
|
|
/// #[weight = 0]
|
|
/// fn my_function(origin, var: u64) -> dispatch::DispatchResult {
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
///
|
|
/// // Public functions are both dispatchable and available to other
|
|
/// // FRAME pallets.
|
|
/// #[weight = 0]
|
|
/// pub fn my_public_function(origin) -> dispatch::DispatchResult {
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// The declaration is set with the header where:
|
|
///
|
|
/// * `Module`: The struct generated by the macro, with type `Config`.
|
|
/// * `Call`: The enum generated for every pallet, which implements
|
|
/// [`Callable`](./dispatch/trait.Callable.html).
|
|
/// * `origin`: Alias of `T::RuntimeOrigin`.
|
|
/// * `Result`: The expected return type from pallet functions.
|
|
///
|
|
/// The first parameter of dispatchable functions must always be `origin`.
|
|
///
|
|
/// ### Shorthand Example
|
|
///
|
|
/// The macro automatically expands a shorthand function declaration to return the
|
|
/// [`DispatchResult`] type. These functions are the same:
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::{Config, ensure_signed};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {
|
|
/// #[weight = 0]
|
|
/// fn my_long_function(origin) -> dispatch::DispatchResult {
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
///
|
|
/// #[weight = 0]
|
|
/// fn my_short_function(origin) {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ### Consuming only portions of the annotated static weight
|
|
///
|
|
/// Per default a callable function consumes all of its static weight as declared via
|
|
/// the #\[weight\] attribute. However, there are use cases where only a portion of this
|
|
/// weight should be consumed. In that case the static weight is charged pre dispatch and
|
|
/// the difference is refunded post dispatch.
|
|
///
|
|
/// In order to make use of this feature the function must return `DispatchResultWithPostInfo`
|
|
/// in place of the default `DispatchResult`. Then the actually consumed weight can be returned.
|
|
/// To consume a non default weight while returning an error
|
|
/// [`WithPostDispatchInfo::with_weight`](./weight/trait.WithPostDispatchInfo.html) can be used
|
|
/// to augment any error with custom weight information.
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::{weights::Weight, dispatch::{DispatchResultWithPostInfo, WithPostDispatchInfo}};
|
|
/// # use frame_system::{Config, ensure_signed};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {
|
|
/// #[weight = 1_000_000]
|
|
/// fn my_long_function(origin, do_expensive_calc: bool) -> DispatchResultWithPostInfo {
|
|
/// ensure_signed(origin).map_err(|e| e.with_weight(Weight::from_ref_time(100_000)))?;
|
|
/// if do_expensive_calc {
|
|
/// // do the expensive calculation
|
|
/// // ...
|
|
/// // return None to indicate that we are using all weight (the default)
|
|
/// return Ok(None::<Weight>.into());
|
|
/// }
|
|
/// // expensive calculation not executed: use only a portion of the weight
|
|
/// Ok(Some(100_000).into())
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ### Transactional Function Example
|
|
///
|
|
/// Transactional function discards all changes to storage if it returns `Err`, or commits if
|
|
/// `Ok`, via the #\[transactional\] attribute. Note the attribute must be after #\[weight\].
|
|
/// The #\[transactional\] attribute is deprecated since it is the default behaviour.
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::transactional;
|
|
/// # use frame_system::Config;
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {
|
|
/// #[weight = 0]
|
|
/// #[transactional]
|
|
/// fn my_short_function(origin) {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ### Privileged Function Example
|
|
///
|
|
/// A privileged function checks that the origin of the call is `ROOT`.
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::{Config, ensure_signed, ensure_root};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {
|
|
/// #[weight = 0]
|
|
/// fn my_privileged_function(origin) -> dispatch::DispatchResult {
|
|
/// ensure_root(origin)?;
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ### Attributes on Functions
|
|
///
|
|
/// Attributes on functions are supported, but must be in the order of:
|
|
/// 1. Optional #\[doc\] attribute.
|
|
/// 2. #\[weight\] attribute.
|
|
/// 3. Optional function attributes, for instance #\[transactional\]. Those function attributes will
|
|
/// be written only on the dispatchable functions implemented on `Module`, not on the `Call` enum
|
|
/// variant.
|
|
///
|
|
/// ## Multiple Module Instances Example
|
|
///
|
|
/// A Substrate module can be built such that multiple instances of the same module can be used
|
|
/// within a single runtime. For example, the [Balances module](../pallet_balances/index.html) can
|
|
/// be added multiple times to your runtime in order to support multiple, independent currencies for
|
|
/// your blockchain. Here is an example of how you would declare such a module using the
|
|
/// `decl_module!` macro:
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::ensure_signed;
|
|
/// # pub struct DefaultInstance;
|
|
/// # pub trait Instance: 'static {}
|
|
/// # impl Instance for DefaultInstance {}
|
|
/// pub trait Config<I: Instance=DefaultInstance>: frame_system::Config {}
|
|
///
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config<I>, I: Instance = DefaultInstance> for enum Call where origin: T::RuntimeOrigin {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// Note: `decl_storage` must be called to generate `Instance` trait and optionally
|
|
/// `DefaultInstance` type.
|
|
///
|
|
/// ## Where clause
|
|
///
|
|
/// Besides the default `origin: T::RuntimeOrigin`, you can also pass other bounds to the module
|
|
/// declaration. This where bound will be replicated to all types generated by this macro. The
|
|
/// chaining of multiple trait bounds with `+` is not supported. If multiple bounds for one type are
|
|
/// required, it needs to be split up into multiple bounds.
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::{self as system, ensure_signed};
|
|
/// pub trait Config: system::Config where Self::AccountId: From<u32> {}
|
|
///
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin, T::AccountId: From<u32> {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ## Reserved Functions
|
|
///
|
|
/// The following are reserved function signatures:
|
|
///
|
|
/// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.io/main-docs/build/events-errors/).
|
|
/// The default behavior is to call `deposit_event` from the [System
|
|
/// module](../frame_system/index.html). However, you can write your own implementation for events
|
|
/// in your runtime. To use the default behavior, add `fn deposit_event() = default;` to your
|
|
/// `Module`.
|
|
///
|
|
/// The following reserved functions also take the block number (with type `T::BlockNumber`) as an
|
|
/// optional input:
|
|
///
|
|
/// * `on_runtime_upgrade`: Executes at the beginning of a block prior to on_initialize when there
|
|
/// is a runtime upgrade. This allows each module to upgrade its storage before the storage items
|
|
/// are used. As such, **calling other modules must be avoided**!! Using this function will
|
|
/// implement the [`OnRuntimeUpgrade`](../sp_runtime/traits/trait.OnRuntimeUpgrade.html) trait.
|
|
/// Function signature must be `fn on_runtime_upgrade() -> frame_support::weights::Weight`.
|
|
///
|
|
/// * `on_initialize`: Executes at the beginning of a block. Using this function will
|
|
/// implement the [`OnInitialize`](./trait.OnInitialize.html) trait.
|
|
/// Function signature can be either:
|
|
/// * `fn on_initialize(n: BlockNumber) -> frame_support::weights::Weight` or
|
|
/// * `fn on_initialize() -> frame_support::weights::Weight`
|
|
///
|
|
/// * `on_idle`: Executes at the end of a block. Passes a remaining weight to provide a threshold
|
|
/// for when to execute non vital functions. Using this function will implement the
|
|
/// [`OnIdle`](./traits/trait.OnIdle.html) trait.
|
|
/// Function signature is:
|
|
/// * `fn on_idle(n: BlockNumber, remaining_weight: Weight) -> frame_support::weights::Weight`
|
|
///
|
|
/// * `on_finalize`: Executes at the end of a block. Using this function will
|
|
/// implement the [`OnFinalize`](./traits/trait.OnFinalize.html) trait.
|
|
/// Function signature can be either:
|
|
/// * `fn on_finalize(n: BlockNumber) -> frame_support::weights::Weight` or
|
|
/// * `fn on_finalize() -> frame_support::weights::Weight`
|
|
///
|
|
/// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future
|
|
/// block upon completion. Using this function will implement the
|
|
/// [`OffchainWorker`](./traits/trait.OffchainWorker.html) trait.
|
|
/// * `integrity_test`: Executes in a test generated by `construct_runtime`, note it doesn't execute
|
|
/// in an externalities-provided environment. Implement
|
|
/// [`IntegrityTest`](./trait.IntegrityTest.html) trait.
|
|
#[macro_export]
|
|
macro_rules! decl_module {
|
|
// Entry point #1.
|
|
(
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$( <I>, I: $instantiable:path $( = $module_default_instance:path )? )?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty $(, $where_ty:ty: $where_bound:path )* $(,)? {
|
|
$( $t:tt )*
|
|
}
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name $(<I>, I: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = frame_system
|
|
{ $( $where_ty: $where_bound ),* }
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
[]
|
|
$($t)*
|
|
);
|
|
};
|
|
// Entry point #2.
|
|
(
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$( <I>, I: $instantiable:path $( = $module_default_instance:path )? )?
|
|
>
|
|
for enum $call_type:ident where
|
|
origin: $origin_type:ty,
|
|
system = $system:ident
|
|
$(, $where_ty:ty: $where_bound:path )*
|
|
$(,)?
|
|
{
|
|
$($t:tt)*
|
|
}
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name $(<I>, I: $instantiable $( = $module_default_instance )? )?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $where_ty: $where_bound ),* }
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
[]
|
|
$($t)*
|
|
);
|
|
};
|
|
|
|
// Normalization expansions. Fills the defaults.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{}
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn deposit_event() = default;
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $vis fn deposit_event() = default; }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{}
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn deposit_event
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;`"
|
|
);
|
|
};
|
|
// Compile error on `deposit_event` being added a second time.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )+ }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn deposit_event() = default;
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`deposit_event` can only be passed once as input.");
|
|
};
|
|
// Add on_finalize
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{}
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{
|
|
fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* }
|
|
}
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// compile_error on_finalize, given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{}
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_finalize` can't be given weight attribute anymore, weight must be returned by \
|
|
`on_initialize` or `on_runtime_upgrade` instead"
|
|
);
|
|
};
|
|
// Compile error on `on_finalize` being added a second time.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )+ }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`on_finalize` can only be passed once as input.");
|
|
};
|
|
|
|
// Add on_idle
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{}
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_idle($param_name1:ident : $param1:ty, $param_name2:ident: $param2:ty $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{
|
|
fn on_idle( $param_name1: $param1, $param_name2: $param2 ) -> $return { $( $impl )* }
|
|
}
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// compile_error for invalid on_idle function signature in decl_module
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
fn on_idle
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`on_idle` method is reserved and syntax doesn't match expected syntax.");
|
|
};
|
|
|
|
// compile_error on_runtime_upgrade, without a given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{}
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_runtime_upgrade` must return Weight, signature has changed."
|
|
);
|
|
};
|
|
// compile_error on_runtime_upgrade, given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{}
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_runtime_upgrade` can't be given weight attribute anymore, weight must be returned \
|
|
by the function directly."
|
|
);
|
|
};
|
|
// Add on_runtime_upgrade
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{}
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{
|
|
fn on_runtime_upgrade( $( $param_name : $param ),* ) -> $return { $( $impl )* }
|
|
}
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Compile error on `on_runtime_upgrade` being added a second time.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )+ }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`on_runtime_upgrade` can only be passed once as input.");
|
|
};
|
|
// Add integrity_test
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{}
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn integrity_test() { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{
|
|
$(#[doc = $doc_attr])*
|
|
fn integrity_test() { $( $impl)* }
|
|
}
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Compile error on `integrity_test` being added a second time.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )+ }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn integrity_test() { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`integrity_test` can only be passed once as input.");
|
|
};
|
|
// compile_error on_initialize, without a given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{}
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_initialize` must return Weight, signature has changed."
|
|
);
|
|
};
|
|
// compile_error on_initialize, with given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{}
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_initialize` can't be given weight attribute anymore, weight must be returned \
|
|
by the function directly."
|
|
);
|
|
};
|
|
// Add on_initialize
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{}
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{
|
|
fn on_initialize( $( $param_name : $param ),* ) -> $return { $( $impl )* }
|
|
}
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Compile error on trying to add a second `on_initialize`.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )+ }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`on_initialize` can only be passed once as input.");
|
|
};
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn offchain_worker( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Compile error on trying to add a second `offchain_worker`.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )+ }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn offchain_worker( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!("`offchain_worker` can only be passed once as input.");
|
|
};
|
|
// This puts a constant in the parsed constants list.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$( #[doc = $doc_attr:tt] )*
|
|
const $name:ident: $ty:ty = $value:expr;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name
|
|
$( <I>, $instance: $instantiable $(= $module_default_instance)? )?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{
|
|
$( $constants )*
|
|
$( #[doc = $doc_attr ] )*
|
|
$name: $ty = $value;
|
|
}
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
|
|
// Parse error type
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
type Error = $error_type:ty;
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $error_type }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Add default Error if none supplied
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $($t:tt)* ]
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ __NO_ERROR_DEFINED }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
[ $($t)* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
|
|
// Parse storage version
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
type StorageVersion = $storage_version:path;
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test)* }
|
|
{ $storage_version }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
|
|
// This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
$(#[$fn_attr:meta])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$origin:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test)* }
|
|
{ $( $storage_version )* }
|
|
[
|
|
$( $dispatchables )*
|
|
$(#[doc = $doc_attr])*
|
|
#[weight = $weight]
|
|
$(#[$fn_attr])*
|
|
$fn_vis fn $fn_name(
|
|
$origin $( , $(#[$codec_attr])* $param_name : $param )*
|
|
) $( -> $result )* { $( $impl )* }
|
|
{ $($instance: $instantiable)? }
|
|
]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Add #[weight] if none is defined.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[$fn_attr:meta])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$from:ident $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(concat!(
|
|
"Missing weight for ", stringify!($ident),
|
|
". Every dispatchable must have a #[weight] attribute."
|
|
)
|
|
);
|
|
};
|
|
// Ignore any ident which is not `origin` with type `T::RuntimeOrigin`.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
$(#[$fn_attr:meta])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$origin:ident : T::RuntimeOrigin $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"First parameter of dispatch should be marked `origin` only, with no type specified \
|
|
(a bit like `self`)."
|
|
);
|
|
};
|
|
// Ignore any ident which is `origin` but has a type, regardless of the type token itself.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
$(#[$fn_attr:meta])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
origin : $origin:ty $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"First parameter of dispatch should be marked `origin` only, with no type specified \
|
|
(a bit like `self`)."
|
|
);
|
|
};
|
|
// Ignore any function missing `origin` as the first parameter.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
$(#[$fn_attr:meta])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$( $(#[$codec_attr:ident])* $param_name:ident : $param:ty ),* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"Implicit conversion to privileged function has been removed. \
|
|
First parameter of dispatch should be marked `origin`. \
|
|
For root-matching dispatch, also add `ensure_root(origin)?`."
|
|
);
|
|
};
|
|
// Last normalize step. Triggers `@imp` expansion which is the real expansion.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
) => {
|
|
$crate::decl_module!(@imp
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system {
|
|
$( $dispatchables )*
|
|
}
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_idle )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
{ $( $integrity_test )* }
|
|
{ $( $storage_version )* }
|
|
);
|
|
};
|
|
|
|
// Implementation of Call enum's .dispatch() method.
|
|
// TODO: this probably should be a different macro?
|
|
|
|
(@call
|
|
$ignore:ident
|
|
$mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ]
|
|
) => {
|
|
// We execute all dispatchable in a new storage layer, allowing them
|
|
// to return an error at any point, and undoing any storage changes.
|
|
$crate::storage::with_storage_layer(|| {
|
|
<$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $origin $(, $param_name )* ).map(Into::into).map_err(Into::into)
|
|
})
|
|
};
|
|
|
|
// no `deposit_event` function wanted
|
|
(@impl_deposit_event
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path)?>;
|
|
$system:ident;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {};
|
|
|
|
(@impl_deposit_event
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
$system:ident;
|
|
{ $( $other_where_bounds:tt )* }
|
|
$vis:vis fn deposit_event$(<$event_trait_instance:ident $(, $event_instance:ident)?>)?() = default;
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
/// Deposits an event using `frame_system::Pallet::deposit_event`.
|
|
$vis fn deposit_event(
|
|
event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::RuntimeEvent>
|
|
) {
|
|
<$system::Pallet<$trait_instance>>::deposit_event(event.into())
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_initialize
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_initialize() -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnInitialize<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_initialize(_block_number_not_used: <$trait_instance as $system::Config>::BlockNumber) -> $return {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_initialize"));
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_initialize
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_initialize($param:ident : $param_ty:ty) -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnInitialize<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_initialize($param: $param_ty) -> $return {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_initialize"));
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_initialize
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnInitialize<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
};
|
|
|
|
(@impl_try_state_default
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
#[cfg(feature = "try-runtime")]
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::TryState<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn try_state(
|
|
_: <$trait_instance as $system::Config>::BlockNumber,
|
|
_: $crate::traits::TryStateSelect,
|
|
) -> Result<(), &'static str> {
|
|
let pallet_name = <<
|
|
$trait_instance
|
|
as
|
|
$system::Config
|
|
>::PalletInfo as $crate::traits::PalletInfo>::name::<Self>().unwrap_or("<unknown pallet name>");
|
|
$crate::log::debug!(
|
|
target: $crate::LOG_TARGET,
|
|
"⚠️ pallet {} cannot have try-state because it is using decl_module!",
|
|
pallet_name,
|
|
);
|
|
Ok(())
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_runtime_upgrade
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_runtime_upgrade() -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnRuntimeUpgrade
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_runtime_upgrade() -> $return {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade"));
|
|
let pallet_name = <<
|
|
$trait_instance
|
|
as
|
|
$system::Config
|
|
>::PalletInfo as $crate::traits::PalletInfo>::name::<Self>().unwrap_or("<unknown pallet name>");
|
|
|
|
$crate::log::info!(
|
|
target: $crate::LOG_TARGET,
|
|
"⚠️ {} declares internal migrations (which *might* execute). \
|
|
On-chain `{:?}` vs current storage version `{:?}`",
|
|
pallet_name,
|
|
<Self as $crate::traits::GetStorageVersion>::on_chain_storage_version(),
|
|
<Self as $crate::traits::GetStorageVersion>::current_storage_version(),
|
|
);
|
|
|
|
{ $( $impl )* }
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
fn pre_upgrade() -> Result<$crate::sp_std::vec::Vec<u8>, &'static str> {
|
|
Ok($crate::sp_std::vec::Vec::new())
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
fn post_upgrade(_: $crate::sp_std::vec::Vec<u8>) -> Result<(), &'static str> {
|
|
Ok(())
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_runtime_upgrade
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnRuntimeUpgrade
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_runtime_upgrade() -> $crate::dispatch::Weight {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade"));
|
|
let pallet_name = <<
|
|
$trait_instance
|
|
as
|
|
$system::Config
|
|
>::PalletInfo as $crate::traits::PalletInfo>::name::<Self>().unwrap_or("<unknown pallet name>");
|
|
|
|
$crate::log::debug!(
|
|
target: $crate::LOG_TARGET,
|
|
"✅ no migration for {}",
|
|
pallet_name,
|
|
);
|
|
|
|
$crate::dispatch::Weight::zero()
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
fn pre_upgrade() -> Result<$crate::sp_std::vec::Vec<u8>, &'static str> {
|
|
Ok($crate::sp_std::vec::Vec::new())
|
|
}
|
|
|
|
#[cfg(feature = "try-runtime")]
|
|
fn post_upgrade(_: $crate::sp_std::vec::Vec<u8>) -> Result<(), &'static str> {
|
|
Ok(())
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_integrity_test
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn integrity_test() { $( $impl:tt )* }
|
|
) => {
|
|
#[cfg(feature = "std")]
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::IntegrityTest
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
$(#[doc = $doc_attr])*
|
|
fn integrity_test() {
|
|
$( $impl )*
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_integrity_test
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
#[cfg(feature = "std")]
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::IntegrityTest
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
};
|
|
|
|
(@impl_on_finalize
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_finalize() { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnFinalize<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_finalize(_block_number_not_used: <$trait_instance as $system::Config>::BlockNumber) {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_finalize"));
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_finalize
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_finalize($param:ident : $param_ty:ty) { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnFinalize<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_finalize($param: $param_ty) {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_finalize"));
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_finalize
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnFinalize<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
}
|
|
};
|
|
|
|
(@impl_on_idle
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_idle($param1:ident : $param1_ty:ty, $param2:ident: $param2_ty:ty) -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnIdle<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_idle($param1: $param1_ty, $param2: $param2_ty) -> $return {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_idle"));
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_idle
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnIdle<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
}
|
|
};
|
|
|
|
(@impl_offchain
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn offchain_worker() { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OffchainWorker<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn offchain_worker(_block_number_not_used: <$trait_instance as $system::Config>::BlockNumber) { $( $impl )* }
|
|
}
|
|
};
|
|
|
|
(@impl_offchain
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn offchain_worker($param:ident : $param_ty:ty) { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OffchainWorker<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn offchain_worker($param: $param_ty) { $( $impl )* }
|
|
}
|
|
};
|
|
|
|
(@impl_offchain
|
|
{ $system:ident }
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $system::Config + $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OffchainWorker<<$trait_instance as $system::Config>::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
};
|
|
|
|
// Expansion for _origin_ dispatch functions with no return type.
|
|
(@impl_function
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
$origin_ty:ty;
|
|
$ignore:ident;
|
|
$(#[$fn_attr:meta])*
|
|
$vis:vis fn $name:ident (
|
|
$origin:ident $(, $param:ident : $param_ty:ty )*
|
|
) { $( $impl:tt )* }
|
|
) => {
|
|
#[allow(unreachable_code)]
|
|
$(#[$fn_attr])*
|
|
$vis fn $name(
|
|
$origin: $origin_ty $(, $param: $param_ty )*
|
|
) -> $crate::dispatch::DispatchResult {
|
|
$crate::storage::with_storage_layer(|| {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!(stringify!($name)));
|
|
{ $( $impl )* }
|
|
Ok(())
|
|
})
|
|
}
|
|
};
|
|
|
|
// Expansion for _origin_ dispatch functions with explicit return type.
|
|
(@impl_function
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
$origin_ty:ty;
|
|
$ignore:ident;
|
|
$(#[$fn_attr:meta])*
|
|
$vis:vis fn $name:ident (
|
|
$origin:ident $(, $param:ident : $param_ty:ty )*
|
|
) -> $result:ty { $( $impl:tt )* }
|
|
) => {
|
|
$(#[$fn_attr])*
|
|
$vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result {
|
|
$crate::storage::with_storage_layer(|| {
|
|
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!(stringify!($name)));
|
|
$( $impl )*
|
|
})
|
|
}
|
|
};
|
|
|
|
// Declare a `Call` variant parameter that should be encoded `compact`.
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{ $( $current_params:tt )* }
|
|
variant $fn_name:ident;
|
|
$( #[doc = $doc_attr:tt] )*
|
|
#[compact]
|
|
$name:ident : $type:ty;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $generated_variants )* }
|
|
{
|
|
$( $current_params )*
|
|
#[codec(compact)]
|
|
$name: $type,
|
|
}
|
|
variant $fn_name;
|
|
$( #[doc = $doc_attr] )*
|
|
$( $rest )*
|
|
}
|
|
};
|
|
|
|
// Declare a `Call` variant parameter.
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{ $( $current_params:tt )* }
|
|
variant $fn_name:ident;
|
|
$(#[doc = $doc_attr:tt])*
|
|
$name:ident : $type:ty;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $generated_variants )* }
|
|
{
|
|
$( $current_params )*
|
|
$name: $type,
|
|
}
|
|
variant $fn_name;
|
|
$( #[doc = $doc_attr] )*
|
|
$( $rest )*
|
|
}
|
|
};
|
|
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{ $( $current_params:tt )* }
|
|
variant $fn_name:ident;
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(
|
|
variant $next_fn_name:ident;
|
|
$( $rest:tt )*
|
|
)?
|
|
) => {
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{
|
|
$( $generated_variants )*
|
|
#[allow(non_camel_case_types)]
|
|
$(#[doc = $doc_attr])*
|
|
$fn_name {
|
|
$( $current_params )*
|
|
},
|
|
}
|
|
{}
|
|
$(
|
|
variant $next_fn_name;
|
|
$( $rest )*
|
|
)?
|
|
}
|
|
};
|
|
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{}
|
|
) => {
|
|
/// Dispatchable calls.
|
|
///
|
|
/// Each variant of this enum maps to a dispatchable function from the associated module.
|
|
#[derive($crate::codec::Encode, $crate::codec::Decode, $crate::scale_info::TypeInfo)]
|
|
#[scale_info(skip_type_params($trait_instance $(, $instance)?), capture_docs = "always")]
|
|
pub enum $call_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $( = $module_default_instance)?)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
#[codec(skip)]
|
|
__PhantomItem($crate::sp_std::marker::PhantomData<($trait_instance, $($instance)?)>, $crate::Never),
|
|
$( $generated_variants )*
|
|
}
|
|
};
|
|
|
|
// Implementation for `GetStorageVersion`.
|
|
(@impl_get_storage_version
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
$( $storage_version:tt )+
|
|
) => {
|
|
// Implement `GetStorageVersion` for `Pallet`
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::GetStorageVersion
|
|
for $module<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn current_storage_version() -> $crate::traits::StorageVersion {
|
|
$( $storage_version )*
|
|
}
|
|
|
|
fn on_chain_storage_version() -> $crate::traits::StorageVersion {
|
|
$crate::traits::StorageVersion::get::<Self>()
|
|
}
|
|
}
|
|
};
|
|
|
|
// Implementation for `GetStorageVersion` when no storage version is passed.
|
|
(@impl_get_storage_version
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
// Implement `GetStorageVersion` for `Pallet`
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::GetStorageVersion
|
|
for $module<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn current_storage_version() -> $crate::traits::StorageVersion {
|
|
Default::default()
|
|
}
|
|
|
|
fn on_chain_storage_version() -> $crate::traits::StorageVersion {
|
|
$crate::traits::StorageVersion::get::<Self>()
|
|
}
|
|
}
|
|
};
|
|
|
|
// The main macro expansion that actually renders the module code.
|
|
|
|
(@imp
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {
|
|
$(
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
$(#[$fn_attr:meta])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$from:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
{ $($fn_instance:ident: $fn_instantiable:path)? }
|
|
)*
|
|
}
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_idle:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
{ $( $integrity_test:tt )* }
|
|
{ $( $storage_version:tt )* }
|
|
) => {
|
|
$crate::__check_reserved_fn_name! { $( $fn_name )* }
|
|
|
|
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
|
#[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)]
|
|
$( #[$attr] )*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name
|
|
$(<I>, $instance: $instantiable $( = $module_default_instance)?)?
|
|
>($crate::sp_std::marker::PhantomData<($trait_instance, $( $instance)?)>) where
|
|
$( $other_where_bounds )*;
|
|
|
|
/// Type alias to `Module`, to be used by `construct_runtime`.
|
|
#[allow(dead_code)]
|
|
pub type Pallet<$trait_instance $(, $instance $( = $module_default_instance)?)?>
|
|
= $mod_type<$trait_instance $(, $instance)?>;
|
|
|
|
$crate::__create_tt_macro! {
|
|
tt_error_token,
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_initialize
|
|
{ $system }
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_initialize )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_try_state_default
|
|
{ $system }
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_runtime_upgrade
|
|
{ $system }
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_runtime_upgrade )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_finalize
|
|
{ $system }
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_finalize )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_idle
|
|
{ $system }
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_idle )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_offchain
|
|
{ $system }
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $offchain )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_deposit_event
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
$system;
|
|
{ $( $other_where_bounds )* }
|
|
$( $deposit_event )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_integrity_test
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $integrity_test )*
|
|
}
|
|
|
|
/// Can also be called using [`Call`].
|
|
///
|
|
/// [`Call`]: enum.Call.html
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
$(
|
|
$crate::decl_module! {
|
|
@impl_function
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $fn_instance: $fn_instantiable)?>;
|
|
$origin_type;
|
|
$from;
|
|
$(#[doc = $doc_attr])*
|
|
///
|
|
/// NOTE: Calling this function will bypass origin filters.
|
|
$(#[$fn_attr])*
|
|
$fn_vis fn $fn_name (
|
|
$from $(, $param_name : $param )*
|
|
) $( -> $result )* { $( $impl )* }
|
|
}
|
|
)*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{}
|
|
{}
|
|
$(
|
|
variant $fn_name;
|
|
$(#[doc = $doc_attr])*
|
|
$(
|
|
$(#[$codec_attr])*
|
|
$param_name : $param;
|
|
)*
|
|
)*
|
|
}
|
|
|
|
$crate::paste::paste! {
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
|
|
$call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
$(
|
|
#[doc = "Create a call with the variant `" $fn_name "`."]
|
|
pub fn [< new_call_variant_ $fn_name >](
|
|
$( $param_name: $param ),*
|
|
) -> Self {
|
|
Self::$fn_name {
|
|
$( $param_name ),*
|
|
}
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_get_storage_version
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $storage_version )*
|
|
}
|
|
|
|
// Implement weight calculation function for Call
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::GetDispatchInfo
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn get_dispatch_info(&self) -> $crate::dispatch::DispatchInfo {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name { $( ref $param_name ),* } => {
|
|
let __pallet_base_weight = $weight;
|
|
let __pallet_weight = <dyn $crate::dispatch::WeighData<( $( & $param, )* )>>::weigh_data(
|
|
&__pallet_base_weight,
|
|
($( $param_name, )*)
|
|
);
|
|
let __pallet_class = <dyn $crate::dispatch::ClassifyDispatch<( $( & $param, )* )>>::classify_dispatch(
|
|
&__pallet_base_weight,
|
|
($( $param_name, )*)
|
|
);
|
|
let __pallet_pays_fee = <dyn $crate::dispatch::PaysFee<( $( & $param, )* )>>::pays_fee(
|
|
&__pallet_base_weight,
|
|
($( $param_name, )*)
|
|
);
|
|
$crate::dispatch::DispatchInfo {
|
|
weight: __pallet_weight,
|
|
class: __pallet_class,
|
|
pays_fee: __pallet_pays_fee,
|
|
}
|
|
},
|
|
)*
|
|
$call_type::__PhantomItem(_, _) => unreachable!("__PhantomItem should never be used."),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Implement PalletInfoAccess for the module.
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::PalletInfoAccess
|
|
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn index() -> usize {
|
|
<
|
|
<$trait_instance as $system::Config>::PalletInfo as $crate::traits::PalletInfo
|
|
>::index::<Self>()
|
|
.expect("Pallet is part of the runtime because pallet `Config` trait is \
|
|
implemented by the runtime")
|
|
}
|
|
|
|
fn name() -> &'static str {
|
|
<
|
|
<$trait_instance as $system::Config>::PalletInfo as $crate::traits::PalletInfo
|
|
>::name::<Self>()
|
|
.expect("Pallet is part of the runtime because pallet `Config` trait is \
|
|
implemented by the runtime")
|
|
}
|
|
|
|
fn module_name() -> &'static str {
|
|
<
|
|
<$trait_instance as $system::Config>::PalletInfo as $crate::traits::PalletInfo
|
|
>::module_name::<Self>()
|
|
.expect("Pallet is part of the runtime because pallet `Config` trait is \
|
|
implemented by the runtime")
|
|
}
|
|
|
|
fn crate_version() -> $crate::traits::CrateVersion {
|
|
$crate::crate_to_crate_version!()
|
|
}
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::PalletsInfoAccess
|
|
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn count() -> usize { 1 }
|
|
fn infos() -> $crate::sp_std::vec::Vec<$crate::traits::PalletInfoData> {
|
|
use $crate::traits::PalletInfoAccess;
|
|
let item = $crate::traits::PalletInfoData {
|
|
index: Self::index(),
|
|
name: Self::name(),
|
|
module_name: Self::module_name(),
|
|
crate_version: Self::crate_version(),
|
|
};
|
|
vec![item]
|
|
}
|
|
}
|
|
|
|
// Implement GetCallName for the Call.
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::GetCallName
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn get_call_name(&self) -> &'static str {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name { $( ref $param_name ),* } => {
|
|
// Don't generate any warnings for unused variables
|
|
let _ = ( $( $param_name ),* );
|
|
stringify!($fn_name)
|
|
},
|
|
)*
|
|
$call_type::__PhantomItem(_, _) => unreachable!("__PhantomItem should never be used."),
|
|
}
|
|
}
|
|
|
|
fn get_call_names() -> &'static [&'static str] {
|
|
&[
|
|
$(
|
|
stringify!($fn_name),
|
|
)*
|
|
]
|
|
}
|
|
}
|
|
|
|
// Implement `OnGenesis` for `Module`
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::OnGenesis
|
|
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_genesis() {
|
|
let storage_version = <Self as $crate::traits::GetStorageVersion>::current_storage_version();
|
|
storage_version.put::<Self>();
|
|
}
|
|
}
|
|
|
|
// manual implementation of clone/eq/partialeq because using derive erroneously requires
|
|
// clone/eq/partialeq from T.
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Clone
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn clone(&self) -> Self {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name { $( ref $param_name ),* } =>
|
|
$call_type::$fn_name { $( $param_name: (*$param_name).clone() ),* }
|
|
,)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::PartialEq
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn eq(&self, _other: &Self) -> bool {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name { $( ref $param_name ),* } => {
|
|
let self_params = ( $( $param_name, )* );
|
|
if let $call_type::$fn_name { $( ref $param_name ),* } = *_other {
|
|
self_params == ( $( $param_name, )* )
|
|
} else {
|
|
match *_other {
|
|
$call_type::__PhantomItem(_, _) => unreachable!(),
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Eq
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::fmt::Debug
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn fmt(
|
|
&self,
|
|
_f: &mut $crate::dispatch::fmt::Formatter,
|
|
) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name { $( ref $param_name ),* } =>
|
|
write!(_f, "{}{:?}",
|
|
stringify!($fn_name),
|
|
( $( $param_name.clone(), )* )
|
|
)
|
|
,)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::UnfilteredDispatchable
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
type RuntimeOrigin = $origin_type;
|
|
fn dispatch_bypass_filter(self, _origin: Self::RuntimeOrigin) -> $crate::dispatch::DispatchResultWithPostInfo {
|
|
match self {
|
|
$(
|
|
$call_type::$fn_name { $( $param_name ),* } => {
|
|
$crate::decl_module!(
|
|
@call
|
|
$from
|
|
$mod_type<$trait_instance $(, $fn_instance)?> $fn_name _origin $system [ $( $param_name ),* ]
|
|
)
|
|
},
|
|
)*
|
|
$call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") },
|
|
}
|
|
}
|
|
}
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Callable<$trait_instance>
|
|
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
type RuntimeCall = $call_type<$trait_instance $(, $instance)?>;
|
|
}
|
|
|
|
$crate::__dispatch_impl_metadata! {
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
|
|
{ $( $other_where_bounds )* }
|
|
$call_type $origin_type
|
|
{
|
|
$(
|
|
$(#[doc = $doc_attr])*
|
|
fn $fn_name($from $(, $(#[$codec_attr])* $param_name : $param )*);
|
|
)*
|
|
}
|
|
}
|
|
$crate::__impl_error_metadata! {
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
|
|
{ $( $other_where_bounds )* }
|
|
$( $error_type )*
|
|
}
|
|
$crate::__impl_module_constants_metadata ! {
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
|
|
{ $( $other_where_bounds )* }
|
|
$( $constants )*
|
|
}
|
|
|
|
$crate::__generate_dummy_part_checker!();
|
|
}
|
|
}
|
|
|
|
/// Implement metadata for dispatch.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __dispatch_impl_metadata {
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$call_type:ident
|
|
$($rest:tt)*
|
|
) => {
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
#[allow(dead_code)]
|
|
pub fn call_functions() -> $crate::metadata::PalletCallMetadata {
|
|
$crate::scale_info::meta_type::<$call_type<$trait_instance $(, $instance)?>>().into()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Implement metadata for pallet error.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __impl_error_metadata {
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
__NO_ERROR_DEFINED
|
|
) => {
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
#[allow(dead_code)]
|
|
pub fn error_metadata() -> Option<$crate::metadata::PalletErrorMetadata> {
|
|
None
|
|
}
|
|
}
|
|
};
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$( $error_type:tt )*
|
|
) => {
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
#[allow(dead_code)]
|
|
pub fn error_metadata() -> Option<$crate::metadata::PalletErrorMetadata> {
|
|
Some($crate::metadata::PalletErrorMetadata {
|
|
ty: $crate::scale_info::meta_type::<$( $error_type )*>()
|
|
})
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Implement metadata for module constants.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __impl_module_constants_metadata {
|
|
// Without instance
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(
|
|
$( #[doc = $doc_attr:tt] )*
|
|
$name:ident: $type:ty = $value:expr;
|
|
)*
|
|
) => {
|
|
$crate::paste::item! {
|
|
$crate::__impl_module_constants_metadata! {
|
|
GENERATE_CODE
|
|
$mod_type<$trait_instance: $trait_name>
|
|
{ $( $other_where_bounds )* }
|
|
$(
|
|
$( #[doc = $doc_attr] )*
|
|
[< $name DefaultByteGetter >]
|
|
$name<$trait_instance: $trait_name>: $type = $value;
|
|
)*
|
|
}
|
|
}
|
|
};
|
|
// With instance
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident<I>, $instance:ident: $instantiable:path>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(
|
|
$( #[doc = $doc_attr:tt] )*
|
|
$name:ident: $type:ty = $value:expr;
|
|
)*
|
|
) => {
|
|
$crate::paste::item! {
|
|
$crate::__impl_module_constants_metadata! {
|
|
GENERATE_CODE
|
|
$mod_type<$trait_instance: $trait_name<I>, $instance: $instantiable>
|
|
{ $( $other_where_bounds )* }
|
|
$(
|
|
$( #[doc = $doc_attr] )*
|
|
[< $name DefaultByteGetter >]
|
|
$name<$trait_instance: $trait_name<I>, $instance: $instantiable>: $type = $value;
|
|
)*
|
|
}
|
|
}
|
|
};
|
|
// Do the code generation
|
|
(GENERATE_CODE
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident $(<I>, $instance:ident: $instantiable:path)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(
|
|
$( #[doc = $doc_attr:tt] )*
|
|
$default_byte_name:ident
|
|
$name:ident<
|
|
$const_trait_instance:ident: $const_trait_name:ident $(
|
|
<I>, $const_instance:ident: $const_instantiable:path
|
|
)*
|
|
>: $type:ty = $value:expr;
|
|
)*
|
|
) => {
|
|
impl<$trait_instance: 'static + $trait_name $(<I>, $instance: $instantiable)?>
|
|
$mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
#[allow(dead_code)]
|
|
pub fn pallet_constants_metadata() -> $crate::sp_std::vec::Vec<$crate::metadata::PalletConstantMetadata> {
|
|
// Create the `ByteGetter`s
|
|
$(
|
|
#[allow(non_upper_case_types)]
|
|
#[allow(non_camel_case_types)]
|
|
struct $default_byte_name<
|
|
$const_trait_instance: $const_trait_name $(
|
|
<I>, $const_instance: $const_instantiable
|
|
)?
|
|
>($crate::dispatch::marker::PhantomData<
|
|
($const_trait_instance, $( $const_instance)?)
|
|
>);
|
|
impl<$const_trait_instance: 'static + $const_trait_name $(
|
|
<I>, $const_instance: $const_instantiable)?
|
|
> $default_byte_name <$const_trait_instance $(, $const_instance)?>
|
|
{
|
|
fn default_byte(&self) -> $crate::dispatch::Vec<u8> {
|
|
let value: $type = $value;
|
|
$crate::dispatch::Encode::encode(&value)
|
|
}
|
|
}
|
|
)*
|
|
$crate::sp_std::vec![
|
|
$(
|
|
$crate::metadata::PalletConstantMetadata {
|
|
name: stringify!($name),
|
|
ty: $crate::scale_info::meta_type::<$type>(),
|
|
value: $default_byte_name::<$const_trait_instance $(, $const_instance)?>(
|
|
Default::default()
|
|
).default_byte(),
|
|
docs: $crate::sp_std::vec![ $( $doc_attr ),* ],
|
|
}
|
|
),*
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __check_reserved_fn_name {
|
|
(deposit_event $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error deposit_event);
|
|
};
|
|
(on_initialize $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_initialize);
|
|
};
|
|
(on_runtime_upgrade $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_runtime_upgrade);
|
|
};
|
|
(on_idle $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_idle);
|
|
};
|
|
(on_finalize $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_finalize);
|
|
};
|
|
(offchain_worker $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error offchain_worker);
|
|
};
|
|
(integrity_test $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error integrity_test);
|
|
};
|
|
($t:ident $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!($( $rest )*);
|
|
};
|
|
() => {};
|
|
(@compile_error $ident:ident) => {
|
|
compile_error!(
|
|
concat!(
|
|
"Invalid call fn name: `",
|
|
stringify!($ident),
|
|
"`, name is reserved and doesn't match expected signature, please refer to ",
|
|
"`decl_module!` documentation to see the appropriate usage, or rename it to an ",
|
|
"unreserved keyword."
|
|
),
|
|
);
|
|
};
|
|
(@compile_error_renamed $ident:ident $new_ident:ident) => {
|
|
compile_error!(
|
|
concat!(
|
|
"`",
|
|
stringify!($ident),
|
|
"` was renamed to `",
|
|
stringify!($new_ident),
|
|
"`. Please rename your function accordingly.",
|
|
),
|
|
);
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
// Do not complain about unused `dispatch` and `dispatch_aux`.
|
|
#[allow(dead_code)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::{
|
|
dispatch::{DispatchClass, DispatchInfo, Pays},
|
|
metadata::*,
|
|
traits::{
|
|
CallerTrait, CrateVersion, Get, GetCallName, IntegrityTest, OnFinalize, OnIdle,
|
|
OnInitialize, OnRuntimeUpgrade, PalletInfo,
|
|
},
|
|
};
|
|
use sp_weights::RuntimeDbWeight;
|
|
|
|
pub trait Config: system::Config + Sized
|
|
where
|
|
Self::AccountId: From<u32>,
|
|
{
|
|
}
|
|
|
|
pub mod system {
|
|
use super::*;
|
|
|
|
pub trait Config: 'static {
|
|
type AccountId;
|
|
type RuntimeCall;
|
|
type BaseCallFilter;
|
|
type RuntimeOrigin: crate::traits::OriginTrait<Call = Self::RuntimeCall>;
|
|
type BlockNumber: Into<u32>;
|
|
type PalletInfo: crate::traits::PalletInfo;
|
|
type DbWeight: Get<RuntimeDbWeight>;
|
|
}
|
|
|
|
pub use super::super::RawOrigin;
|
|
|
|
pub type Origin<T> = RawOrigin<<T as Config>::AccountId>;
|
|
}
|
|
|
|
decl_module! {
|
|
pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin, system = system, T::AccountId: From<u32> {
|
|
/// Hi, this is a comment.
|
|
#[weight = 0]
|
|
fn aux_0(_origin) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = 0]
|
|
fn aux_1(_origin, #[compact] _data: u32,) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = 0]
|
|
fn aux_2(_origin, _data: i32, _data2: String) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = 3]
|
|
fn aux_3(_origin) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = 0]
|
|
fn aux_4(_origin, _data: i32) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = 0]
|
|
fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = (5, DispatchClass::Operational)]
|
|
fn operational(_origin) { unreachable!() }
|
|
|
|
fn on_initialize(n: T::BlockNumber,) -> Weight { if n.into() == 42 { panic!("on_initialize") } Weight::from_ref_time(7) }
|
|
fn on_idle(n: T::BlockNumber, remaining_weight: Weight,) -> Weight {
|
|
if n.into() == 42 || remaining_weight == Weight::from_ref_time(42) { panic!("on_idle") }
|
|
Weight::from_ref_time(7)
|
|
}
|
|
fn on_finalize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_finalize") } }
|
|
fn on_runtime_upgrade() -> Weight { Weight::from_ref_time(10) }
|
|
fn offchain_worker() {}
|
|
/// Some doc
|
|
fn integrity_test() { panic!("integrity_test") }
|
|
}
|
|
}
|
|
|
|
#[derive(Eq, PartialEq, Clone, crate::RuntimeDebug, scale_info::TypeInfo)]
|
|
pub struct TraitImpl {}
|
|
impl Config for TraitImpl {}
|
|
|
|
type Test = Module<TraitImpl>;
|
|
|
|
impl PalletInfo for TraitImpl {
|
|
fn index<P: 'static>() -> Option<usize> {
|
|
let type_id = sp_std::any::TypeId::of::<P>();
|
|
if type_id == sp_std::any::TypeId::of::<Test>() {
|
|
return Some(0)
|
|
}
|
|
|
|
None
|
|
}
|
|
fn name<P: 'static>() -> Option<&'static str> {
|
|
let type_id = sp_std::any::TypeId::of::<P>();
|
|
if type_id == sp_std::any::TypeId::of::<Test>() {
|
|
return Some("Test")
|
|
}
|
|
|
|
None
|
|
}
|
|
fn module_name<P: 'static>() -> Option<&'static str> {
|
|
let type_id = sp_std::any::TypeId::of::<P>();
|
|
if type_id == sp_std::any::TypeId::of::<Test>() {
|
|
return Some("tests")
|
|
}
|
|
|
|
None
|
|
}
|
|
fn crate_version<P: 'static>() -> Option<CrateVersion> {
|
|
let type_id = sp_std::any::TypeId::of::<P>();
|
|
if type_id == sp_std::any::TypeId::of::<Test>() {
|
|
return Some(frame_support::crate_to_crate_version!())
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|
|
|
|
#[derive(
|
|
TypeInfo, crate::RuntimeDebug, Eq, PartialEq, Clone, Encode, Decode, MaxEncodedLen,
|
|
)]
|
|
pub struct OuterOrigin;
|
|
|
|
impl From<RawOrigin<<TraitImpl as system::Config>::AccountId>> for OuterOrigin {
|
|
fn from(_: RawOrigin<<TraitImpl as system::Config>::AccountId>) -> Self {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
}
|
|
|
|
impl CallerTrait<<TraitImpl as system::Config>::AccountId> for OuterOrigin {
|
|
fn into_system(self) -> Option<RawOrigin<<TraitImpl as system::Config>::AccountId>> {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn as_system_ref(&self) -> Option<&RawOrigin<<TraitImpl as system::Config>::AccountId>> {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
}
|
|
|
|
impl crate::traits::OriginTrait for OuterOrigin {
|
|
type Call = <TraitImpl as system::Config>::RuntimeCall;
|
|
type PalletsOrigin = OuterOrigin;
|
|
type AccountId = <TraitImpl as system::Config>::AccountId;
|
|
|
|
fn add_filter(&mut self, _filter: impl Fn(&Self::Call) -> bool + 'static) {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn reset_filter(&mut self) {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn set_caller_from(&mut self, _other: impl Into<Self>) {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn filter_call(&self, _call: &Self::Call) -> bool {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn caller(&self) -> &Self::PalletsOrigin {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn into_caller(self) -> Self::PalletsOrigin {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn try_with_caller<R>(
|
|
self,
|
|
_f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
|
|
) -> Result<R, Self> {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
|
|
fn none() -> Self {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
fn root() -> Self {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
fn signed(_by: <TraitImpl as system::Config>::AccountId) -> Self {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
fn as_signed(self) -> Option<Self::AccountId> {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
fn as_system_ref(&self) -> Option<&RawOrigin<Self::AccountId>> {
|
|
unimplemented!("Not required in tests!")
|
|
}
|
|
}
|
|
|
|
impl system::Config for TraitImpl {
|
|
type RuntimeOrigin = OuterOrigin;
|
|
type AccountId = u32;
|
|
type RuntimeCall = ();
|
|
type BaseCallFilter = frame_support::traits::Everything;
|
|
type BlockNumber = u32;
|
|
type PalletInfo = Self;
|
|
type DbWeight = ();
|
|
}
|
|
|
|
#[test]
|
|
fn module_json_metadata() {
|
|
let metadata = Module::<TraitImpl>::call_functions();
|
|
let expected_metadata =
|
|
PalletCallMetadata { ty: scale_info::meta_type::<Call<TraitImpl>>() };
|
|
assert_eq!(expected_metadata, metadata);
|
|
}
|
|
|
|
#[test]
|
|
fn compact_attr() {
|
|
let call: Call<TraitImpl> = Call::aux_1 { _data: 1 };
|
|
let encoded = call.encode();
|
|
assert_eq!(2, encoded.len());
|
|
assert_eq!(vec![1, 4], encoded);
|
|
|
|
let call: Call<TraitImpl> = Call::aux_5 { _data: 1, _data2: 2 };
|
|
let encoded = call.encode();
|
|
assert_eq!(6, encoded.len());
|
|
assert_eq!(vec![5, 1, 0, 0, 0, 8], encoded);
|
|
}
|
|
|
|
#[test]
|
|
fn encode_is_correct_and_decode_works() {
|
|
let call: Call<TraitImpl> = Call::aux_0 {};
|
|
let encoded = call.encode();
|
|
assert_eq!(vec![0], encoded);
|
|
let decoded = Call::<TraitImpl>::decode(&mut &encoded[..]).unwrap();
|
|
assert_eq!(decoded, call);
|
|
|
|
let call: Call<TraitImpl> = Call::aux_2 { _data: 32, _data2: "hello".into() };
|
|
let encoded = call.encode();
|
|
assert_eq!(vec![2, 32, 0, 0, 0, 20, 104, 101, 108, 108, 111], encoded);
|
|
let decoded = Call::<TraitImpl>::decode(&mut &encoded[..]).unwrap();
|
|
assert_eq!(decoded, call);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "on_initialize")]
|
|
fn on_initialize_should_work_1() {
|
|
<Module<TraitImpl> as OnInitialize<u32>>::on_initialize(42);
|
|
}
|
|
|
|
#[test]
|
|
fn on_initialize_should_work_2() {
|
|
assert_eq!(
|
|
<Module<TraitImpl> as OnInitialize<u32>>::on_initialize(10),
|
|
Weight::from_ref_time(7)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "on_idle")]
|
|
fn on_idle_should_work_1() {
|
|
<Module<TraitImpl> as OnIdle<u32>>::on_idle(42, Weight::from_ref_time(9));
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "on_idle")]
|
|
fn on_idle_should_work_2() {
|
|
<Module<TraitImpl> as OnIdle<u32>>::on_idle(9, Weight::from_ref_time(42));
|
|
}
|
|
|
|
#[test]
|
|
fn on_idle_should_work_3() {
|
|
assert_eq!(
|
|
<Module<TraitImpl> as OnIdle<u32>>::on_idle(10, Weight::from_ref_time(11)),
|
|
Weight::from_ref_time(7)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "on_finalize")]
|
|
fn on_finalize_should_work() {
|
|
<Module<TraitImpl> as OnFinalize<u32>>::on_finalize(42);
|
|
}
|
|
|
|
#[test]
|
|
fn on_runtime_upgrade_should_work() {
|
|
sp_io::TestExternalities::default().execute_with(|| {
|
|
assert_eq!(
|
|
<Module<TraitImpl> as OnRuntimeUpgrade>::on_runtime_upgrade(),
|
|
Weight::from_ref_time(10)
|
|
)
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn weight_should_attach_to_call_enum() {
|
|
// operational.
|
|
assert_eq!(
|
|
Call::<TraitImpl>::operational {}.get_dispatch_info(),
|
|
DispatchInfo {
|
|
weight: Weight::from_ref_time(5),
|
|
class: DispatchClass::Operational,
|
|
pays_fee: Pays::Yes
|
|
},
|
|
);
|
|
// custom basic
|
|
assert_eq!(
|
|
Call::<TraitImpl>::aux_3 {}.get_dispatch_info(),
|
|
DispatchInfo {
|
|
weight: Weight::from_ref_time(3),
|
|
class: DispatchClass::Normal,
|
|
pays_fee: Pays::Yes
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn call_name() {
|
|
let name = Call::<TraitImpl>::aux_3 {}.get_call_name();
|
|
assert_eq!("aux_3", name);
|
|
}
|
|
|
|
#[test]
|
|
fn get_call_names() {
|
|
let call_names = Call::<TraitImpl>::get_call_names();
|
|
assert_eq!(
|
|
["aux_0", "aux_1", "aux_2", "aux_3", "aux_4", "aux_5", "operational"],
|
|
call_names
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "integrity_test")]
|
|
fn integrity_test_should_work() {
|
|
<Module<TraitImpl> as IntegrityTest>::integrity_test();
|
|
}
|
|
|
|
#[test]
|
|
fn test_new_call_variant() {
|
|
Call::<TraitImpl>::new_call_variant_aux_0();
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
// Do not complain about unused `dispatch` and `dispatch_aux`.
|
|
#[allow(dead_code)]
|
|
mod weight_tests {
|
|
use super::*;
|
|
use sp_core::{parameter_types, Get};
|
|
use sp_weights::RuntimeDbWeight;
|
|
|
|
pub trait Config: 'static {
|
|
type RuntimeOrigin;
|
|
type Balance;
|
|
type BlockNumber;
|
|
type DbWeight: Get<RuntimeDbWeight>;
|
|
type PalletInfo: crate::traits::PalletInfo;
|
|
}
|
|
|
|
pub struct TraitImpl {}
|
|
|
|
parameter_types! {
|
|
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
|
|
read: 100,
|
|
write: 1000,
|
|
};
|
|
}
|
|
|
|
impl Config for TraitImpl {
|
|
type RuntimeOrigin = u32;
|
|
type BlockNumber = u32;
|
|
type Balance = u32;
|
|
type DbWeight = DbWeight;
|
|
type PalletInfo = crate::tests::PanicPalletInfo;
|
|
}
|
|
|
|
decl_module! {
|
|
pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin, system=self {
|
|
// no arguments, fixed weight
|
|
#[weight = 1000]
|
|
fn f00(_origin) { unimplemented!(); }
|
|
|
|
#[weight = (1000, DispatchClass::Mandatory)]
|
|
fn f01(_origin) { unimplemented!(); }
|
|
|
|
#[weight = (1000, Pays::No)]
|
|
fn f02(_origin) { unimplemented!(); }
|
|
|
|
#[weight = (1000, DispatchClass::Operational, Pays::No)]
|
|
fn f03(_origin) { unimplemented!(); }
|
|
|
|
// weight = a x 10 + b
|
|
#[weight = ((_a * 10 + _eb * 1) as u64, DispatchClass::Normal, Pays::Yes)]
|
|
fn f11(_origin, _a: u32, _eb: u32) { unimplemented!(); }
|
|
|
|
#[weight = (0, DispatchClass::Operational, Pays::Yes)]
|
|
fn f12(_origin, _a: u32, _eb: u32) { unimplemented!(); }
|
|
|
|
#[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + Weight::from_ref_time(10_000)]
|
|
fn f20(_origin) { unimplemented!(); }
|
|
|
|
#[weight = T::DbWeight::get().reads_writes(6, 5) + Weight::from_ref_time(40_000)]
|
|
fn f21(_origin) { unimplemented!(); }
|
|
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn weights_are_correct() {
|
|
// #[weight = 1000]
|
|
let info = Call::<TraitImpl>::f00 {}.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(1000));
|
|
assert_eq!(info.class, DispatchClass::Normal);
|
|
assert_eq!(info.pays_fee, Pays::Yes);
|
|
|
|
// #[weight = (1000, DispatchClass::Mandatory)]
|
|
let info = Call::<TraitImpl>::f01 {}.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(1000));
|
|
assert_eq!(info.class, DispatchClass::Mandatory);
|
|
assert_eq!(info.pays_fee, Pays::Yes);
|
|
|
|
// #[weight = (1000, Pays::No)]
|
|
let info = Call::<TraitImpl>::f02 {}.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(1000));
|
|
assert_eq!(info.class, DispatchClass::Normal);
|
|
assert_eq!(info.pays_fee, Pays::No);
|
|
|
|
// #[weight = (1000, DispatchClass::Operational, Pays::No)]
|
|
let info = Call::<TraitImpl>::f03 {}.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(1000));
|
|
assert_eq!(info.class, DispatchClass::Operational);
|
|
assert_eq!(info.pays_fee, Pays::No);
|
|
|
|
// #[weight = ((_a * 10 + _eb * 1) as Weight, DispatchClass::Normal, Pays::Yes)]
|
|
let info = Call::<TraitImpl>::f11 { _a: 13, _eb: 20 }.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(150)); // 13*10 + 20
|
|
assert_eq!(info.class, DispatchClass::Normal);
|
|
assert_eq!(info.pays_fee, Pays::Yes);
|
|
|
|
// #[weight = (0, DispatchClass::Operational, Pays::Yes)]
|
|
let info = Call::<TraitImpl>::f12 { _a: 10, _eb: 20 }.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(0));
|
|
assert_eq!(info.class, DispatchClass::Operational);
|
|
assert_eq!(info.pays_fee, Pays::Yes);
|
|
|
|
// #[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + 10_000]
|
|
let info = Call::<TraitImpl>::f20 {}.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(12300)); // 100*3 + 1000*2 + 10_1000
|
|
assert_eq!(info.class, DispatchClass::Normal);
|
|
assert_eq!(info.pays_fee, Pays::Yes);
|
|
|
|
// #[weight = T::DbWeight::get().reads_writes(6, 5) + 40_000]
|
|
let info = Call::<TraitImpl>::f21 {}.get_dispatch_info();
|
|
assert_eq!(info.weight, Weight::from_ref_time(45600)); // 100*6 + 1000*5 + 40_1000
|
|
assert_eq!(info.class, DispatchClass::Normal);
|
|
assert_eq!(info.pays_fee, Pays::Yes);
|
|
}
|
|
|
|
#[test]
|
|
fn extract_actual_weight_works() {
|
|
let pre = DispatchInfo { weight: Weight::from_ref_time(1000), ..Default::default() };
|
|
assert_eq!(extract_actual_weight(&Ok(Some(7).into()), &pre), Weight::from_ref_time(7));
|
|
assert_eq!(
|
|
extract_actual_weight(&Ok(Some(1000).into()), &pre),
|
|
Weight::from_ref_time(1000)
|
|
);
|
|
assert_eq!(
|
|
extract_actual_weight(
|
|
&Err(DispatchError::BadOrigin.with_weight(Weight::from_ref_time(9))),
|
|
&pre
|
|
),
|
|
Weight::from_ref_time(9)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn extract_actual_weight_caps_at_pre_weight() {
|
|
let pre = DispatchInfo { weight: Weight::from_ref_time(1000), ..Default::default() };
|
|
assert_eq!(
|
|
extract_actual_weight(&Ok(Some(1250).into()), &pre),
|
|
Weight::from_ref_time(1000)
|
|
);
|
|
assert_eq!(
|
|
extract_actual_weight(
|
|
&Err(DispatchError::BadOrigin.with_weight(Weight::from_ref_time(1300))),
|
|
&pre
|
|
),
|
|
Weight::from_ref_time(1000),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn extract_actual_pays_fee_works() {
|
|
let pre = DispatchInfo { weight: Weight::from_ref_time(1000), ..Default::default() };
|
|
assert_eq!(extract_actual_pays_fee(&Ok(Some(7).into()), &pre), Pays::Yes);
|
|
assert_eq!(extract_actual_pays_fee(&Ok(Some(1000).into()), &pre), Pays::Yes);
|
|
assert_eq!(extract_actual_pays_fee(&Ok((Some(1000), Pays::Yes).into()), &pre), Pays::Yes);
|
|
assert_eq!(extract_actual_pays_fee(&Ok((Some(1000), Pays::No).into()), &pre), Pays::No);
|
|
assert_eq!(
|
|
extract_actual_pays_fee(
|
|
&Err(DispatchError::BadOrigin.with_weight(Weight::from_ref_time(9))),
|
|
&pre
|
|
),
|
|
Pays::Yes
|
|
);
|
|
assert_eq!(
|
|
extract_actual_pays_fee(
|
|
&Err(DispatchErrorWithPostInfo {
|
|
post_info: PostDispatchInfo { actual_weight: None, pays_fee: Pays::No },
|
|
error: DispatchError::BadOrigin,
|
|
}),
|
|
&pre
|
|
),
|
|
Pays::No
|
|
);
|
|
|
|
let pre = DispatchInfo {
|
|
weight: Weight::from_ref_time(1000),
|
|
pays_fee: Pays::No,
|
|
..Default::default()
|
|
};
|
|
assert_eq!(extract_actual_pays_fee(&Ok(Some(7).into()), &pre), Pays::No);
|
|
assert_eq!(extract_actual_pays_fee(&Ok(Some(1000).into()), &pre), Pays::No);
|
|
assert_eq!(extract_actual_pays_fee(&Ok((Some(1000), Pays::Yes).into()), &pre), Pays::No);
|
|
}
|
|
}
|