staging_xcm_builder/
routing.rs1use alloc::vec::Vec;
20use codec::Encode;
21use core::{marker::PhantomData, result::Result};
22use frame_system::unique;
23use xcm::prelude::*;
24use xcm_executor::{traits::FeeReason, FeesMode};
25
26pub struct WithUniqueTopic<Inner>(PhantomData<Inner>);
39impl<Inner: SendXcm> SendXcm for WithUniqueTopic<Inner> {
40 type Ticket = (Inner::Ticket, [u8; 32]);
41
42 fn validate(
43 destination: &mut Option<Location>,
44 message: &mut Option<Xcm<()>>,
45 ) -> SendResult<Self::Ticket> {
46 let mut message = message.take().ok_or(SendError::MissingArgument)?;
47 let unique_id = if let Some(SetTopic(id)) = message.last() {
48 *id
49 } else {
50 let unique_id = unique(&message);
51 message.0.push(SetTopic(unique_id));
52 unique_id
53 };
54 let (ticket, assets) = Inner::validate(destination, &mut Some(message))?;
55 Ok(((ticket, unique_id), assets))
56 }
57
58 fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
59 let (ticket, unique_id) = ticket;
60 Inner::deliver(ticket)?;
61 Ok(unique_id)
62 }
63
64 #[cfg(feature = "runtime-benchmarks")]
65 fn ensure_successful_delivery(location: Option<Location>) {
66 Inner::ensure_successful_delivery(location);
67 }
68}
69impl<Inner: InspectMessageQueues> InspectMessageQueues for WithUniqueTopic<Inner> {
70 fn clear_messages() {
71 Inner::clear_messages()
72 }
73
74 fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)> {
75 Inner::get_messages()
76 }
77}
78
79pub trait SourceTopic {
80 fn source_topic(entropy: impl Encode) -> XcmHash;
81}
82
83impl SourceTopic for () {
84 fn source_topic(_: impl Encode) -> XcmHash {
85 [0u8; 32]
86 }
87}
88
89pub struct WithTopicSource<Inner, TopicSource>(PhantomData<(Inner, TopicSource)>);
97impl<Inner: SendXcm, TopicSource: SourceTopic> SendXcm for WithTopicSource<Inner, TopicSource> {
98 type Ticket = (Inner::Ticket, [u8; 32]);
99
100 fn validate(
101 destination: &mut Option<Location>,
102 message: &mut Option<Xcm<()>>,
103 ) -> SendResult<Self::Ticket> {
104 let mut message = message.take().ok_or(SendError::MissingArgument)?;
105 let unique_id = if let Some(SetTopic(id)) = message.last() {
106 *id
107 } else {
108 let unique_id = TopicSource::source_topic(&message);
109 message.0.push(SetTopic(unique_id));
110 unique_id
111 };
112 let (ticket, assets) = Inner::validate(destination, &mut Some(message.clone())).map_err(|e| {
113 tracing::debug!(target: "xcm::validate::WithTopicSource", ?destination, ?message, error = ?e, "Failed to validate");
114 SendError::NotApplicable
115 })?;
116 Ok(((ticket, unique_id), assets))
117 }
118
119 fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
120 let (ticket, unique_id) = ticket;
121 Inner::deliver(ticket)?;
122 Ok(unique_id)
123 }
124
125 #[cfg(feature = "runtime-benchmarks")]
126 fn ensure_successful_delivery(location: Option<Location>) {
127 Inner::ensure_successful_delivery(location);
128 }
129}
130
131pub trait EnsureDelivery {
134 fn ensure_successful_delivery(
139 origin_ref: &Location,
140 dest: &Location,
141 fee_reason: FeeReason,
142 ) -> (Option<FeesMode>, Option<Assets>);
143}
144
145#[impl_trait_for_tuples::impl_for_tuples(30)]
147impl EnsureDelivery for Tuple {
148 fn ensure_successful_delivery(
149 origin_ref: &Location,
150 dest: &Location,
151 fee_reason: FeeReason,
152 ) -> (Option<FeesMode>, Option<Assets>) {
153 for_tuples!( #(
154 match Tuple::ensure_successful_delivery(origin_ref, dest, fee_reason.clone()) {
156 r @ (Some(_), Some(_)) | r @ (Some(_), None) | r @ (None, Some(_)) => return r,
157 (None, None) => (),
158 }
159 )* );
160 (None, None)
162 }
163}
164
165pub trait InspectMessageQueues {
168 fn clear_messages();
171 fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)>;
173}
174
175#[impl_trait_for_tuples::impl_for_tuples(30)]
176impl InspectMessageQueues for Tuple {
177 fn clear_messages() {
178 for_tuples!( #(
179 Tuple::clear_messages();
180 )* );
181 }
182
183 fn get_messages() -> Vec<(VersionedLocation, Vec<VersionedXcm<()>>)> {
184 let mut messages = Vec::new();
185
186 for_tuples!( #(
187 messages.append(&mut Tuple::get_messages());
188 )* );
189
190 messages
191 }
192}
193
194pub struct EnsureDecodableXcm<Inner>(core::marker::PhantomData<Inner>);
203impl<Inner: SendXcm> SendXcm for EnsureDecodableXcm<Inner> {
204 type Ticket = Inner::Ticket;
205
206 fn validate(
207 destination: &mut Option<Location>,
208 message: &mut Option<Xcm<()>>,
209 ) -> SendResult<Self::Ticket> {
210 if let Some(msg) = message {
211 let versioned_xcm = VersionedXcm::<()>::from(msg.clone());
212 if versioned_xcm.check_is_decodable().is_err() {
213 tracing::debug!(
214 target: "xcm::validate_xcm_nesting",
215 ?versioned_xcm,
216 ?msg,
217 "EnsureDecodableXcm `validate_xcm_nesting` failed"
218 );
219 return Err(SendError::Transport("EnsureDecodableXcm validate_xcm_nesting error"))
220 }
221 }
222 Inner::validate(destination, message)
223 }
224
225 fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
226 Inner::deliver(ticket)
227 }
228
229 #[cfg(feature = "runtime-benchmarks")]
230 fn ensure_successful_delivery(location: Option<Location>) {
231 Inner::ensure_successful_delivery(location);
232 }
233}