staging_xcm_executor/traits/should_execute.rs
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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
use core::result::Result;
use frame_support::traits::ProcessMessageError;
use xcm::latest::{Instruction, Location, Weight, XcmHash};
/// Properties of an XCM message and its imminent execution.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Properties {
/// The amount of weight that the system has determined this
/// message may utilize in its execution. Typically non-zero only because of prior fee
/// payment, but could in principle be due to other factors.
pub weight_credit: Weight,
/// The identity of the message, if one is known. If left as `None`, then it will generally
/// default to the hash of the message which may be non-unique.
pub message_id: Option<XcmHash>,
}
/// Trait to determine whether the execution engine should actually execute a given XCM.
///
/// Can be amalgamated into a tuple to have multiple trials. If any of the tuple elements returns
/// `Ok(())`, the execution stops. Else, `Err(_)` is returned if all elements reject the message.
pub trait ShouldExecute {
/// Returns `Ok(())` if the given `message` may be executed.
///
/// - `origin`: The origin (sender) of the message.
/// - `instructions`: The message itself.
/// - `max_weight`: The (possibly over-) estimation of the weight of execution of the message.
/// - `properties`: Various pre-established properties of the message which may be mutated by
/// this API.
fn should_execute<RuntimeCall>(
origin: &Location,
instructions: &mut [Instruction<RuntimeCall>],
max_weight: Weight,
properties: &mut Properties,
) -> Result<(), ProcessMessageError>;
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl ShouldExecute for Tuple {
fn should_execute<RuntimeCall>(
origin: &Location,
instructions: &mut [Instruction<RuntimeCall>],
max_weight: Weight,
properties: &mut Properties,
) -> Result<(), ProcessMessageError> {
for_tuples!( #(
let barrier = core::any::type_name::<Tuple>();
match Tuple::should_execute(origin, instructions, max_weight, properties) {
Ok(()) => {
tracing::trace!(
target: "xcm::should_execute",
?origin,
?instructions,
?max_weight,
?properties,
%barrier,
"pass barrier",
);
return Ok(())
},
Err(error) => {
tracing::trace!(
target: "xcm::should_execute",
?origin,
?instructions,
?max_weight,
?properties,
?error,
%barrier,
"did not pass barrier",
);
},
}
)* );
Err(ProcessMessageError::Unsupported)
}
}
/// Trait to determine whether the execution engine is suspended from executing a given XCM.
///
/// The trait method is given the same parameters as `ShouldExecute::should_execute`, so that the
/// implementer will have all the context necessary to determine whether or not to suspend the
/// XCM executor.
///
/// Can be chained together in tuples to have multiple rounds of checks. If all of the tuple
/// elements returns false, then execution is not suspended. Otherwise, execution is suspended
/// if any of the tuple elements returns true.
pub trait CheckSuspension {
fn is_suspended<Call>(
origin: &Location,
instructions: &mut [Instruction<Call>],
max_weight: Weight,
properties: &mut Properties,
) -> bool;
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl CheckSuspension for Tuple {
fn is_suspended<Call>(
origin: &Location,
instruction: &mut [Instruction<Call>],
max_weight: Weight,
properties: &mut Properties,
) -> bool {
for_tuples!( #(
if Tuple::is_suspended(origin, instruction, max_weight, properties) {
return true
}
)* );
false
}
}
/// Trait to determine whether the execution engine should not execute a given XCM.
///
/// Can be amalgamated into a tuple to have multiple traits. If any of the tuple elements returns
/// `Err(ProcessMessageError)`, the execution stops. Else, `Ok(())` is returned if all elements
/// accept the message.
pub trait DenyExecution {
/// Returns `Ok(())` if there is no reason to deny execution,
/// while `Err(ProcessMessageError)` indicates there is a reason to deny execution.
///
/// - `origin`: The origin (sender) of the message.
/// - `instructions`: The message itself.
/// - `max_weight`: The (possibly over-) estimation of the weight of execution of the message.
/// - `properties`: Various pre-established properties of the message which may be mutated by
/// this API.
fn deny_execution<RuntimeCall>(
origin: &Location,
instructions: &mut [Instruction<RuntimeCall>],
max_weight: Weight,
properties: &mut Properties,
) -> Result<(), ProcessMessageError>;
}
#[impl_trait_for_tuples::impl_for_tuples(10)]
impl DenyExecution for Tuple {
fn deny_execution<RuntimeCall>(
origin: &Location,
instructions: &mut [Instruction<RuntimeCall>],
max_weight: Weight,
properties: &mut Properties,
) -> Result<(), ProcessMessageError> {
for_tuples!( #(
let barrier = core::any::type_name::<Tuple>();
match Tuple::deny_execution(origin, instructions, max_weight, properties) {
Err(error) => {
tracing::error!(
target: "xcm::deny_execution",
?origin,
?instructions,
?max_weight,
?properties,
?error,
%barrier,
"did not pass barrier",
);
return Err(error);
},
Ok(()) => {
tracing::trace!(
target: "xcm::deny_execution",
?origin,
?instructions,
?max_weight,
?properties,
%barrier,
"pass barrier",
);
},
}
)* );
Ok(())
}
}