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