frame_support_procedural/construct_runtime/expand/
inherent.rs1use crate::construct_runtime::Pallet;
19use proc_macro2::TokenStream;
20use quote::quote;
21use syn::Ident;
22
23pub fn expand_outer_inherent(
24 runtime: &Ident,
25 block: &TokenStream,
26 unchecked_extrinsic: &TokenStream,
27 pallet_decls: &[Pallet],
28 scrate: &TokenStream,
29) -> TokenStream {
30 let mut pallet_positions = Vec::new();
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_pos, pallet_decl) in pallet_decls
36 .iter()
37 .filter(|pallet_decl| pallet_decl.exists_part("Inherent"))
38 .enumerate()
39 {
40 let name = &pallet_decl.name;
41 let path = &pallet_decl.path;
42 let attr = pallet_decl.get_attributes();
43
44 pallet_positions.push(pallet_pos);
45 pallet_names.push(name);
46 pallet_attrs.push(attr);
47 query_inherent_part_macros.push(quote! {
48 #path::__substrate_inherent_check::is_inherent_part_defined!(#name);
49 });
50 }
51 let pallet_count = pallet_positions.len();
52
53 quote! {
54 #( #query_inherent_part_macros )*
55
56 trait InherentDataExt {
57 fn create_extrinsics(&self) ->
58 #scrate::__private::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic>;
59 fn check_extrinsics(&self, block: &#block) -> #scrate::inherent::CheckInherentsResult;
60 }
61
62 impl InherentDataExt for #scrate::inherent::InherentData {
63 fn create_extrinsics(&self) ->
64 #scrate::__private::Vec<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic>
65 {
66 use #scrate::{inherent::ProvideInherent, traits::InherentBuilder};
67
68 let mut inherents = #scrate::__private::Vec::new();
69
70 #(
71 #pallet_attrs
72 if let Some(inherent) = #pallet_names::create_inherent(self) {
73 let inherent = <#unchecked_extrinsic as InherentBuilder>::new_inherent(
74 inherent.into(),
75 );
76
77 inherents.push(inherent);
78 }
79 )*
80
81 inherents
82 }
83
84 fn check_extrinsics(&self, block: &#block) -> #scrate::inherent::CheckInherentsResult {
85 use #scrate::inherent::{ProvideInherent, IsFatalError};
86 use #scrate::traits::IsSubType;
87 use #scrate::sp_runtime::traits::{Block as _, ExtrinsicCall};
88 use #scrate::__private::{sp_inherents::Error, log};
89
90 let mut result = #scrate::inherent::CheckInherentsResult::new();
91
92 fn handle_put_error_result(res: Result<(), Error>) {
94 const LOG_TARGET: &str = "runtime::inherent";
95 match res {
96 Ok(()) => (),
97 Err(Error::InherentDataExists(id)) =>
98 log::debug!(
99 target: LOG_TARGET,
100 "Some error already reported for inherent {:?}, new non fatal \
101 error is ignored",
102 id
103 ),
104 Err(Error::FatalErrorReported) =>
105 log::error!(
106 target: LOG_TARGET,
107 "Fatal error already reported, unexpected considering there is \
108 only one fatal error",
109 ),
110 Err(_) =>
111 log::error!(
112 target: LOG_TARGET,
113 "Unexpected error from `put_error` operation",
114 ),
115 }
116 }
117
118 let mut pallet_has_inherent = [false; #pallet_count];
119 for xt in block.extrinsics() {
120 if !(#scrate::sp_runtime::traits::ExtrinsicLike::is_bare(xt)) {
123 break
124 }
125
126 let mut is_inherent = false;
127 let call = ExtrinsicCall::call(xt);
128 #(
129 #pallet_attrs
130 {
131 if let Some(call) = IsSubType::<_>::is_sub_type(call) {
132 if #pallet_names::is_inherent(call) {
133 is_inherent = true;
134 pallet_has_inherent[#pallet_positions] = true;
135 if let Err(e) = #pallet_names::check_inherent(call, self) {
136 handle_put_error_result(result.put_error(
137 #pallet_names::INHERENT_IDENTIFIER, &e
138 ));
139 if e.is_fatal_error() {
140 return result;
141 }
142 }
143 }
144 }
145 }
146 )*
147
148 if !is_inherent {
151 break
152 }
153 }
154
155 #(
156 #pallet_attrs
157 match #pallet_names::is_inherent_required(self) {
158 Ok(Some(e)) => {
159 if !pallet_has_inherent[#pallet_positions] {
160 handle_put_error_result(result.put_error(
161 #pallet_names::INHERENT_IDENTIFIER, &e
162 ));
163 if e.is_fatal_error() {
164 return result;
165 }
166 }
167 },
168 Ok(None) => (),
169 Err(e) => {
170 handle_put_error_result(result.put_error(
171 #pallet_names::INHERENT_IDENTIFIER, &e
172 ));
173 if e.is_fatal_error() {
174 return result;
175 }
176 },
177 }
178 )*
179
180 result
181 }
182 }
183
184 impl #scrate::traits::IsInherent<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic> for #runtime {
185 fn is_inherent(ext: &<#block as #scrate::sp_runtime::traits::Block>::Extrinsic) -> bool {
186 use #scrate::inherent::ProvideInherent;
187 use #scrate::traits::IsSubType;
188 use #scrate::sp_runtime::traits::ExtrinsicCall;
189
190 let is_bare = #scrate::sp_runtime::traits::ExtrinsicLike::is_bare(ext);
191 if !is_bare {
192 return false
194 }
195
196 let call = ExtrinsicCall::call(ext);
197 #(
198 #pallet_attrs
199 {
200 if let Some(call) = IsSubType::<_>::is_sub_type(call) {
201 if <#pallet_names as ProvideInherent>::is_inherent(&call) {
202 return true;
203 }
204 }
205 }
206 )*
207 false
208 }
209 }
210 }
211}