diff --git a/substrate/srml/metadata/src/lib.rs b/substrate/srml/metadata/src/lib.rs index bf7c379000..244d117564 100644 --- a/substrate/srml/metadata/src/lib.rs +++ b/substrate/srml/metadata/src/lib.rs @@ -179,7 +179,7 @@ pub struct OuterEventMetadata { >, } -/// All the metadata about a event. +/// All the metadata about an event. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] pub struct EventMetadata { @@ -209,6 +209,25 @@ pub struct ModuleConstantMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } +/// All the metadata about a module error. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +pub struct ErrorMetadata { + pub name: DecodeDifferentStr, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about errors in a module. +pub trait ModuleErrorMetadata { + fn metadata() -> &'static [ErrorMetadata]; +} + +impl ModuleErrorMetadata for &'static str { + fn metadata() -> &'static [ErrorMetadata] { + &[] + } +} + /// A technical trait to store lazy initiated vec value as static dyn pointer. pub trait DefaultByte: Send + Sync { fn default_byte(&self) -> Vec; @@ -326,8 +345,10 @@ pub enum RuntimeMetadata { V5(RuntimeMetadataDeprecated), /// Version 6 for runtime metadata. No longer used. V6(RuntimeMetadataDeprecated), - /// Version 7 for runtime metadata. - V7(RuntimeMetadataV7), + /// Version 7 for runtime metadata. No longer used. + V7(RuntimeMetadataDeprecated), + /// Version 8 for runtime metadata. + V8(RuntimeMetadataV8), } /// Enum that should fail. @@ -351,12 +372,12 @@ impl Decode for RuntimeMetadataDeprecated { /// The metadata of a runtime. #[derive(Eq, Encode, PartialEq)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct RuntimeMetadataV7 { +pub struct RuntimeMetadataV8 { pub modules: DecodeDifferentArray, } /// The latest version of the metadata. -pub type RuntimeMetadataLastVersion = RuntimeMetadataV7; +pub type RuntimeMetadataLastVersion = RuntimeMetadataV8; /// All metadata about an runtime module. #[derive(Clone, PartialEq, Eq, Encode)] @@ -367,6 +388,7 @@ pub struct ModuleMetadata { pub calls: ODFnA, pub event: ODFnA, pub constants: DFnA, + pub errors: DFnA, } type ODFnA = Option>; @@ -380,6 +402,6 @@ impl Into for RuntimeMetadataPrefixed { impl Into for RuntimeMetadataLastVersion { fn into(self) -> RuntimeMetadataPrefixed { - RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V7(self)) + RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V8(self)) } } diff --git a/substrate/srml/support/src/dispatch.rs b/substrate/srml/support/src/dispatch.rs index 67cd3e44bf..fd24c257ae 100644 --- a/substrate/srml/support/src/dispatch.rs +++ b/substrate/srml/support/src/dispatch.rs @@ -23,7 +23,7 @@ pub use std::fmt; pub use crate::codec::{Codec, EncodeLike, Decode, Encode, Input, Output, HasCompact, EncodeAsRef}; pub use srml_metadata::{ FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata, - ModuleConstantMetadata, DefaultByte, DefaultByteGetter, + ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata }; pub use sr_primitives::{ weights::{ @@ -1298,6 +1298,14 @@ macro_rules! decl_module { { $( $other_where_bounds )* } $( $constants )* } + + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::ModuleErrorMetadata + for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* + { + fn metadata() -> &'static [$crate::dispatch::ErrorMetadata] { + <$error_type as $crate::dispatch::ModuleErrorMetadata>::metadata() + } + } } } diff --git a/substrate/srml/support/src/error.rs b/substrate/srml/support/src/error.rs index 2f9d9379bf..848bd126d2 100644 --- a/substrate/srml/support/src/error.rs +++ b/substrate/srml/support/src/error.rs @@ -18,6 +18,7 @@ #[doc(hidden)] pub use sr_primitives::traits::LookupError; +pub use srml_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; /// Declare an error type for a runtime module. /// @@ -49,7 +50,7 @@ macro_rules! decl_error { $(#[$attr:meta])* pub enum $error:ident { $( - $( #[$variant_attr:meta] )* + $( #[doc = $doc_attr:tt] )* $name:ident ),* $(,)? @@ -62,7 +63,7 @@ macro_rules! decl_error { Other(&'static str), CannotLookup, $( - $(#[$variant_attr])* + $( #[doc = $doc_attr] )* $name ),* } @@ -115,6 +116,21 @@ macro_rules! decl_error { $crate::dispatch::DispatchError::new(None, self.as_u8(), Some(self.as_str())) } } + + impl $crate::error::ModuleErrorMetadata for $error { + fn metadata() -> &'static [$crate::error::ErrorMetadata] { + &[ + $( + $crate::error::ErrorMetadata { + name: $crate::error::DecodeDifferent::Encode(stringify!($name)), + documentation: $crate::error::DecodeDifferent::Encode(&[ + $( $doc_attr ),* + ]), + } + ),* + ] + } + } }; (@GENERATE_AS_U8 $self:ident diff --git a/substrate/srml/support/src/metadata.rs b/substrate/srml/support/src/metadata.rs index 7ae5f7d193..a223a14f9e 100644 --- a/substrate/srml/support/src/metadata.rs +++ b/substrate/srml/support/src/metadata.rs @@ -17,7 +17,7 @@ pub use srml_metadata::{ DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion, DefaultByteGetter, RuntimeMetadataPrefixed, StorageEntryMetadata, StorageMetadata, - StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher + StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher, ModuleErrorMetadata }; /// Implements the metadata support for the given runtime and all its modules. @@ -96,6 +96,11 @@ macro_rules! __runtime_modules_to_metadata { $crate::metadata::FnEncode( $mod::$module::<$runtime $(, $mod::$instance )?>::module_constants_metadata ) + ), + errors: $crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + <$mod::$module::<$runtime $(, $mod::$instance )?> as $crate::metadata::ModuleErrorMetadata>::metadata + ) ) }; $( $rest )* @@ -227,6 +232,7 @@ mod tests { use srml_metadata::{ EventMetadata, StorageEntryModifier, StorageEntryType, FunctionMetadata, StorageEntryMetadata, ModuleMetadata, RuntimeMetadataPrefixed, DefaultByte, ModuleConstantMetadata, DefaultByteGetter, + ErrorMetadata, }; use codec::{Encode, Decode}; use crate::traits::Get; @@ -278,7 +284,7 @@ mod tests { } mod event_module { - use crate::dispatch::Result; + use crate::dispatch::DispatchResult; pub trait Trait { type Origin; @@ -296,7 +302,19 @@ mod tests { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn aux_0(_origin) -> Result { unreachable!() } + type Error = Error; + + fn aux_0(_origin) -> DispatchResult { unreachable!() } + } + } + + crate::decl_error! { + pub enum Error { + /// Some user input error + UserInputError, + /// Something bad happened + /// this could be due to many reasons + BadThingHappened, } } } @@ -447,6 +465,7 @@ mod tests { } ]) ), + errors: DecodeDifferent::Encode(FnEncode(|| &[])), }, ModuleMetadata { name: DecodeDifferent::Encode("Module"), @@ -469,6 +488,19 @@ mod tests { ]) )), constants: DecodeDifferent::Encode(FnEncode(|| &[])), + errors: DecodeDifferent::Encode(FnEncode(|| &[ + ErrorMetadata { + name: DecodeDifferent::Encode("UserInputError"), + documentation: DecodeDifferent::Encode(&[" Some user input error"]), + }, + ErrorMetadata { + name: DecodeDifferent::Encode("BadThingHappened"), + documentation: DecodeDifferent::Encode(&[ + " Something bad happened", + " this could be due to many reasons", + ]), + }, + ])), }, ModuleMetadata { name: DecodeDifferent::Encode("Module2"), @@ -505,6 +537,7 @@ mod tests { ]) )), constants: DecodeDifferent::Encode(FnEncode(|| &[])), + errors: DecodeDifferent::Encode(FnEncode(|| &[])), }, ]) }; diff --git a/substrate/srml/support/test/tests/system.rs b/substrate/srml/support/test/tests/system.rs index 1040b26cc6..f1a427060a 100644 --- a/substrate/srml/support/test/tests/system.rs +++ b/substrate/srml/support/test/tests/system.rs @@ -29,7 +29,10 @@ support::decl_event!( support::decl_error! { pub enum Error { + /// Test error documentation TestError, + /// Error documentation + /// with multiple lines AnotherError } }