referrerpolicy=no-referrer-when-downgrade

bp_runtime/
extensions.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Primitives that may be used for creating signed extensions for indirect runtimes.
18
19use codec::{Compact, Decode, DecodeWithMemTracking, Encode};
20use impl_trait_for_tuples::impl_for_tuples;
21use scale_info::{StaticTypeInfo, TypeInfo};
22use sp_runtime::{
23	impl_tx_ext_default,
24	traits::{Dispatchable, TransactionExtension},
25	transaction_validity::TransactionValidityError,
26};
27use sp_std::{fmt::Debug, marker::PhantomData};
28
29/// Trait that describes some properties of a `TransactionExtension` that are needed in order to
30/// send a transaction to the chain.
31pub trait TransactionExtensionSchema:
32	Encode + Decode + DecodeWithMemTracking + Debug + Eq + Clone + StaticTypeInfo
33{
34	/// A type of the data encoded as part of the transaction.
35	type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo;
36	/// Parameters which are part of the payload used to produce transaction signature,
37	/// but don't end up in the transaction itself (i.e. inherent part of the runtime).
38	type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo;
39}
40
41impl TransactionExtensionSchema for () {
42	type Payload = ();
43	type Implicit = ();
44}
45
46/// An implementation of `TransactionExtensionSchema` using generic params.
47#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Debug, PartialEq, Eq, TypeInfo)]
48pub struct GenericTransactionExtensionSchema<P, S>(PhantomData<(P, S)>);
49
50impl<P, S> TransactionExtensionSchema for GenericTransactionExtensionSchema<P, S>
51where
52	P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo,
53	S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo,
54{
55	type Payload = P;
56	type Implicit = S;
57}
58
59/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`.
60pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>;
61
62/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`.
63pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>;
64
65/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`.
66pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>;
67
68/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`.
69pub type CheckGenesis<Hash> = GenericTransactionExtensionSchema<(), Hash>;
70
71/// The `TransactionExtensionSchema` for `frame_system::CheckEra`.
72pub type CheckEra<Hash> = GenericTransactionExtensionSchema<sp_runtime::generic::Era, Hash>;
73
74/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`.
75pub type CheckNonce<TxNonce> = GenericTransactionExtensionSchema<Compact<TxNonce>, ()>;
76
77/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`.
78pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>;
79
80/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`.
81pub type ChargeTransactionPayment<Balance> =
82	GenericTransactionExtensionSchema<Compact<Balance>, ()>;
83
84/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`.
85pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>;
86
87/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`.
88pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>;
89
90/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`.
91/// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as
92/// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (),
93/// ())` is the same. So runtime can contains any kind of tuple:
94/// `(BridgeRefundBridgeHubRococoMessages)`
95/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)`
96/// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)`
97pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>;
98
99#[impl_for_tuples(1, 12)]
100impl TransactionExtensionSchema for Tuple {
101	for_tuples!( type Payload = ( #( Tuple::Payload ),* ); );
102	for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); );
103}
104
105/// A simplified version of signed extensions meant for producing signed transactions
106/// and signed payloads in the client code.
107#[derive(Encode, Decode, DecodeWithMemTracking, Debug, PartialEq, Eq, Clone, TypeInfo)]
108pub struct GenericTransactionExtension<S: TransactionExtensionSchema> {
109	/// A payload that is included in the transaction.
110	pub payload: S::Payload,
111	#[codec(skip)]
112	// It may be set to `None` if extensions are decoded. We are never reconstructing transactions
113	// (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only
114	// used to read fields of the `payload`. And when resigning transaction, we're reconstructing
115	// `TransactionExtensions` from scratch.
116	implicit: Option<S::Implicit>,
117}
118
119impl<S: TransactionExtensionSchema> GenericTransactionExtension<S> {
120	/// Create new `GenericTransactionExtension` object.
121	pub fn new(payload: S::Payload, implicit: Option<S::Implicit>) -> Self {
122		Self { payload, implicit }
123	}
124}
125
126impl<S, C> TransactionExtension<C> for GenericTransactionExtension<S>
127where
128	C: Dispatchable,
129	S: TransactionExtensionSchema,
130	S::Payload: DecodeWithMemTracking + Send + Sync,
131	S::Implicit: Send + Sync,
132{
133	const IDENTIFIER: &'static str = "Not needed.";
134	type Implicit = S::Implicit;
135
136	fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
137		// we shall not ever see this error in relay, because we are never signing decoded
138		// transactions. Instead we're constructing and signing new transactions. So the error code
139		// is kinda random here
140		self.implicit
141			.clone()
142			.ok_or(frame_support::unsigned::TransactionValidityError::Unknown(
143				frame_support::unsigned::UnknownTransaction::Custom(0xFF),
144			))
145	}
146	type Pre = ();
147	type Val = ();
148
149	impl_tx_ext_default!(C; weight validate prepare);
150}