1use external_memory_tools::{BufferError, ExternalMemory};
3use primitive_types::H256;
4
5use crate::std::string::String;
6
7#[cfg(feature = "std")]
8use std::{
9 error::Error,
10 fmt::{Display, Formatter, Result as FmtResult},
11};
12
13#[cfg(not(feature = "std"))]
14use core::fmt::{Display, Formatter, Result as FmtResult};
15
16use crate::traits::AsMetadata;
17
18#[derive(Debug, Eq, PartialEq)]
20pub enum SignableError<E, M>
21where
22 E: ExternalMemory,
23 M: AsMetadata<E>,
24{
25 CutSignable,
26 ExtensionsList(ExtensionsError),
27 ImmortalHashMismatch,
28 MetaStructure(M::MetaStructureError),
29 NotACall(u32),
30 Parsing(ParserError<E>),
31 SomeDataNotUsedCall {
32 from: usize,
33 to: usize,
34 },
35 SomeDataNotUsedExtensions {
36 from: usize,
37 },
38 WrongGenesisHash {
39 as_decoded: H256,
40 expected: H256,
41 },
42 WrongSpecVersion {
43 as_decoded: String,
44 in_metadata: String,
45 },
46}
47
48impl<E, M> SignableError<E, M>
49where
50 E: ExternalMemory,
51 M: AsMetadata<E>,
52{
53 fn error_text(&self) -> String {
54 match &self {
55 SignableError::CutSignable => String::from("Unable to separate signable transaction data into call data and extensions data."),
56 SignableError::ExtensionsList(extensions_error) => extensions_error.error_text(),
57 SignableError::ImmortalHashMismatch => String::from("Extensions error. Block hash does not match the chain genesis hash in transaction with immortal `Era`."),
58 SignableError::MetaStructure(meta_structure_error) => format!("Unexpected structure of the metadata. {meta_structure_error}"),
59 SignableError::NotACall(all_calls_ty_id) => format!("Decoded signable transaction is not a call. Unexpected structure of calls descriptor type {all_calls_ty_id}."),
60 SignableError::Parsing(parser_error) => format!("Parsing error. {parser_error}"),
61 SignableError::SomeDataNotUsedCall { from, to } => format!("Some call data (input positions [{from}..{to}]) remained unused after decoding."),
62 SignableError::SomeDataNotUsedExtensions { from } => format!("Some extensions data (input positions [{from}..]) remained unused after decoding."),
63 SignableError::WrongGenesisHash { as_decoded, expected } => format!("Wrong chain. Apparent genesis hash in extensions {} does not match the expected one {}.", hex::encode(as_decoded.0), hex::encode(expected.0)),
64 SignableError::WrongSpecVersion { as_decoded, in_metadata} => format!("Wrong metadata spec version. When decoding extensions data with metadata version {in_metadata}, the apparent spec version in extensions is {as_decoded}."),
65 }
66 }
67}
68
69#[derive(Debug, Eq, PartialEq)]
71pub enum StorageError<E: ExternalMemory> {
72 KeyPartHashMismatch,
73 KeyPartsUnused,
74 KeyShorterThanPrefix,
75 MultipleHashesNotATuple,
76 MultipleHashesNumberMismatch,
77 ParsingKey(ParserError<E>),
78 ParsingValue(ParserError<E>),
79 PlainKeyExceedsPrefix,
80}
81
82impl<E: ExternalMemory> StorageError<E> {
83 fn error_text(&self) -> String {
84 match &self {
85 StorageError::KeyPartHashMismatch => {
86 String::from("Hash part of the storage key does not match the key data.")
87 }
88 StorageError::KeyPartsUnused => {
89 String::from("During the storage key parsing a part of the key remained unused.")
90 }
91 StorageError::KeyShorterThanPrefix => {
92 String::from("Provided storage key is shorter than the expected prefix.")
93 }
94 StorageError::MultipleHashesNotATuple => {
95 String::from("Hashers length is not 1, but the key type is not a tuple.")
96 }
97 StorageError::MultipleHashesNumberMismatch => String::from(
98 "Hashers length does not match the number of fields in a tuple key type.",
99 ),
100 StorageError::ParsingKey(parser_error) => {
101 format!("Error parsing the storage key. {parser_error}")
102 }
103 StorageError::ParsingValue(parser_error) => {
104 format!("Error parsing the storage value. {parser_error}")
105 }
106 StorageError::PlainKeyExceedsPrefix => {
107 String::from("Plain storage key contains data other than the prefix.")
108 }
109 }
110 }
111}
112
113#[derive(Debug, Eq, PartialEq)]
115pub enum ParserError<E: ExternalMemory> {
116 Buffer(BufferError<E>),
117 Registry(RegistryError<E>),
118 NoCompact { position: usize },
119 SomeDataNotUsedBlob { from: usize },
120 TypeFailure { position: usize, ty: &'static str },
121 UnexpectedEnumVariant { position: usize },
122}
123
124impl<E: ExternalMemory> ParserError<E> {
125 fn error_text(&self) -> String {
126 match &self {
127 ParserError::Buffer(buffer_error) => format!("{buffer_error}"),
128 ParserError::Registry(registry_error) => {
129 format!("{registry_error}")
130 }
131 ParserError::NoCompact { position } => {
132 format!("Expected compact starting at position {position}, not found one.")
133 }
134 ParserError::SomeDataNotUsedBlob { from } => {
135 format!("Some data (input positions [{from}..]) remained unused after decoding.")
136 }
137 ParserError::TypeFailure { position, ty } => {
138 format!("Unable to decode data starting at position {position} as {ty}.")
139 }
140 ParserError::UnexpectedEnumVariant { position } => {
141 format!("Encountered unexpected enum variant at position {position}.")
142 }
143 }
144 }
145}
146
147#[derive(Debug, Eq, PartialEq)]
149pub enum RegistryError<E: ExternalMemory> {
150 External(E::ExternalMemoryError),
151 Internal(RegistryInternalError),
152}
153
154impl<E: ExternalMemory> RegistryError<E> {
155 fn error_text(&self) -> String {
156 match &self {
157 RegistryError::External(external_memory_error) => {
158 format!("Error accessing type from external memory. {external_memory_error}")
159 }
160 RegistryError::Internal(registry_internal_error) => {
161 format!("{registry_internal_error}")
162 }
163 }
164 }
165}
166
167#[derive(Debug, Eq, PartialEq)]
169pub enum RegistryInternalError {
170 CyclicMetadata { id: u32 },
171 ExtrinsicNoCallParam,
172 NotBitOrderType { id: u32 },
173 NotBitStoreType { id: u32 },
174 TypeNotResolved { id: u32 },
175 UnexpectedCompactInsides { id: u32 },
176 UnexpectedExtrinsicType { extrinsic_ty_id: u32 },
177}
178
179impl RegistryInternalError {
180 fn error_text(&self) -> String {
181 match &self {
182 RegistryInternalError::CyclicMetadata { id } => format!("Resolving type id {id} in metadata type registry results in cycling."),
183 RegistryInternalError::ExtrinsicNoCallParam => String::from("Extrinsic type in provided metadata has no specified call parameter."),
184 RegistryInternalError::NotBitOrderType { id } => format!("BitVec type {id} in metadata type registry has unexpected BitOrder type."),
185 RegistryInternalError::NotBitStoreType { id } => format!("BitVec type {id} in metadata type registry has unexpected BitStore type."),
186 RegistryInternalError::TypeNotResolved { id } => format!("Unable to resolve type id {id} in metadata type registry."),
187 RegistryInternalError::UnexpectedCompactInsides { id } => format!("Compact type {id} in metadata type registry has unexpected type inside compact."),
188 RegistryInternalError::UnexpectedExtrinsicType { extrinsic_ty_id } => format!("Decoding is based on assumption that extrinsic type resolves into a SCALE-encoded opaque `Vec<u8>`. Unexpected type description is found for type {extrinsic_ty_id} in metadata type registry."),
189 }
190 }
191}
192
193impl<E: ExternalMemory> From<RegistryInternalError> for RegistryError<E> {
194 fn from(registry_internal_error: RegistryInternalError) -> Self {
195 RegistryError::Internal(registry_internal_error)
196 }
197}
198
199#[derive(Debug, Eq, PartialEq)]
215pub enum ExtensionsError {
216 BlockHashTwice,
217 EraTwice,
218 GenesisHashTwice,
219 NoGenesisHash,
220 NoSpecVersion,
221 SpecVersionTwice,
222}
223
224impl ExtensionsError {
225 fn error_text(&self) -> String {
226 match &self {
227 ExtensionsError::BlockHashTwice => String::from("Signable transaction extensions contain more than one block hash entry."),
228 ExtensionsError::EraTwice => String::from("Signable transaction extensions contain more than one `Era` entry."),
229 ExtensionsError::GenesisHashTwice => String::from("Signable transaction extensions contain more than one genesis hash entry. Unable to verify that correct chain is used for parsing."),
230 ExtensionsError::NoGenesisHash => String::from("Signable transaction extensions do not include chain genesis hash. Unable to verify that correct chain is used for parsing."),
231 ExtensionsError::NoSpecVersion => String::from("Signable transaction extensions do not include metadata spec version. Unable to verify that correct metadata version is used for parsing."),
232 ExtensionsError::SpecVersionTwice => String::from("Signable transaction extensions contain more than one metadata spec version. Unable to verify that correct metadata version is used for parsing."),
233 }
234 }
235}
236
237#[derive(Debug, Eq, PartialEq)]
239pub enum MetaStructureErrorV14 {
240 ExtrinsicTypeNotResolved(RegistryInternalError),
241 NoAddressParam,
242 NoCallParam,
243 NoExtraParam,
244 NoSignatureParam,
245 UnexpectedExtrinsicType { extrinsic_ty_id: u32 },
246 Version(MetaVersionErrorPallets),
247}
248
249impl MetaStructureErrorV14 {
250 fn error_text(&self) -> String {
251 match &self {
252 MetaStructureErrorV14::ExtrinsicTypeNotResolved(registry_error_extrinsic) => format!("Unable to resolve in registry the chain extrinsic type. {registry_error_extrinsic}"),
253 MetaStructureErrorV14::NoAddressParam => String::from("Unchecked extrinsic type in provided metadata has no specified address parameter."),
254 MetaStructureErrorV14::NoCallParam => String::from("Unchecked extrinsic type in provided metadata has no specified call parameter."),
255 MetaStructureErrorV14::NoExtraParam => String::from("Unchecked extrinsic type in provided metadata has no specified extra parameter."),
256 MetaStructureErrorV14::NoSignatureParam => String::from("Unchecked extrinsic type in provided metadata has no specified signature parameter."),
257 MetaStructureErrorV14::UnexpectedExtrinsicType { extrinsic_ty_id } => format!("Decoding is based on assumption that extrinsic type resolves into a SCALE-encoded opaque `Vec<u8>`. Unexpected type description is found for type {extrinsic_ty_id} in metadata type registry."),
258 MetaStructureErrorV14::Version(meta_version_error_pallets) => format!("{meta_version_error_pallets}"),
259 }
260 }
261}
262
263impl From<MetaVersionErrorPallets> for MetaStructureErrorV14 {
264 fn from(meta_version_error_pallets: MetaVersionErrorPallets) -> Self {
265 MetaStructureErrorV14::Version(meta_version_error_pallets)
266 }
267}
268
269impl From<RegistryInternalError> for MetaStructureErrorV14 {
270 fn from(registry_error_extrinsic: RegistryInternalError) -> Self {
271 MetaStructureErrorV14::ExtrinsicTypeNotResolved(registry_error_extrinsic)
272 }
273}
274
275impl From<RegistryError<()>> for MetaStructureErrorV14 {
276 fn from(registry_error_extrinsic: RegistryError<()>) -> Self {
277 let RegistryError::Internal(internal) = registry_error_extrinsic;
278 MetaStructureErrorV14::ExtrinsicTypeNotResolved(internal)
279 }
280}
281
282#[derive(Debug, Eq, PartialEq)]
284pub enum MetaVersionErrorPallets {
285 NoSpecNameIdentifier,
286 NoSpecVersionIdentifier,
287 NoSystemPallet,
288 NoVersionInConstants,
289 RuntimeVersionNotDecodeable,
290 SpecNameIdentifierTwice,
291 SpecVersionIdentifierTwice,
292 UnexpectedRuntimeVersionFormat,
293}
294
295impl MetaVersionErrorPallets {
296 fn error_text(&self) -> String {
297 match &self {
298 MetaVersionErrorPallets::NoSpecNameIdentifier => {
299 String::from("No spec name found in decoded `Version` constant.")
300 }
301 MetaVersionErrorPallets::NoSpecVersionIdentifier => {
302 String::from("No spec version found in decoded `Version` constant.")
303 }
304 MetaVersionErrorPallets::NoSystemPallet => {
305 String::from("No `System` pallet in metadata.")
306 }
307 MetaVersionErrorPallets::NoVersionInConstants => {
308 String::from("No `Version` constant in metadata `System` pallet.")
309 }
310 MetaVersionErrorPallets::RuntimeVersionNotDecodeable => String::from(
311 "`Version` constant from metadata `System` pallet could not be decoded.",
312 ),
313 MetaVersionErrorPallets::SpecNameIdentifierTwice => String::from(
314 "Spec name associated identifier found twice when decoding `Version` constant.",
315 ),
316 MetaVersionErrorPallets::SpecVersionIdentifierTwice => String::from(
317 "Spec version associated identifier found twice when decoding `Version` constant.",
318 ),
319 MetaVersionErrorPallets::UnexpectedRuntimeVersionFormat => {
320 String::from("Decoded `Version` constant is not a composite.")
321 }
322 }
323 }
324}
325
326#[derive(Debug, Eq, PartialEq)]
328pub enum UncheckedExtrinsicError<E: ExternalMemory, M: AsMetadata<E>> {
329 FormatNoCompact,
330 MetaStructure(M::MetaStructureError),
331 Parsing(ParserError<E>),
332 VersionMismatch { version_byte: u8, version: u8 },
333 UnexpectedCallTy { call_ty_id: u32 },
334}
335
336impl<E, M> UncheckedExtrinsicError<E, M>
337where
338 E: ExternalMemory,
339 M: AsMetadata<E>,
340{
341 fn error_text(&self) -> String {
342 match &self {
343 UncheckedExtrinsicError::FormatNoCompact => String::from("Unchecked extrinsic was expected to be a SCALE-encoded opaque `Vec<u8>`. Have not found a compact indicating vector length."),
344 UncheckedExtrinsicError::MetaStructure(meta_structure_error) => format!("Unexpected structure of the metadata. {meta_structure_error}"),
345 UncheckedExtrinsicError::Parsing(parser_error) => format!("Error parsing unchecked extrinsic data. {parser_error}"),
346 UncheckedExtrinsicError::VersionMismatch { version_byte, version } => format!("Version byte in unchecked extrinsic {version_byte} does not match with version {version} from provided metadata. Last 7 bits were expected to be identical."),
347 UncheckedExtrinsicError::UnexpectedCallTy { call_ty_id } => format!("Parameter type for call {call_ty_id} in metadata type registry is not a call type, and does not match known call type descriptors."),
348 }
349 }
350}
351
352macro_rules! impl_display_and_error {
354 ($($ty: ty), *) => {
355 $(
356 impl Display for $ty {
357 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
358 write!(f, "{}", self.error_text())
359 }
360 }
361
362 #[cfg(feature = "std")]
363 impl Error for $ty {
364 fn source(&self) -> Option<&(dyn Error + 'static)> {
365 None
366 }
367 }
368 )*
369 }
370}
371
372impl_display_and_error!(
373 ExtensionsError,
374 MetaStructureErrorV14,
375 MetaVersionErrorPallets,
376 RegistryInternalError
377);
378
379macro_rules! impl_display_and_error_gen {
381 ($($ty: ty), *) => {
382 $(
383 impl <E: ExternalMemory> Display for $ty {
384 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
385 write!(f, "{}", self.error_text())
386 }
387 }
388
389 #[cfg(feature = "std")]
390 impl <E: ExternalMemory> Error for $ty {
391 fn source(&self) -> Option<&(dyn Error + 'static)> {
392 None
393 }
394 }
395 )*
396 }
397}
398
399impl_display_and_error_gen!(ParserError<E>, RegistryError<E>, StorageError<E>);
400
401impl<E: ExternalMemory> From<BufferError<E>> for ParserError<E> {
402 fn from(buffer_error: BufferError<E>) -> Self {
403 ParserError::Buffer(buffer_error)
404 }
405}
406
407impl<E: ExternalMemory> From<RegistryInternalError> for ParserError<E> {
408 fn from(registry_error: RegistryInternalError) -> Self {
409 ParserError::Registry(RegistryError::Internal(registry_error))
410 }
411}
412
413impl<E: ExternalMemory> From<RegistryError<E>> for ParserError<E> {
414 fn from(registry_error: RegistryError<E>) -> Self {
415 ParserError::Registry(registry_error)
416 }
417}
418
419macro_rules! impl_display_error_from_2gen {
421 ($($ty: ty), *) => {
422 $(
423 impl <E, M> Display for $ty
424 where
425 E: ExternalMemory,
426 M: AsMetadata<E>,
427 {
428 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
429 write!(f, "{}", self.error_text())
430 }
431 }
432
433 #[cfg(feature = "std")]
434 impl <E, M> Error for $ty
435 where
436 E: ExternalMemory,
437 M: AsMetadata<E>,
438 {
439 fn source(&self) -> Option<&(dyn Error + 'static)> {
440 None
441 }
442 }
443
444 impl <E, M> From<ParserError<E>> for $ty
445 where
446 E: ExternalMemory,
447 M: AsMetadata<E>,
448 {
449 fn from(parser_error: ParserError<E>) -> Self {
450 <$ty>::Parsing(parser_error)
451 }
452 }
453 )*
454 }
455}
456
457impl_display_error_from_2gen!(SignableError<E, M>, UncheckedExtrinsicError<E, M>);