referrerpolicy=no-referrer-when-downgrade

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 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				// This handle assume we abort on the first fatal error.
93				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					// Inherents are before any other extrinsics.
121					// And signed extrinsics are not inherents.
122					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					// Inherents are before any other extrinsics.
149					// No module marked it as inherent, thus it is not.
150					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					// Inherents must be bare extrinsics.
193					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}