frame_support_procedural/construct_runtime/expand/
inherent.rs1use crate::construct_runtime::Pallet;
19use proc_macro2::TokenStream;
20use quote::quote;
21use std::str::FromStr;
22use syn::Ident;
23
24pub fn expand_outer_inherent(
25 runtime: &Ident,
26 block: &TokenStream,
27 unchecked_extrinsic: &TokenStream,
28 pallet_decls: &[Pallet],
29 scrate: &TokenStream,
30) -> TokenStream {
31 let mut pallet_names = Vec::new();
32 let mut pallet_attrs = Vec::new();
33 let mut query_inherent_part_macros = Vec::new();
34
35 for pallet_decl in pallet_decls {
36 if pallet_decl.exists_part("Inherent") {
37 let name = &pallet_decl.name;
38 let path = &pallet_decl.path;
39 let attr = pallet_decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| {
40 let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original()))
41 .expect("was successfully parsed before; qed");
42 quote! {
43 #acc
44 #attr
45 }
46 });
47
48 pallet_names.push(name);
49 pallet_attrs.push(attr);
50 query_inherent_part_macros.push(quote! {
51 #path::__substrate_inherent_check::is_inherent_part_defined!(#name);
52 });
53 }
54 }
55
56 quote! {
57 #( #query_inherent_part_macros )*
58
59 trait InherentDataExt {
60 fn create_extrinsics(&self) ->
61 #scrate::__private::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic>;
62 fn check_extrinsics(&self, block: &#block) -> #scrate::inherent::CheckInherentsResult;
63 }
64
65 impl InherentDataExt for #scrate::inherent::InherentData {
66 fn create_extrinsics(&self) ->
67 #scrate::__private::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic>
68 {
69 use #scrate::inherent::ProvideInherent;
70
71 let mut inherents = #scrate::__private::Vec::new();
72
73 #(
74 #pallet_attrs
75 if let Some(inherent) = #pallet_names::create_inherent(self) {
76 let inherent = <#unchecked_extrinsic as #scrate::sp_runtime::traits::Extrinsic>::new(
77 inherent.into(),
78 None,
79 ).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return \
80 `Some`; qed");
81
82 inherents.push(inherent);
83 }
84 )*
85
86 inherents
87 }
88
89 fn check_extrinsics(&self, block: &#block) -> #scrate::inherent::CheckInherentsResult {
90 use #scrate::inherent::{ProvideInherent, IsFatalError};
91 use #scrate::traits::{IsSubType, ExtrinsicCall};
92 use #scrate::sp_runtime::traits::Block as _;
93 use #scrate::__private::{sp_inherents::Error, log};
94
95 let mut result = #scrate::inherent::CheckInherentsResult::new();
96
97 fn handle_put_error_result(res: Result<(), Error>) {
99 const LOG_TARGET: &str = "runtime::inherent";
100 match res {
101 Ok(()) => (),
102 Err(Error::InherentDataExists(id)) =>
103 log::debug!(
104 target: LOG_TARGET,
105 "Some error already reported for inherent {:?}, new non fatal \
106 error is ignored",
107 id
108 ),
109 Err(Error::FatalErrorReported) =>
110 log::error!(
111 target: LOG_TARGET,
112 "Fatal error already reported, unexpected considering there is \
113 only one fatal error",
114 ),
115 Err(_) =>
116 log::error!(
117 target: LOG_TARGET,
118 "Unexpected error from `put_error` operation",
119 ),
120 }
121 }
122
123 for xt in block.extrinsics() {
124 if #scrate::sp_runtime::traits::Extrinsic::is_signed(xt).unwrap_or(false) {
127 break
128 }
129
130 let mut is_inherent = false;
131
132 #(
133 #pallet_attrs
134 {
135 let call = <#unchecked_extrinsic as ExtrinsicCall>::call(xt);
136 if let Some(call) = IsSubType::<_>::is_sub_type(call) {
137 if #pallet_names::is_inherent(call) {
138 is_inherent = true;
139 if let Err(e) = #pallet_names::check_inherent(call, self) {
140 handle_put_error_result(result.put_error(
141 #pallet_names::INHERENT_IDENTIFIER, &e
142 ));
143 if e.is_fatal_error() {
144 return result;
145 }
146 }
147 }
148 }
149 }
150 )*
151
152 if !is_inherent {
155 break
156 }
157 }
158
159 #(
160 #pallet_attrs
161 match #pallet_names::is_inherent_required(self) {
162 Ok(Some(e)) => {
163 let found = block.extrinsics().iter().any(|xt| {
164 let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt)
165 .unwrap_or(false);
166
167 if !is_signed {
168 let call = <
169 #unchecked_extrinsic as ExtrinsicCall
170 >::call(xt);
171 if let Some(call) = IsSubType::<_>::is_sub_type(call) {
172 #pallet_names::is_inherent(&call)
173 } else {
174 false
175 }
176 } else {
177 false
179 }
180 });
181
182 if !found {
183 handle_put_error_result(result.put_error(
184 #pallet_names::INHERENT_IDENTIFIER, &e
185 ));
186 if e.is_fatal_error() {
187 return result;
188 }
189 }
190 },
191 Ok(None) => (),
192 Err(e) => {
193 handle_put_error_result(result.put_error(
194 #pallet_names::INHERENT_IDENTIFIER, &e
195 ));
196 if e.is_fatal_error() {
197 return result;
198 }
199 },
200 }
201 )*
202
203 result
204 }
205 }
206
207 impl #scrate::traits::IsInherent<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic> for #runtime {
208 fn is_inherent(ext: &<#block as #scrate::sp_runtime::traits::Block>::Extrinsic) -> bool {
209 use #scrate::inherent::ProvideInherent;
210 use #scrate::traits::{IsSubType, ExtrinsicCall};
211
212 if #scrate::sp_runtime::traits::Extrinsic::is_signed(ext).unwrap_or(false) {
213 return false
215 }
216
217 #(
218 #pallet_attrs
219 {
220 let call = <#unchecked_extrinsic as ExtrinsicCall>::call(ext);
221 if let Some(call) = IsSubType::<_>::is_sub_type(call) {
222 if <#pallet_names as ProvideInherent>::is_inherent(&call) {
223 return true;
224 }
225 }
226 }
227 )*
228 false
229 }
230 }
231
232 impl #scrate::traits::EnsureInherentsAreFirst<#block> for #runtime {
233 fn ensure_inherents_are_first(block: &#block) -> Result<u32, u32> {
234 use #scrate::inherent::ProvideInherent;
235 use #scrate::traits::{IsSubType, ExtrinsicCall};
236 use #scrate::sp_runtime::traits::Block as _;
237
238 let mut num_inherents = 0u32;
239
240 for (i, xt) in block.extrinsics().iter().enumerate() {
241 if <Self as #scrate::traits::IsInherent<_>>::is_inherent(xt) {
242 if num_inherents != i as u32 {
243 return Err(i as u32);
244 }
245
246 num_inherents += 1; }
248 }
249
250 Ok(num_inherents)
251 }
252 }
253 }
254}