referrerpolicy=no-referrer-when-downgrade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.

// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.

//! Primitives that may be used for creating signed extensions for indirect runtimes.

use codec::{Compact, Decode, Encode};
use impl_trait_for_tuples::impl_for_tuples;
use scale_info::{StaticTypeInfo, TypeInfo};
use sp_runtime::{
	impl_tx_ext_default,
	traits::{Dispatchable, TransactionExtension},
	transaction_validity::TransactionValidityError,
};
use sp_std::{fmt::Debug, marker::PhantomData};

/// Trait that describes some properties of a `TransactionExtension` that are needed in order to
/// send a transaction to the chain.
pub trait TransactionExtensionSchema:
	Encode + Decode + Debug + Eq + Clone + StaticTypeInfo
{
	/// A type of the data encoded as part of the transaction.
	type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo;
	/// Parameters which are part of the payload used to produce transaction signature,
	/// but don't end up in the transaction itself (i.e. inherent part of the runtime).
	type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo;
}

impl TransactionExtensionSchema for () {
	type Payload = ();
	type Implicit = ();
}

/// An implementation of `TransactionExtensionSchema` using generic params.
#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)]
pub struct GenericTransactionExtensionSchema<P, S>(PhantomData<(P, S)>);

impl<P, S> TransactionExtensionSchema for GenericTransactionExtensionSchema<P, S>
where
	P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo,
	S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo,
{
	type Payload = P;
	type Implicit = S;
}

/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`.
pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>;

/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`.
pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>;

/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`.
pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>;

/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`.
pub type CheckGenesis<Hash> = GenericTransactionExtensionSchema<(), Hash>;

/// The `TransactionExtensionSchema` for `frame_system::CheckEra`.
pub type CheckEra<Hash> = GenericTransactionExtensionSchema<sp_runtime::generic::Era, Hash>;

/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`.
pub type CheckNonce<TxNonce> = GenericTransactionExtensionSchema<Compact<TxNonce>, ()>;

/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`.
pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>;

/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`.
pub type ChargeTransactionPayment<Balance> =
	GenericTransactionExtensionSchema<Compact<Balance>, ()>;

/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`.
pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>;

/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`.
pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>;

/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`.
/// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as
/// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (),
/// ())` is the same. So runtime can contains any kind of tuple:
/// `(BridgeRefundBridgeHubRococoMessages)`
/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)`
/// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)`
pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>;

#[impl_for_tuples(1, 12)]
impl TransactionExtensionSchema for Tuple {
	for_tuples!( type Payload = ( #( Tuple::Payload ),* ); );
	for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); );
}

/// A simplified version of signed extensions meant for producing signed transactions
/// and signed payloads in the client code.
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub struct GenericTransactionExtension<S: TransactionExtensionSchema> {
	/// A payload that is included in the transaction.
	pub payload: S::Payload,
	#[codec(skip)]
	// It may be set to `None` if extensions are decoded. We are never reconstructing transactions
	// (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only
	// used to read fields of the `payload`. And when resigning transaction, we're reconstructing
	// `TransactionExtensions` from scratch.
	implicit: Option<S::Implicit>,
}

impl<S: TransactionExtensionSchema> GenericTransactionExtension<S> {
	/// Create new `GenericTransactionExtension` object.
	pub fn new(payload: S::Payload, implicit: Option<S::Implicit>) -> Self {
		Self { payload, implicit }
	}
}

impl<S, C> TransactionExtension<C> for GenericTransactionExtension<S>
where
	C: Dispatchable,
	S: TransactionExtensionSchema,
	S::Payload: Send + Sync,
	S::Implicit: Send + Sync,
{
	const IDENTIFIER: &'static str = "Not needed.";
	type Implicit = S::Implicit;

	fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
		// we shall not ever see this error in relay, because we are never signing decoded
		// transactions. Instead we're constructing and signing new transactions. So the error code
		// is kinda random here
		self.implicit
			.clone()
			.ok_or(frame_support::unsigned::TransactionValidityError::Unknown(
				frame_support::unsigned::UnknownTransaction::Custom(0xFF),
			))
	}
	type Pre = ();
	type Val = ();

	impl_tx_ext_default!(C; weight validate prepare);
}