1use external_memory_tools::ExternalMemory;
2use frame_metadata::{
3 v14::{
4 PalletCallMetadata, PalletConstantMetadata, PalletErrorMetadata, PalletEventMetadata,
5 PalletMetadata as PalletMetadataV14, PalletStorageMetadata, RuntimeMetadataV14,
6 },
7 v15::{PalletMetadata as PalletMetadataV15, RuntimeMetadataV15},
8};
9use scale_info::form::PortableForm;
10use substrate_parser::{
11 cards::ParsedData,
12 decode_all_as_type,
13 error::{MetaStructureErrorV14, MetaVersionErrorPallets},
14 special_indicators::SpecialtyUnsignedInteger,
15 traits::{
16 version_constant_data_and_ty_v14, version_constant_data_and_ty_v15, AsCompleteMetadata,
17 },
18};
19
20use std::fmt::Debug;
21
22#[derive(Clone, Debug, Eq, PartialEq)]
23pub enum Unsigned {
24 U8(u8),
25 U16(u16),
26 U32(u32),
27 U64(u64),
28 U128(u128),
29}
30
31pub trait AsPalletMetadata<E: ExternalMemory> {
32 fn name(&self) -> String;
33 fn storage(&self) -> Option<PalletStorageMetadata<PortableForm>>;
34 fn calls(&self) -> Option<PalletCallMetadata<PortableForm>>;
35 fn event(&self) -> Option<PalletEventMetadata<PortableForm>>;
36 fn constants(&self) -> Vec<PalletConstantMetadata<PortableForm>>;
37 fn error(&self) -> Option<PalletErrorMetadata<PortableForm>>;
38 fn index(&self) -> u8;
39}
40
41macro_rules! impl_as_pallet_metadata {
42 ($($ty:ty), *) => {
43 $(
44 impl <E: ExternalMemory> AsPalletMetadata<E> for $ty {
45 fn name(&self) -> String {
46 self.name.to_owned()
47 }
48 fn storage(&self) -> Option<PalletStorageMetadata<PortableForm>> {
49 self.storage.to_owned()
50 }
51 fn calls(&self) -> Option<PalletCallMetadata<PortableForm>> {
52 self.calls.to_owned()
53 }
54 fn event(&self) -> Option<PalletEventMetadata<PortableForm>> {
55 self.event.to_owned()
56 }
57 fn constants(&self) -> Vec<PalletConstantMetadata<PortableForm>> {
58 self.constants.to_owned()
59 }
60 fn error(&self) -> Option<PalletErrorMetadata<PortableForm>> {
61 self.error.to_owned()
62 }
63 fn index(&self) -> u8 {
64 self.index
65 }
66 }
67 )*
68 }
69}
70
71impl_as_pallet_metadata!(
72 PalletMetadataV14<PortableForm>,
73 PalletMetadataV15<PortableForm>
74);
75
76pub trait AsFillMetadata<E: ExternalMemory>: AsCompleteMetadata<E> {
77 type PalletMetadata: AsPalletMetadata<E> + Clone + Debug;
78 fn pallets(&self) -> Vec<Self::PalletMetadata>;
79 fn defined_tx_version(&self) -> Option<Unsigned>;
80 fn spec_version(&self) -> Result<Unsigned, Self::MetaStructureError>;
81}
82
83macro_rules! impl_as_fill_metadata {
86 ($($ty:ty, $ty_pallet_metadata:ty, $func:ident, $err:expr), *) => {
87 $(
88 impl <E: ExternalMemory> AsFillMetadata<E> for $ty {
89 type PalletMetadata = $ty_pallet_metadata;
90 fn pallets(&self) -> Vec<Self::PalletMetadata> {
91 self.pallets.to_owned()
92 }
93 fn defined_tx_version(&self) -> Option<Unsigned> {
94 match $func(&self.pallets) {
95 Ok((version_data, version_ty)) => {
96 match decode_all_as_type::<&[u8], (), $ty>(
97 &version_ty,
98 &version_data.as_ref(),
99 &mut (),
100 &self.types,
101 ) {
102 Ok(extended_data) => tx_version(
103 extended_data.data,
104 ),
105 Err(_) => None,
106 }
107 },
108 Err(_) => None,
109 }
110 }
111 fn spec_version(&self) -> Result<Unsigned, Self::MetaStructureError> {
112 let (version_data, version_ty) = $func(&self.pallets)?;
113 match decode_all_as_type::<&[u8], (), $ty>(
114 &version_ty,
115 &version_data.as_ref(),
116 &mut (),
117 &self.types,
118 ) {
119 Ok(extended_data) => Ok(spec_version(
120 extended_data.data,
121 )?),
122 Err(_) => Err($err),
123 }
124 }
125 }
126 )*
127 }
128}
129
130impl_as_fill_metadata!(
131 RuntimeMetadataV14,
132 PalletMetadataV14<PortableForm>,
133 version_constant_data_and_ty_v14,
134 MetaStructureErrorV14::Version(MetaVersionErrorPallets::RuntimeVersionNotDecodeable)
135);
136impl_as_fill_metadata!(
137 RuntimeMetadataV15,
138 PalletMetadataV15<PortableForm>,
139 version_constant_data_and_ty_v15,
140 MetaVersionErrorPallets::RuntimeVersionNotDecodeable
141);
142
143fn spec_version(parsed_data: ParsedData) -> Result<Unsigned, MetaVersionErrorPallets> {
145 let mut spec_version = None;
146
147 if let ParsedData::Composite(fields) = parsed_data {
148 for field in fields.iter() {
149 match &field.data.data {
150 ParsedData::PrimitiveU8 {
151 value,
152 specialty: SpecialtyUnsignedInteger::SpecVersion,
153 } => {
154 if spec_version.is_none() {
155 spec_version = Some(Unsigned::U8(*value))
156 } else {
157 return Err(MetaVersionErrorPallets::SpecVersionIdentifierTwice);
158 }
159 }
160 ParsedData::PrimitiveU16 {
161 value,
162 specialty: SpecialtyUnsignedInteger::SpecVersion,
163 } => {
164 if spec_version.is_none() {
165 spec_version = Some(Unsigned::U16(*value))
166 } else {
167 return Err(MetaVersionErrorPallets::SpecVersionIdentifierTwice);
168 }
169 }
170 ParsedData::PrimitiveU32 {
171 value,
172 specialty: SpecialtyUnsignedInteger::SpecVersion,
173 } => {
174 if spec_version.is_none() {
175 spec_version = Some(Unsigned::U32(*value))
176 } else {
177 return Err(MetaVersionErrorPallets::SpecVersionIdentifierTwice);
178 }
179 }
180 ParsedData::PrimitiveU64 {
181 value,
182 specialty: SpecialtyUnsignedInteger::SpecVersion,
183 } => {
184 if spec_version.is_none() {
185 spec_version = Some(Unsigned::U64(*value))
186 } else {
187 return Err(MetaVersionErrorPallets::SpecVersionIdentifierTwice);
188 }
189 }
190 ParsedData::PrimitiveU128 {
191 value,
192 specialty: SpecialtyUnsignedInteger::SpecVersion,
193 } => {
194 if spec_version.is_none() {
195 spec_version = Some(Unsigned::U128(*value))
196 } else {
197 return Err(MetaVersionErrorPallets::SpecVersionIdentifierTwice);
198 }
199 }
200 _ => (),
201 }
202 }
203 } else {
204 return Err(MetaVersionErrorPallets::UnexpectedRuntimeVersionFormat);
205 }
206 spec_version.ok_or(MetaVersionErrorPallets::NoSpecVersionIdentifier)
207}
208
209fn tx_version(parsed_data: ParsedData) -> Option<Unsigned> {
213 let mut tx_version = None;
214
215 if let ParsedData::Composite(fields) = parsed_data {
216 for field in fields.iter() {
217 match &field.data.data {
218 ParsedData::PrimitiveU8 {
219 value,
220 specialty: SpecialtyUnsignedInteger::TxVersion,
221 } => {
222 if tx_version.is_none() {
223 tx_version = Some(Unsigned::U8(*value))
224 } else {
225 return None;
226 }
227 }
228 ParsedData::PrimitiveU16 {
229 value,
230 specialty: SpecialtyUnsignedInteger::TxVersion,
231 } => {
232 if tx_version.is_none() {
233 tx_version = Some(Unsigned::U16(*value))
234 } else {
235 return None;
236 }
237 }
238 ParsedData::PrimitiveU32 {
239 value,
240 specialty: SpecialtyUnsignedInteger::TxVersion,
241 } => {
242 if tx_version.is_none() {
243 tx_version = Some(Unsigned::U32(*value))
244 } else {
245 return None;
246 }
247 }
248 ParsedData::PrimitiveU64 {
249 value,
250 specialty: SpecialtyUnsignedInteger::TxVersion,
251 } => {
252 if tx_version.is_none() {
253 tx_version = Some(Unsigned::U64(*value))
254 } else {
255 return None;
256 }
257 }
258 ParsedData::PrimitiveU128 {
259 value,
260 specialty: SpecialtyUnsignedInteger::TxVersion,
261 } => {
262 if tx_version.is_none() {
263 tx_version = Some(Unsigned::U128(*value))
264 } else {
265 return None;
266 }
267 }
268 _ => (),
269 }
270 }
271 } else {
272 return None;
273 }
274 tx_version
275}