Closes#2160
First part of [Extrinsic
Horizon](https://github.com/paritytech/polkadot-sdk/issues/2415)
Introduces a new trait `TransactionExtension` to replace
`SignedExtension`. Introduce the idea of transactions which obey the
runtime's extensions and have according Extension data (né Extra data)
yet do not have hard-coded signatures.
Deprecate the terminology of "Unsigned" when used for
transactions/extrinsics owing to there now being "proper" unsigned
transactions which obey the extension framework and "old-style" unsigned
which do not. Instead we have __*General*__ for the former and
__*Bare*__ for the latter. (Ultimately, the latter will be phased out as
a type of transaction, and Bare will only be used for Inherents.)
Types of extrinsic are now therefore:
- Bare (no hardcoded signature, no Extra data; used to be known as
"Unsigned")
- Bare transactions (deprecated): Gossiped, validated with
`ValidateUnsigned` (deprecated) and the `_bare_compat` bits of
`TransactionExtension` (deprecated).
- Inherents: Not gossiped, validated with `ProvideInherent`.
- Extended (Extra data): Gossiped, validated via `TransactionExtension`.
- Signed transactions (with a hardcoded signature).
- General transactions (without a hardcoded signature).
`TransactionExtension` differs from `SignedExtension` because:
- A signature on the underlying transaction may validly not be present.
- It may alter the origin during validation.
- `pre_dispatch` is renamed to `prepare` and need not contain the checks
present in `validate`.
- `validate` and `prepare` is passed an `Origin` rather than a
`AccountId`.
- `validate` may pass arbitrary information into `prepare` via a new
user-specifiable type `Val`.
- `AdditionalSigned`/`additional_signed` is renamed to
`Implicit`/`implicit`. It is encoded *for the entire transaction* and
passed in to each extension as a new argument to `validate`. This
facilitates the ability of extensions to acts as underlying crypto.
There is a new `DispatchTransaction` trait which contains only default
function impls and is impl'ed for any `TransactionExtension` impler. It
provides several utility functions which reduce some of the tedium from
using `TransactionExtension` (indeed, none of its regular functions
should now need to be called directly).
Three transaction version discriminator ("versions") are now
permissible:
- 0b000000100: Bare (used to be called "Unsigned"): contains Signature
or Extra (extension data). After bare transactions are no longer
supported, this will strictly identify an Inherents only.
- 0b100000100: Old-school "Signed" Transaction: contains Signature and
Extra (extension data).
- 0b010000100: New-school "General" Transaction: contains Extra
(extension data), but no Signature.
For the New-school General Transaction, it becomes trivial for authors
to publish extensions to the mechanism for authorizing an Origin, e.g.
through new kinds of key-signing schemes, ZK proofs, pallet state,
mutations over pre-authenticated origins or any combination of the
above.
## Code Migration
### NOW: Getting it to build
Wrap your `SignedExtension`s in `AsTransactionExtension`. This should be
accompanied by renaming your aggregate type in line with the new
terminology. E.g. Before:
```rust
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
/* snip */
MySpecialSignedExtension,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
```
After:
```rust
/// The extension to the basic transaction logic.
pub type TxExtension = (
/* snip */
AsTransactionExtension<MySpecialSignedExtension>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
```
You'll also need to alter any transaction building logic to add a
`.into()` to make the conversion happen. E.g. Before:
```rust
fn construct_extrinsic(
/* snip */
) -> UncheckedExtrinsic {
let extra: SignedExtra = (
/* snip */
MySpecialSignedExtension::new(/* snip */),
);
let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap();
let signature = payload.using_encoded(|e| sender.sign(e));
UncheckedExtrinsic::new_signed(
/* snip */
Signature::Sr25519(signature),
extra,
)
}
```
After:
```rust
fn construct_extrinsic(
/* snip */
) -> UncheckedExtrinsic {
let tx_ext: TxExtension = (
/* snip */
MySpecialSignedExtension::new(/* snip */).into(),
);
let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap();
let signature = payload.using_encoded(|e| sender.sign(e));
UncheckedExtrinsic::new_signed(
/* snip */
Signature::Sr25519(signature),
tx_ext,
)
}
```
### SOON: Migrating to `TransactionExtension`
Most `SignedExtension`s can be trivially converted to become a
`TransactionExtension`. There are a few things to know.
- Instead of a single trait like `SignedExtension`, you should now
implement two traits individually: `TransactionExtensionBase` and
`TransactionExtension`.
- Weights are now a thing and must be provided via the new function `fn
weight`.
#### `TransactionExtensionBase`
This trait takes care of anything which is not dependent on types
specific to your runtime, most notably `Call`.
- `AdditionalSigned`/`additional_signed` is renamed to
`Implicit`/`implicit`.
- Weight must be returned by implementing the `weight` function. If your
extension is associated with a pallet, you'll probably want to do this
via the pallet's existing benchmarking infrastructure.
#### `TransactionExtension`
Generally:
- `pre_dispatch` is now `prepare` and you *should not reexecute the
`validate` functionality in there*!
- You don't get an account ID any more; you get an origin instead. If
you need to presume an account ID, then you can use the trait function
`AsSystemOriginSigner::as_system_origin_signer`.
- You get an additional ticket, similar to `Pre`, called `Val`. This
defines data which is passed from `validate` into `prepare`. This is
important since you should not be duplicating logic from `validate` to
`prepare`, you need a way of passing your working from the former into
the latter. This is it.
- This trait takes two type parameters: `Call` and `Context`. `Call` is
the runtime call type which used to be an associated type; you can just
move it to become a type parameter for your trait impl. `Context` is not
currently used and you can safely implement over it as an unbounded
type.
- There's no `AccountId` associated type any more. Just remove it.
Regarding `validate`:
- You get three new parameters in `validate`; all can be ignored when
migrating from `SignedExtension`.
- `validate` returns a tuple on success; the second item in the tuple is
the new ticket type `Self::Val` which gets passed in to `prepare`. If
you use any information extracted during `validate` (off-chain and
on-chain, non-mutating) in `prepare` (on-chain, mutating) then you can
pass it through with this. For the tuple's last item, just return the
`origin` argument.
Regarding `prepare`:
- This is renamed from `pre_dispatch`, but there is one change:
- FUNCTIONALITY TO VALIDATE THE TRANSACTION NEED NOT BE DUPLICATED FROM
`validate`!!
- (This is different to `SignedExtension` which was required to run the
same checks in `pre_dispatch` as in `validate`.)
Regarding `post_dispatch`:
- Since there are no unsigned transactions handled by
`TransactionExtension`, `Pre` is always defined, so the first parameter
is `Self::Pre` rather than `Option<Self::Pre>`.
If you make use of `SignedExtension::validate_unsigned` or
`SignedExtension::pre_dispatch_unsigned`, then:
- Just use the regular versions of these functions instead.
- Have your logic execute in the case that the `origin` is `None`.
- Ensure your transaction creation logic creates a General Transaction
rather than a Bare Transaction; this means having to include all
`TransactionExtension`s' data.
- `ValidateUnsigned` can still be used (for now) if you need to be able
to construct transactions which contain none of the extension data,
however these will be phased out in stage 2 of the Transactions Horizon,
so you should consider moving to an extension-centric design.
## TODO
- [x] Introduce `CheckSignature` impl of `TransactionExtension` to
ensure it's possible to have crypto be done wholly in a
`TransactionExtension`.
- [x] Deprecate `SignedExtension` and move all uses in codebase to
`TransactionExtension`.
- [x] `ChargeTransactionPayment`
- [x] `DummyExtension`
- [x] `ChargeAssetTxPayment` (asset-tx-payment)
- [x] `ChargeAssetTxPayment` (asset-conversion-tx-payment)
- [x] `CheckWeight`
- [x] `CheckTxVersion`
- [x] `CheckSpecVersion`
- [x] `CheckNonce`
- [x] `CheckNonZeroSender`
- [x] `CheckMortality`
- [x] `CheckGenesis`
- [x] `CheckOnlySudoAccount`
- [x] `WatchDummy`
- [x] `PrevalidateAttests`
- [x] `GenericSignedExtension`
- [x] `SignedExtension` (chain-polkadot-bulletin)
- [x] `RefundSignedExtensionAdapter`
- [x] Implement `fn weight` across the board.
- [ ] Go through all pre-existing extensions which assume an account
signer and explicitly handle the possibility of another kind of origin.
- [x] `CheckNonce` should probably succeed in the case of a non-account
origin.
- [x] `CheckNonZeroSender` should succeed in the case of a non-account
origin.
- [x] `ChargeTransactionPayment` and family should fail in the case of a
non-account origin.
- [ ]
- [x] Fix any broken tests.
---------
Signed-off-by: georgepisaltu <george.pisaltu@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io>
Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>
Co-authored-by: Nikhil Gupta <17176722+gupnik@users.noreply.github.com>
Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com>
Co-authored-by: Chevdor <chevdor@users.noreply.github.com>
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Maciej <maciej.zyszkiewicz@parity.io>
Co-authored-by: Javier Viola <javier@parity.io>
Co-authored-by: Marcin S. <marcin@realemail.net>
Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io>
Co-authored-by: Javier Bullrich <javier@bullrich.dev>
Co-authored-by: Koute <koute@users.noreply.github.com>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: Vladimir Istyufeev <vladimir@parity.io>
Co-authored-by: Ross Bulat <ross@parity.io>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com>
Co-authored-by: ordian <write@reusable.software>
Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com>
Co-authored-by: Dmitry Markin <dmitry@markin.tech>
Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com>
Co-authored-by: Julian Eager <eagr@tutanota.com>
Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>
Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: Dónal Murray <donal.murray@parity.io>
Co-authored-by: yjh <yjh465402634@gmail.com>
Co-authored-by: Tom Mi <tommi@niemi.lol>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Will | Paradox | ParaNodes.io <79228812+paradox-tt@users.noreply.github.com>
Co-authored-by: Bastian Köcher <info@kchr.de>
Co-authored-by: Joshy Orndorff <JoshOrndorff@users.noreply.github.com>
Co-authored-by: Joshy Orndorff <git-user-email.h0ly5@simplelogin.com>
Co-authored-by: PG Herveou <pgherveou@gmail.com>
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Juan Girini <juangirini@gmail.com>
Co-authored-by: bader y <ibnbassem@gmail.com>
Co-authored-by: James Wilson <james@jsdw.me>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: asynchronous rob <rphmeier@gmail.com>
Co-authored-by: Parth <desaiparth08@gmail.com>
Co-authored-by: Andrew Jones <ascjones@gmail.com>
Co-authored-by: Jonathan Udd <jonathan@dwellir.com>
Co-authored-by: Serban Iorga <serban@parity.io>
Co-authored-by: Egor_P <egor@parity.io>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: Evgeny Snitko <evgeny@parity.io>
Co-authored-by: Just van Stam <vstam1@users.noreply.github.com>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: gupnik <nikhilgupta.iitk@gmail.com>
Co-authored-by: dzmitry-lahoda <dzmitry@lahoda.pro>
Co-authored-by: zhiqiangxu <652732310@qq.com>
Co-authored-by: Nazar Mokrynskyi <nazar@mokrynskyi.com>
Co-authored-by: Anwesh <anweshknayak@gmail.com>
Co-authored-by: cheme <emericchevalier.pro@gmail.com>
Co-authored-by: Sam Johnson <sam@durosoft.com>
Co-authored-by: kianenigma <kian@parity.io>
Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
Co-authored-by: Muharem <ismailov.m.h@gmail.com>
Co-authored-by: joepetrowski <joe@parity.io>
Co-authored-by: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com>
Co-authored-by: Gabriel Facco de Arruda <arrudagates@gmail.com>
Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com>
Co-authored-by: georgepisaltu <george.pisaltu@parity.io>
Co-authored-by: command-bot <>
* add serde_full feature flag
add serde_full to sp_runtime
add space to toml
add serde_full to application-crypto
add serde_full to arithmetic
fix arithmetic
add serde full to beefy
add serde full to consensus
add serde_full to core
add serdefull to finality grandpa
add serde_full to several primitives crates
make rpc no_std compatible
add scale info to runtime
make serializer no_std compatible
add serde full to storage
add full serde to version
add serde full to weights
add all serde_full features
add . to comment
add missing impl-serde
fix no-std build
fix build
add full_crypto to serde_full
serde_full also implements crypto
full_serde does not work with full_crytpo. needs std
no no_std serde impl possible
also for crypto std is necessary
no serde full for application crypto
fix arithmetic
fix tomls
fix some things
impl fmt for Signature
add serialize to Public
add impl_maybe_marker_serde_full
fix sp-application-crypto toml
add serde feature flag
fix clippy
fix toml grandpa
fix grandpa
rename if_std to if_serde
keystore is not no_std compatible
make keystore vrf no_std compatible
fix nopos-elections
fix rpc
fix serializer
fix test-primitives
fix version
add comment
add serde full only import for format string
remove all(serde_full and full_crypot) as serde_full enforces full_crypto
make comment better readable
even better comment
clean up rpc toml
clean up toml
clean up serializer toml
clean up storage toml
fix std build
update .lock
fix sp-version
move sp_std import
test extern crate alloc
replace sp_std with core
add missing core
sp_core: serde feature do not enforce full crypto
application-crypto: serde feature do not enforce full crypto
rename serde_full to serde
add dep:serde and alloc to default feature
add full_crypto and remove unnecessary debu/fmt impls for serde
update comment
remove obolsete change in display AccountId32
remove extra changes
minimize diff
revert keystore changes
remove std from keystore
remove full-crypto feature
fix serde import
fix comment
fix feature = serde
* rename serde_full to serde
* move #[doc(hidden)] back
* remove feature = full crypto require frm MultiSigner
* reorder serde and scale_info import
* fix bs58 missing alloc import in serde feature
* add `from_string` to serde feature and add unimplemented
* remove serde feature from fixed_point display
* Remove serde/alloc
Co-authored-by: Davide Galassi <davxy@datawok.net>
* Update primitives/consensus/babe/Cargo.toml
Co-authored-by: Bastian Köcher <git@kchr.de>
* Update primitives/arithmetic/src/fixed_point.rs
Co-authored-by: Bastian Köcher <git@kchr.de>
* revert `from_string`fixed impl back to std only
* remove duplicate runtime string impl
* use sp_std::alloc
* remove no_std compatible rpc
* remove no_std compatibility from serializer
* rename mpl_maybe_marker_serde to std_or_serde
* update .lock
* add sp-std to executor
* fix sp-std import
* fix sp_std::format import
* use crate import
* add serde feature
* Update primitives/core/src/lib.rs
---------
Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: Bastian Köcher <git@kchr.de>
* Change copyright year to 2023 from 2022
* Fix incorrect update of copyright year
* Remove years from copy right header
* Fix remaining files
* Fix typo in a header and remove update-copyright.sh
* frame-executive: Reject invalid inherents in the executive
We already had support for making a block fail if an inherent returned, but it was part of the
signed extension `CheckWeight`. Rejecting blocks with invalid inherents should happen on the
`frame-executive` level without requiring any special signed extension. This is crucial to prevent
any kind of spamming of the network that could may happen with blocks that include failing inherents.
* FMT
* Update frame/executive/src/lib.rs
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
* Update primitives/runtime/src/transaction_validity.rs
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
Co-authored-by: parity-processbot <>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
* `sp-runtime`: make `parity-util-mem` dependency optional
* Use default-features = false for sp-runtime in sp-keyring
* Remove parity-util-mem from sp-core
* Cargo.lock
* Restore default-features for keyring dependency
* Run cargo fmt on the whole code base
* Second run
* Add CI check
* Fix compilation
* More unnecessary braces
* Handle weights
* Use --all
* Use correct attributes...
* Fix UI tests
* AHHHHHHHHH
* 🤦
* Docs
* Fix compilation
* 🤷
* Please stop
* 🤦 x 2
* More
* make rustfmt.toml consistent with polkadot
Co-authored-by: André Silva <andrerfosilva@gmail.com>