mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 22:47:56 +00:00
Make decl_error! errors usable (#4449)
* Make `decl_error!` errors usable This pr implements support for returning errors of different pallets in a pallet. These errors need to be declared with `decl_error!`. The pr changes the following: - Each dispatchable function now returns a `DispatchResult` which is an alias for `Result<(), DispatchError>`. - `DispatchError` is an enum that has 4 variants: - `Other`: For storing string error messages - `CannotLookup`: Variant that is returned when something returns a `sp_runtime::LookupError` - `BadOrigin`: Variant that is returned for any kind of bad origin - `Module`: The error of a specific module. Contains the `index`, `error` and the `message`. The index is the index of the module in `construct_runtime!`. `error` is the index of the error in the error enum declared by `decl_error!`. `message` is the message to the error variant (this will not be encoded). - `construct_runtime!` now creates a new struct `ModuleToIndex`. This struct implements the trait `ModuleToIndex`. - `frame_system::Trait` has a new associated type: `ModuleToIndex` that expects the `ModuleToIndex` generated by `construct_runtime!`. - All error strings returned in any module are being converted now to `DispatchError`. - `BadOrigin` is the default error returned by any type that implements `EnsureOrigin`. * Fix frame system benchmarks
This commit is contained in:
committed by
Gavin Wood
parent
0aab5c659e
commit
8e393aa5a8
@@ -358,26 +358,57 @@ impl From<DispatchError> for DispatchOutcome {
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of a module function call; either nothing (functions are only called for "side effects")
|
||||
/// or an error message.
|
||||
pub type DispatchResult = sp_std::result::Result<(), DispatchError>;
|
||||
|
||||
/// Reason why a dispatch call failed
|
||||
#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize))]
|
||||
/// Reason why a dispatch call failed
|
||||
pub struct DispatchError {
|
||||
/// Module index, matching the metadata module index
|
||||
pub module: Option<u8>,
|
||||
/// Module specific error value
|
||||
pub error: u8,
|
||||
/// Optional error message.
|
||||
#[codec(skip)]
|
||||
pub message: Option<&'static str>,
|
||||
pub enum DispatchError {
|
||||
/// Some error occurred.
|
||||
Other(#[codec(skip)] &'static str),
|
||||
/// Failed to lookup some data.
|
||||
CannotLookup,
|
||||
/// A bad origin.
|
||||
BadOrigin,
|
||||
/// A custom error in a module
|
||||
Module {
|
||||
/// Module index, matching the metadata module index
|
||||
index: u8,
|
||||
/// Module specific error value
|
||||
error: u8,
|
||||
/// Optional error message.
|
||||
#[codec(skip)]
|
||||
message: Option<&'static str>,
|
||||
},
|
||||
}
|
||||
|
||||
impl DispatchError {
|
||||
/// Create a new instance of `DispatchError`.
|
||||
pub fn new(module: Option<u8>, error: u8, message: Option<&'static str>) -> Self {
|
||||
Self {
|
||||
module,
|
||||
error,
|
||||
message,
|
||||
impl From<crate::traits::LookupError> for DispatchError {
|
||||
fn from(_: crate::traits::LookupError) -> Self {
|
||||
Self::CannotLookup
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::traits::BadOrigin> for DispatchError {
|
||||
fn from(_: crate::traits::BadOrigin) -> Self {
|
||||
Self::BadOrigin
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for DispatchError {
|
||||
fn from(err: &'static str) -> DispatchError {
|
||||
DispatchError::Other(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<&'static str> for DispatchError {
|
||||
fn into(self) -> &'static str {
|
||||
match self {
|
||||
Self::Other(msg) => msg,
|
||||
Self::CannotLookup => "Can not lookup",
|
||||
Self::BadOrigin => "Bad origin",
|
||||
Self::Module { message, .. } => message.unwrap_or("Unknown module error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,29 +416,18 @@ impl DispatchError {
|
||||
impl traits::Printable for DispatchError {
|
||||
fn print(&self) {
|
||||
"DispatchError".print();
|
||||
if let Some(module) = self.module {
|
||||
module.print();
|
||||
match self {
|
||||
Self::Other(err) => err.print(),
|
||||
Self::CannotLookup => "Can not lookup".print(),
|
||||
Self::BadOrigin => "Bad origin".print(),
|
||||
Self::Module { index, error, message } => {
|
||||
index.print();
|
||||
error.print();
|
||||
if let Some(msg) = message {
|
||||
msg.print();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.error.print();
|
||||
if let Some(msg) = self.message {
|
||||
msg.print();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl traits::ModuleDispatchError for &'static str {
|
||||
fn as_u8(&self) -> u8 {
|
||||
0
|
||||
}
|
||||
|
||||
fn as_str(&self) -> &'static str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for DispatchError {
|
||||
fn from(err: &'static str) -> DispatchError {
|
||||
DispatchError::new(None, 0, Some(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,18 +688,18 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn dispatch_error_encoding() {
|
||||
let error = DispatchError {
|
||||
module: Some(1),
|
||||
let error = DispatchError::Module {
|
||||
index: 1,
|
||||
error: 2,
|
||||
message: Some("error message"),
|
||||
};
|
||||
let encoded = error.encode();
|
||||
let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
|
||||
assert_eq!(encoded, vec![1, 1, 2]);
|
||||
assert_eq!(encoded, vec![3, 1, 2]);
|
||||
assert_eq!(
|
||||
decoded,
|
||||
DispatchError {
|
||||
module: Some(1),
|
||||
DispatchError::Module {
|
||||
index: 1,
|
||||
error: 2,
|
||||
message: None,
|
||||
},
|
||||
|
||||
@@ -136,11 +136,11 @@ impl<
|
||||
|
||||
/// An error type that indicates that the origin is invalid.
|
||||
#[derive(Encode, Decode)]
|
||||
pub struct InvalidOrigin;
|
||||
pub struct BadOrigin;
|
||||
|
||||
impl From<InvalidOrigin> for &'static str {
|
||||
fn from(_: InvalidOrigin) -> &'static str {
|
||||
"Invalid origin"
|
||||
impl From<BadOrigin> for &'static str {
|
||||
fn from(_: BadOrigin) -> &'static str {
|
||||
"Bad origin"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ pub trait EnsureOrigin<OuterOrigin> {
|
||||
/// A return type.
|
||||
type Success;
|
||||
/// Perform the origin check.
|
||||
fn ensure_origin(o: OuterOrigin) -> result::Result<Self::Success, InvalidOrigin> {
|
||||
Self::try_origin(o).map_err(|_| InvalidOrigin)
|
||||
fn ensure_origin(o: OuterOrigin) -> result::Result<Self::Success, BadOrigin> {
|
||||
Self::try_origin(o).map_err(|_| BadOrigin)
|
||||
}
|
||||
/// Perform the origin check.
|
||||
fn try_origin(o: OuterOrigin) -> result::Result<Self::Success, OuterOrigin>;
|
||||
@@ -668,10 +668,6 @@ impl<T: BlindCheckable, Context> Checkable<Context> for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of a module function call; either nothing (functions are only called for "side effects")
|
||||
/// or an error message.
|
||||
pub type DispatchResult<Error> = result::Result<(), Error>;
|
||||
|
||||
/// A lazy call (module function and argument values) that can be executed via its `dispatch`
|
||||
/// method.
|
||||
pub trait Dispatchable {
|
||||
@@ -681,10 +677,8 @@ pub trait Dispatchable {
|
||||
type Origin;
|
||||
/// ...
|
||||
type Trait;
|
||||
/// The error type returned by this dispatchable.
|
||||
type Error: Into<crate::DispatchError>;
|
||||
/// Actually dispatch this call and result the result of it.
|
||||
fn dispatch(self, origin: Self::Origin) -> DispatchResult<Self::Error>;
|
||||
fn dispatch(self, origin: Self::Origin) -> crate::DispatchResult;
|
||||
}
|
||||
|
||||
/// Means by which a transaction may be extended. This type embodies both the data and the logic
|
||||
@@ -789,17 +783,6 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
fn post_dispatch(_pre: Self::Pre, _info: Self::DispatchInfo, _len: usize) { }
|
||||
}
|
||||
|
||||
/// An error that is returned by a dispatchable function of a module.
|
||||
pub trait ModuleDispatchError {
|
||||
/// Convert this error to a `u8`.
|
||||
///
|
||||
/// The `u8` corresponds to the index of the variant in the error enum.
|
||||
fn as_u8(&self) -> u8;
|
||||
|
||||
/// Convert the error to a `&'static str`.
|
||||
fn as_str(&self) -> &'static str;
|
||||
}
|
||||
|
||||
#[impl_for_tuples(1, 12)]
|
||||
impl<AccountId, Call, Info: Clone> SignedExtension for Tuple {
|
||||
for_tuples!( where #( Tuple: SignedExtension<AccountId=AccountId, Call=Call, DispatchInfo=Info> )* );
|
||||
|
||||
Reference in New Issue
Block a user