referrerpolicy=no-referrer-when-downgrade

staging_xcm_executor/traits/
should_execute.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot 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// Polkadot 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 Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17use core::result::Result;
18use frame_support::traits::ProcessMessageError;
19use xcm::latest::{Instruction, Location, Weight, XcmHash};
20
21/// Properties of an XCM message and its imminent execution.
22#[derive(Clone, Eq, PartialEq, Debug)]
23pub struct Properties {
24	/// The amount of weight that the system has determined this
25	/// message may utilize in its execution. Typically non-zero only because of prior fee
26	/// payment, but could in principle be due to other factors.
27	pub weight_credit: Weight,
28	/// The identity of the message, if one is known. If left as `None`, then it will generally
29	/// default to the hash of the message which may be non-unique.
30	pub message_id: Option<XcmHash>,
31}
32
33/// Trait to determine whether the execution engine should actually execute a given XCM.
34///
35/// Can be amalgamated into a tuple to have multiple trials. If any of the tuple elements returns
36/// `Ok(())`, the execution stops. Else, `Err(_)` is returned if all elements reject the message.
37pub trait ShouldExecute {
38	/// Returns `Ok(())` if the given `message` may be executed.
39	///
40	/// - `origin`: The origin (sender) of the message.
41	/// - `instructions`: The message itself.
42	/// - `max_weight`: The (possibly over-) estimation of the weight of execution of the message.
43	/// - `properties`: Various pre-established properties of the message which may be mutated by
44	///   this API.
45	fn should_execute<RuntimeCall>(
46		origin: &Location,
47		instructions: &mut [Instruction<RuntimeCall>],
48		max_weight: Weight,
49		properties: &mut Properties,
50	) -> Result<(), ProcessMessageError>;
51}
52
53#[impl_trait_for_tuples::impl_for_tuples(30)]
54impl ShouldExecute for Tuple {
55	fn should_execute<RuntimeCall>(
56		origin: &Location,
57		instructions: &mut [Instruction<RuntimeCall>],
58		max_weight: Weight,
59		properties: &mut Properties,
60	) -> Result<(), ProcessMessageError> {
61		for_tuples!( #(
62			let barrier = core::any::type_name::<Tuple>();
63 			match Tuple::should_execute(origin, instructions, max_weight, properties) {
64				Ok(()) => {
65					tracing::trace!(
66						target: "xcm::should_execute",
67						?origin,
68						?instructions,
69						?max_weight,
70						?properties,
71						%barrier,
72						"pass barrier",
73					);
74					return Ok(())
75				},
76				Err(error) => {
77					tracing::trace!(
78						target: "xcm::should_execute",
79						?origin,
80						?instructions,
81						?max_weight,
82						?properties,
83						?error,
84						%barrier,
85						"did not pass barrier",
86					);
87				},
88			}
89		)* );
90
91		Err(ProcessMessageError::Unsupported)
92	}
93}
94
95/// Trait to determine whether the execution engine is suspended from executing a given XCM.
96///
97/// The trait method is given the same parameters as `ShouldExecute::should_execute`, so that the
98/// implementer will have all the context necessary to determine whether or not to suspend the
99/// XCM executor.
100///
101/// Can be chained together in tuples to have multiple rounds of checks. If all of the tuple
102/// elements returns false, then execution is not suspended. Otherwise, execution is suspended
103/// if any of the tuple elements returns true.
104pub trait CheckSuspension {
105	fn is_suspended<Call>(
106		origin: &Location,
107		instructions: &mut [Instruction<Call>],
108		max_weight: Weight,
109		properties: &mut Properties,
110	) -> bool;
111}
112
113#[impl_trait_for_tuples::impl_for_tuples(30)]
114impl CheckSuspension for Tuple {
115	fn is_suspended<Call>(
116		origin: &Location,
117		instruction: &mut [Instruction<Call>],
118		max_weight: Weight,
119		properties: &mut Properties,
120	) -> bool {
121		for_tuples!( #(
122			if Tuple::is_suspended(origin, instruction, max_weight, properties) {
123				return true
124			}
125		)* );
126
127		false
128	}
129}
130
131/// Trait to determine whether the execution engine should not execute a given XCM.
132///
133/// Can be amalgamated into a tuple to have multiple traits. If any of the tuple elements returns
134/// `Err(ProcessMessageError)`, the execution stops. Else, `Ok(())` is returned if all elements
135/// accept the message.
136pub trait DenyExecution {
137	/// Returns `Ok(())` if there is no reason to deny execution,
138	/// while `Err(ProcessMessageError)` indicates there is a reason to deny execution.
139	///
140	/// - `origin`: The origin (sender) of the message.
141	/// - `instructions`: The message itself.
142	/// - `max_weight`: The (possibly over-) estimation of the weight of execution of the message.
143	/// - `properties`: Various pre-established properties of the message which may be mutated by
144	///   this API.
145	fn deny_execution<RuntimeCall>(
146		origin: &Location,
147		instructions: &mut [Instruction<RuntimeCall>],
148		max_weight: Weight,
149		properties: &mut Properties,
150	) -> Result<(), ProcessMessageError>;
151}
152
153#[impl_trait_for_tuples::impl_for_tuples(10)]
154impl DenyExecution for Tuple {
155	fn deny_execution<RuntimeCall>(
156		origin: &Location,
157		instructions: &mut [Instruction<RuntimeCall>],
158		max_weight: Weight,
159		properties: &mut Properties,
160	) -> Result<(), ProcessMessageError> {
161		for_tuples!( #(
162            let barrier = core::any::type_name::<Tuple>();
163            match Tuple::deny_execution(origin, instructions, max_weight, properties) {
164                Err(error) => {
165                    tracing::error!(
166                        target: "xcm::deny_execution",
167                        ?origin,
168                        ?instructions,
169                        ?max_weight,
170                        ?properties,
171                        ?error,
172                        %barrier,
173                        "did not pass barrier",
174                    );
175                    return Err(error);
176                },
177				  Ok(())  => {
178                    tracing::trace!(
179                        target: "xcm::deny_execution",
180                        ?origin,
181                        ?instructions,
182                        ?max_weight,
183                        ?properties,
184                        %barrier,
185                        "pass barrier",
186                    );
187                },
188            }
189        )* );
190
191		Ok(())
192	}
193}