frame_support_procedural/construct_runtime/expand/
call.rs1use crate::construct_runtime::Pallet;
19use proc_macro2::TokenStream;
20use quote::quote;
21use std::str::FromStr;
22use syn::Ident;
23
24pub fn expand_outer_dispatch(
25 runtime: &Ident,
26 system_pallet: &Pallet,
27 pallet_decls: &[Pallet],
28 scrate: &TokenStream,
29) -> TokenStream {
30 let mut variant_defs = TokenStream::new();
31 let mut variant_patterns = Vec::new();
32 let mut query_call_part_macros = Vec::new();
33 let mut pallet_names = Vec::new();
34 let mut pallet_attrs = Vec::new();
35 let system_path = &system_pallet.path;
36
37 let pallets_with_call = pallet_decls.iter().filter(|decl| decl.exists_part("Call"));
38
39 for pallet_declaration in pallets_with_call {
40 let name = &pallet_declaration.name;
41 let path = &pallet_declaration.path;
42 let index = pallet_declaration.index;
43 let attr =
44 pallet_declaration.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| {
45 let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original()))
46 .expect("was successfully parsed before; qed");
47 quote! {
48 #acc
49 #attr
50 }
51 });
52
53 variant_defs.extend(quote! {
54 #attr
55 #[codec(index = #index)]
56 #name( #scrate::dispatch::CallableCallFor<#name, #runtime> ),
57 });
58 variant_patterns.push(quote!(RuntimeCall::#name(call)));
59 pallet_names.push(name);
60 pallet_attrs.push(attr);
61 query_call_part_macros.push(quote! {
62 #path::__substrate_call_check::is_call_part_defined!(#name);
63 });
64 }
65
66 quote! {
67 #( #query_call_part_macros )*
68
69 #[derive(
71 Clone, PartialEq, Eq,
72 #scrate::__private::codec::Encode,
73 #scrate::__private::codec::Decode,
74 #scrate::__private::scale_info::TypeInfo,
75 #scrate::__private::RuntimeDebug,
76 )]
77 pub enum RuntimeCall {
78 #variant_defs
79 }
80 #[cfg(test)]
81 impl RuntimeCall {
82 pub const fn sizes() -> &'static [( &'static str, usize )] {
84 use #scrate::dispatch::Callable;
85 use core::mem::size_of;
86 &[#(
87 #pallet_attrs
88 (
89 stringify!(#pallet_names),
90 size_of::< <#pallet_names as Callable<#runtime>>::RuntimeCall >(),
91 ),
92 )*]
93 }
94
95 pub fn assert_size_under(limit: usize) {
97 let size = core::mem::size_of::<Self>();
98 let call_oversize = size > limit;
99 if call_oversize {
100 println!("Size of `Call` is {} bytes (provided limit is {} bytes)", size, limit);
101 let mut sizes = Self::sizes().to_vec();
102 sizes.sort_by_key(|x| -(x.1 as isize));
103 for (i, &(name, size)) in sizes.iter().enumerate().take(5) {
104 println!("Offender #{}: {} at {} bytes", i + 1, name, size);
105 }
106 if let Some((_, next_size)) = sizes.get(5) {
107 println!("{} others of size {} bytes or less", sizes.len() - 5, next_size);
108 }
109 panic!(
110 "Size of `Call` is more than limit; use `Box` on complex parameter types to reduce the
111 size of `Call`.
112 If the limit is too strong, maybe consider providing a higher limit."
113 );
114 }
115 }
116 }
117 impl #scrate::dispatch::GetDispatchInfo for RuntimeCall {
118 fn get_dispatch_info(&self) -> #scrate::dispatch::DispatchInfo {
119 match self {
120 #(
121 #pallet_attrs
122 #variant_patterns => call.get_dispatch_info(),
123 )*
124 }
125 }
126 }
127
128 impl #scrate::dispatch::CheckIfFeeless for RuntimeCall {
129 type Origin = #system_path::pallet_prelude::OriginFor<#runtime>;
130 fn is_feeless(&self, origin: &Self::Origin) -> bool {
131 match self {
132 #(
133 #pallet_attrs
134 #variant_patterns => call.is_feeless(origin),
135 )*
136 }
137 }
138 }
139
140 impl #scrate::traits::GetCallMetadata for RuntimeCall {
141 fn get_call_metadata(&self) -> #scrate::traits::CallMetadata {
142 use #scrate::traits::GetCallName;
143 match self {
144 #(
145 #pallet_attrs
146 #variant_patterns => {
147 let function_name = call.get_call_name();
148 let pallet_name = stringify!(#pallet_names);
149 #scrate::traits::CallMetadata { function_name, pallet_name }
150 }
151 )*
152 }
153 }
154
155 fn get_module_names() -> &'static [&'static str] {
156 &[#(
157 #pallet_attrs
158 stringify!(#pallet_names),
159 )*]
160 }
161
162 fn get_call_names(module: &str) -> &'static [&'static str] {
163 use #scrate::{dispatch::Callable, traits::GetCallName};
164 match module {
165 #(
166 #pallet_attrs
167 stringify!(#pallet_names) =>
168 <<#pallet_names as Callable<#runtime>>::RuntimeCall
169 as GetCallName>::get_call_names(),
170 )*
171 _ => unreachable!(),
172 }
173 }
174 }
175 impl #scrate::__private::Dispatchable for RuntimeCall {
176 type RuntimeOrigin = RuntimeOrigin;
177 type Config = RuntimeCall;
178 type Info = #scrate::dispatch::DispatchInfo;
179 type PostInfo = #scrate::dispatch::PostDispatchInfo;
180 fn dispatch(self, origin: RuntimeOrigin) -> #scrate::dispatch::DispatchResultWithPostInfo {
181 if !<Self::RuntimeOrigin as #scrate::traits::OriginTrait>::filter_call(&origin, &self) {
182 return ::core::result::Result::Err(
183 #system_path::Error::<#runtime>::CallFiltered.into()
184 );
185 }
186
187 #scrate::traits::UnfilteredDispatchable::dispatch_bypass_filter(self, origin)
188 }
189 }
190 impl #scrate::traits::UnfilteredDispatchable for RuntimeCall {
191 type RuntimeOrigin = RuntimeOrigin;
192 fn dispatch_bypass_filter(self, origin: RuntimeOrigin) -> #scrate::dispatch::DispatchResultWithPostInfo {
193 match self {
194 #(
195 #pallet_attrs
196 #variant_patterns =>
197 #scrate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, origin),
198 )*
199 }
200 }
201 }
202
203 #(
204 #pallet_attrs
205 impl #scrate::traits::IsSubType<#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> for RuntimeCall {
206 #[allow(unreachable_patterns)]
207 fn is_sub_type(&self) -> Option<&#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> {
208 match self {
209 #variant_patterns => Some(call),
210 _ => None,
212 }
213 }
214 }
215
216 #pallet_attrs
217 impl From<#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> for RuntimeCall {
218 fn from(call: #scrate::dispatch::CallableCallFor<#pallet_names, #runtime>) -> Self {
219 #variant_patterns
220 }
221 }
222 )*
223 }
224}