cumulus_pallet_parachain_system_proc_macro/
lib.rs1use proc_macro2::Span;
18use proc_macro_crate::{crate_name, FoundCrate};
19use syn::{
20 parse::{Parse, ParseStream},
21 spanned::Spanned,
22 token, Error, Ident, Path,
23};
24
25mod keywords {
26 syn::custom_keyword!(Runtime);
27 syn::custom_keyword!(BlockExecutor);
28 syn::custom_keyword!(CheckInherents);
29}
30
31struct Input {
32 runtime: Path,
33 block_executor: Path,
34}
35
36impl Parse for Input {
37 fn parse(input: ParseStream) -> Result<Self, Error> {
38 let mut runtime = None;
39 let mut block_executor = None;
40
41 fn parse_inner<KW: Parse + Spanned>(
42 input: ParseStream,
43 result: &mut Option<Path>,
44 ) -> Result<(), Error> {
45 let kw = input.parse::<KW>()?;
46
47 if result.is_none() {
48 input.parse::<token::Eq>()?;
49 *result = Some(input.parse::<Path>()?);
50 if input.peek(token::Comma) {
51 input.parse::<token::Comma>()?;
52 }
53
54 Ok(())
55 } else {
56 Err(Error::new(kw.span(), "Is only allowed to be passed once"))
57 }
58 }
59
60 while !input.is_empty() || runtime.is_none() || block_executor.is_none() {
61 let lookahead = input.lookahead1();
62
63 if lookahead.peek(keywords::Runtime) {
64 parse_inner::<keywords::Runtime>(input, &mut runtime)?;
65 } else if lookahead.peek(keywords::BlockExecutor) {
66 parse_inner::<keywords::BlockExecutor>(input, &mut block_executor)?;
67 } else if lookahead.peek(keywords::CheckInherents) {
68 return Err(Error::new(input.span(), "`CheckInherents` is not supported anymore!"));
69 } else {
70 return Err(lookahead.error());
71 }
72 }
73
74 Ok(Self {
75 runtime: runtime.expect("Everything is parsed before; qed"),
76 block_executor: block_executor.expect("Everything is parsed before; qed"),
77 })
78 }
79}
80
81fn crate_() -> Result<Ident, Error> {
82 match crate_name("cumulus-pallet-parachain-system") {
83 Ok(FoundCrate::Itself) => {
84 Ok(syn::Ident::new("cumulus_pallet_parachain_system", Span::call_site()))
85 },
86 Ok(FoundCrate::Name(name)) => Ok(Ident::new(&name, Span::call_site())),
87 Err(e) => Err(Error::new(Span::call_site(), e)),
88 }
89}
90
91#[proc_macro]
92pub fn register_validate_block(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
93 let Input { runtime, block_executor } = match syn::parse(input) {
94 Ok(t) => t,
95 Err(e) => return e.into_compile_error().into(),
96 };
97
98 let crate_ = match crate_() {
99 Ok(c) => c,
100 Err(e) => return e.into_compile_error().into(),
101 };
102
103 if cfg!(not(feature = "std")) {
104 quote::quote! {
105 #[doc(hidden)]
106 mod parachain_validate_block {
107 use super::*;
108
109 #[no_mangle]
110 #[cfg_attr(
111 target_arch = "riscv64",
112 #crate_::validate_block::sp_api::__private::polkavm_export(abi = #crate_::validate_block::sp_api::__private::polkavm_abi)
113 )]
114 unsafe fn validate_block(arguments: *mut u8, arguments_len: usize) -> u64 {
115 let args = #crate_::validate_block::Box::from_raw(
117 #crate_::validate_block::slice::from_raw_parts_mut(
118 arguments,
119 arguments_len,
120 )
121 );
122 let args = #crate_::validate_block::bytes::Bytes::from(args);
123
124 let params = #crate_::validate_block::decode_from_bytes::<
126 #crate_::validate_block::MemoryOptimizedValidationParams
127 >(args).expect("Invalid arguments to `validate_block`.");
128
129 let res = #crate_::validate_block::implementation::validate_block::<
130 <#runtime as #crate_::validate_block::GetRuntimeBlockType>::RuntimeBlock,
131 #block_executor,
132 #runtime,
133 >(params);
134
135 #crate_::validate_block::polkadot_parachain_primitives::write_result(&res)
136 }
137 }
138 }
139 } else {
140 quote::quote!()
141 }
142 .into()
143}