frame_support_procedural/construct_runtime/expand/
inherent.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License
17
18use 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				// This handle assume we abort on the first fatal error.
98				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					// Inherents are before any other extrinsics.
125					// And signed extrinsics are not inherents.
126					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					// Inherents are before any other extrinsics.
153					// No module marked it as inherent thus it is not.
154					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									// Signed extrinsics are not inherents.
178									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					// Signed extrinsics are never inherents.
214					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; // Safe since we are in an `enumerate` loop.
247					}
248				}
249
250				Ok(num_inherents)
251			}
252		}
253	}
254}