frame_support_procedural/construct_runtime/expand/
origin.rs1use crate::construct_runtime::{Pallet, SYSTEM_PALLET_NAME};
19use proc_macro2::TokenStream;
20use quote::quote;
21use syn::{Generics, Ident};
22
23pub fn expand_outer_origin(
24 runtime: &Ident,
25 system_pallet: &Pallet,
26 pallets: &[Pallet],
27 scrate: &TokenStream,
28) -> syn::Result<TokenStream> {
29 let mut caller_variants = TokenStream::new();
30 let mut pallet_conversions = TokenStream::new();
31 let mut query_origin_part_macros = Vec::new();
32
33 for pallet_decl in pallets.iter().filter(|pallet| pallet.name != SYSTEM_PALLET_NAME) {
34 if let Some(pallet_entry) = pallet_decl.find_part("Origin") {
35 let instance = pallet_decl.instance.as_ref();
36 let index = pallet_decl.index;
37 let generics = &pallet_entry.generics;
38 let name = &pallet_decl.name;
39 let path = &pallet_decl.path;
40
41 if instance.is_some() && generics.params.is_empty() {
42 let msg = format!(
43 "Instantiable pallet with no generic `Origin` cannot \
44 be constructed: pallet `{}` must have generic `Origin`",
45 name
46 );
47 return Err(syn::Error::new(name.span(), msg))
48 }
49
50 caller_variants.extend(expand_origin_caller_variant(
51 runtime,
52 pallet_decl,
53 index,
54 instance,
55 generics,
56 ));
57 pallet_conversions.extend(expand_origin_pallet_conversions(
58 scrate,
59 runtime,
60 pallet_decl,
61 instance,
62 generics,
63 ));
64 query_origin_part_macros.push(quote! {
65 #path::__substrate_origin_check::is_origin_part_defined!(#name);
66 });
67 }
68 }
69
70 let system_path = &system_pallet.path;
71
72 let system_index = system_pallet.index;
73
74 let system_path_name = system_path.module_name();
75
76 let doc_string = get_intra_doc_string(
77 "Origin is always created with the base filter configured in",
78 &system_path_name,
79 );
80
81 let doc_string_none_origin =
82 get_intra_doc_string("Create with system none origin and", &system_path_name);
83
84 let doc_string_root_origin =
85 get_intra_doc_string("Create with system root origin and", &system_path_name);
86
87 let doc_string_signed_origin =
88 get_intra_doc_string("Create with system signed origin and", &system_path_name);
89
90 let doc_string_runtime_origin =
91 get_intra_doc_string("Convert to runtime origin, using as filter:", &system_path_name);
92
93 let doc_string_runtime_origin_with_caller = get_intra_doc_string(
94 "Convert to runtime origin with caller being system signed or none and use filter",
95 &system_path_name,
96 );
97
98 Ok(quote! {
99 #( #query_origin_part_macros )*
100
101 #[doc = #doc_string]
104 #[derive(Clone)]
105 pub struct RuntimeOrigin {
106 pub caller: OriginCaller,
107 filter: #scrate::__private::Rc<#scrate::__private::Box<dyn Fn(&<#runtime as #system_path::Config>::RuntimeCall) -> bool>>,
108 }
109
110 impl core::fmt::Debug for RuntimeOrigin {
111 fn fmt(
112 &self,
113 fmt: &mut core::fmt::Formatter,
114 ) -> core::result::Result<(), core::fmt::Error> {
115 fmt.debug_struct("Origin")
116 .field("caller", &self.caller)
117 .field("filter", &"[function ptr]")
118 .finish()
119 }
120 }
121
122 impl #scrate::traits::OriginTrait for RuntimeOrigin {
123 type Call = <#runtime as #system_path::Config>::RuntimeCall;
124 type PalletsOrigin = OriginCaller;
125 type AccountId = <#runtime as #system_path::Config>::AccountId;
126
127 fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static) {
128 let f = self.filter.clone();
129
130 self.filter = #scrate::__private::Rc::new(#scrate::__private::Box::new(move |call| {
131 f(call) && filter(call)
132 }));
133 }
134
135 fn reset_filter(&mut self) {
136 let filter = <
137 <#runtime as #system_path::Config>::BaseCallFilter
138 as #scrate::traits::Contains<<#runtime as #system_path::Config>::RuntimeCall>
139 >::contains;
140
141 self.filter = #scrate::__private::Rc::new(#scrate::__private::Box::new(filter));
142 }
143
144 fn set_caller(&mut self, caller: OriginCaller) {
145 self.caller = caller;
146 }
147
148 fn set_caller_from(&mut self, other: impl Into<Self>) {
149 self.caller = other.into().caller;
150 }
151
152 fn filter_call(&self, call: &Self::Call) -> bool {
153 match self.caller {
154 OriginCaller::system(#system_path::Origin::<#runtime>::Root) => true,
156 _ => (self.filter)(call),
157 }
158 }
159
160 fn caller(&self) -> &Self::PalletsOrigin {
161 &self.caller
162 }
163
164 fn into_caller(self) -> Self::PalletsOrigin {
165 self.caller
166 }
167
168 fn try_with_caller<R>(
169 mut self,
170 f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
171 ) -> Result<R, Self> {
172 match f(self.caller) {
173 Ok(r) => Ok(r),
174 Err(caller) => { self.caller = caller; Err(self) }
175 }
176 }
177
178 fn none() -> Self {
179 #system_path::RawOrigin::None.into()
180 }
181
182 fn root() -> Self {
183 #system_path::RawOrigin::Root.into()
184 }
185
186 fn signed(by: Self::AccountId) -> Self {
187 #system_path::RawOrigin::Signed(by).into()
188 }
189 }
190
191 #[derive(
192 Clone, PartialEq, Eq,
193 #scrate::__private::Debug,
194 #scrate::__private::codec::Encode,
195 #scrate::__private::codec::Decode,
196 #scrate::__private::codec::DecodeWithMemTracking,
197 #scrate::__private::scale_info::TypeInfo,
198 #scrate::__private::codec::MaxEncodedLen,
199 )]
200 #[allow(non_camel_case_types)]
201 pub enum OriginCaller {
202 #[codec(index = #system_index)]
203 system(#system_path::Origin<#runtime>),
204 #caller_variants
205 #[allow(dead_code)]
206 #[codec(skip)]
207 Void(#scrate::__private::Void)
208 }
209
210 #[allow(dead_code)]
212 impl RuntimeOrigin {
213 #[doc = #doc_string_none_origin]
214 pub fn none() -> Self {
215 <RuntimeOrigin as #scrate::traits::OriginTrait>::none()
216 }
217
218 #[doc = #doc_string_root_origin]
219 pub fn root() -> Self {
220 <RuntimeOrigin as #scrate::traits::OriginTrait>::root()
221 }
222
223 #[doc = #doc_string_signed_origin]
224 pub fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self {
225 <RuntimeOrigin as #scrate::traits::OriginTrait>::signed(by)
226 }
227 }
228
229 impl From<#system_path::Origin<#runtime>> for OriginCaller {
230 fn from(x: #system_path::Origin<#runtime>) -> Self {
231 OriginCaller::system(x)
232 }
233 }
234
235 impl #scrate::traits::CallerTrait<<#runtime as #system_path::Config>::AccountId> for OriginCaller {
236 fn into_system(self) -> Option<#system_path::RawOrigin<<#runtime as #system_path::Config>::AccountId>> {
237 match self {
238 OriginCaller::system(x) => Some(x),
239 _ => None,
240 }
241 }
242 fn as_system_ref(&self) -> Option<&#system_path::RawOrigin<<#runtime as #system_path::Config>::AccountId>> {
243 match &self {
244 OriginCaller::system(o) => Some(o),
245 _ => None,
246 }
247 }
248 }
249
250 impl TryFrom<OriginCaller> for #system_path::Origin<#runtime> {
251 type Error = OriginCaller;
252 fn try_from(x: OriginCaller)
253 -> core::result::Result<#system_path::Origin<#runtime>, OriginCaller>
254 {
255 if let OriginCaller::system(l) = x {
256 Ok(l)
257 } else {
258 Err(x)
259 }
260 }
261 }
262
263 impl From<#system_path::Origin<#runtime>> for RuntimeOrigin {
264
265 #[doc = #doc_string_runtime_origin]
266 fn from(x: #system_path::Origin<#runtime>) -> Self {
267 let o: OriginCaller = x.into();
268 o.into()
269 }
270 }
271
272 impl From<OriginCaller> for RuntimeOrigin {
273 fn from(x: OriginCaller) -> Self {
274 let mut o = RuntimeOrigin {
275 caller: x,
276 filter: #scrate::__private::Rc::new(#scrate::__private::Box::new(|_| true)),
277 };
278
279 #scrate::traits::OriginTrait::reset_filter(&mut o);
280
281 o
282 }
283 }
284
285 impl From<RuntimeOrigin> for core::result::Result<#system_path::Origin<#runtime>, RuntimeOrigin> {
286 fn from(val: RuntimeOrigin) -> Self {
288 if let OriginCaller::system(l) = val.caller {
289 Ok(l)
290 } else {
291 Err(val)
292 }
293 }
294 }
295 impl From<Option<<#runtime as #system_path::Config>::AccountId>> for RuntimeOrigin {
296 #[doc = #doc_string_runtime_origin_with_caller]
297 fn from(x: Option<<#runtime as #system_path::Config>::AccountId>) -> Self {
298 <#system_path::Origin<#runtime>>::from(x).into()
299 }
300 }
301
302 impl #scrate::__private::AsSystemOriginSigner<<#runtime as #system_path::Config>::AccountId> for RuntimeOrigin {
303 fn as_system_origin_signer(&self) -> Option<&<#runtime as #system_path::Config>::AccountId> {
304 if let OriginCaller::system(#system_path::Origin::<#runtime>::Signed(ref signed)) = &self.caller {
305 Some(signed)
306 } else {
307 None
308 }
309 }
310 }
311
312 impl #scrate::__private::AsTransactionAuthorizedOrigin for RuntimeOrigin {
313 fn is_transaction_authorized(&self) -> bool {
314 !matches!(&self.caller, OriginCaller::system(#system_path::Origin::<#runtime>::None))
315 }
316 }
317
318 #pallet_conversions
319 })
320}
321
322fn expand_origin_caller_variant(
323 runtime: &Ident,
324 pallet: &Pallet,
325 index: u8,
326 instance: Option<&Ident>,
327 generics: &Generics,
328) -> TokenStream {
329 let part_is_generic = !generics.params.is_empty();
330 let variant_name = &pallet.name;
331 let path = &pallet.path;
332 let attr = pallet.get_attributes();
333
334 match instance {
335 Some(inst) if part_is_generic => quote! {
336 #attr
337 #[codec(index = #index)]
338 #variant_name(#path::Origin<#runtime, #path::#inst>),
339 },
340 Some(inst) => quote! {
341 #attr
342 #[codec(index = #index)]
343 #variant_name(#path::Origin<#path::#inst>),
344 },
345 None if part_is_generic => quote! {
346 #attr
347 #[codec(index = #index)]
348 #variant_name(#path::Origin<#runtime>),
349 },
350 None => quote! {
351 #attr
352 #[codec(index = #index)]
353 #variant_name(#path::Origin),
354 },
355 }
356}
357
358fn expand_origin_pallet_conversions(
359 _scrate: &TokenStream,
360 runtime: &Ident,
361 pallet: &Pallet,
362 instance: Option<&Ident>,
363 generics: &Generics,
364) -> TokenStream {
365 let path = &pallet.path;
366 let variant_name = &pallet.name;
367
368 let part_is_generic = !generics.params.is_empty();
369 let pallet_origin = match instance {
370 Some(inst) if part_is_generic => quote!(#path::Origin<#runtime, #path::#inst>),
371 Some(inst) => quote!(#path::Origin<#path::#inst>),
372 None if part_is_generic => quote!(#path::Origin<#runtime>),
373 None => quote!(#path::Origin),
374 };
375
376 let doc_string = get_intra_doc_string(" Convert to runtime origin using", &path.module_name());
377 let attr = pallet.get_attributes();
378
379 quote! {
380 #attr
381 impl From<#pallet_origin> for OriginCaller {
382 fn from(x: #pallet_origin) -> Self {
383 OriginCaller::#variant_name(x)
384 }
385 }
386
387 #attr
388 impl From<#pallet_origin> for RuntimeOrigin {
389 #[doc = #doc_string]
390 fn from(x: #pallet_origin) -> Self {
391 let x: OriginCaller = x.into();
392 x.into()
393 }
394 }
395
396 #attr
397 impl From<RuntimeOrigin> for core::result::Result<#pallet_origin, RuntimeOrigin> {
398 fn from(val: RuntimeOrigin) -> Self {
400 if let OriginCaller::#variant_name(l) = val.caller {
401 Ok(l)
402 } else {
403 Err(val)
404 }
405 }
406 }
407
408 #attr
409 impl TryFrom<OriginCaller> for #pallet_origin {
410 type Error = OriginCaller;
411 fn try_from(
412 x: OriginCaller,
413 ) -> core::result::Result<#pallet_origin, OriginCaller> {
414 if let OriginCaller::#variant_name(l) = x {
415 Ok(l)
416 } else {
417 Err(x)
418 }
419 }
420 }
421
422 #attr
423 impl<'a> TryFrom<&'a OriginCaller> for &'a #pallet_origin {
424 type Error = ();
425 fn try_from(
426 x: &'a OriginCaller,
427 ) -> core::result::Result<&'a #pallet_origin, ()> {
428 if let OriginCaller::#variant_name(l) = x {
429 Ok(&l)
430 } else {
431 Err(())
432 }
433 }
434 }
435
436 #attr
437 impl<'a> TryFrom<&'a RuntimeOrigin> for &'a #pallet_origin {
438 type Error = ();
439 fn try_from(
440 x: &'a RuntimeOrigin,
441 ) -> core::result::Result<&'a #pallet_origin, ()> {
442 if let OriginCaller::#variant_name(l) = &x.caller {
443 Ok(&l)
444 } else {
445 Err(())
446 }
447 }
448 }
449 }
450}
451
452fn get_intra_doc_string(doc_info: &str, system_path_name: &String) -> String {
454 format!(" {} [`{}::Config::BaseCallFilter`].", doc_info, system_path_name)
455}