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:
Bastian Köcher
2019-12-19 14:01:52 +01:00
committed by Gavin Wood
parent 0aab5c659e
commit 8e393aa5a8
69 changed files with 868 additions and 611 deletions
+15 -15
View File
@@ -119,7 +119,7 @@ use sp_runtime::{
},
RuntimeDebug,
};
use frame_support::dispatch::{Result, Dispatchable};
use frame_support::dispatch::{DispatchResult, Dispatchable};
use frame_support::{
Parameter, decl_module, decl_event, decl_storage, storage::child,
parameter_types, IsSubType,
@@ -539,10 +539,10 @@ decl_module! {
/// Updates the schedule for metering contracts.
///
/// The schedule must have a greater version than the stored schedule.
pub fn update_schedule(origin, schedule: Schedule) -> Result {
pub fn update_schedule(origin, schedule: Schedule) -> DispatchResult {
ensure_root(origin)?;
if <Module<T>>::current_schedule().version >= schedule.version {
return Err("new schedule must have a greater version than current");
Err("new schedule must have a greater version than current")?
}
Self::deposit_event(RawEvent::ScheduleUpdated(schedule.version));
@@ -557,7 +557,7 @@ decl_module! {
origin,
#[compact] gas_limit: Gas,
code: Vec<u8>
) -> Result {
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let (mut gas_meter, imbalance) = gas::buy_gas::<T>(&origin, gas_limit)?;
@@ -570,7 +570,7 @@ decl_module! {
gas::refund_unused_gas::<T>(&origin, gas_meter, imbalance);
result.map(|_| ())
result.map(|_| ()).map_err(Into::into)
}
/// Makes a call to an account, optionally transferring some balance.
@@ -586,13 +586,13 @@ decl_module! {
#[compact] value: BalanceOf<T>,
#[compact] gas_limit: Gas,
data: Vec<u8>
) -> Result {
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let dest = T::Lookup::lookup(dest)?;
Self::bare_call(origin, dest, value, gas_limit, data)
.map(|_| ())
.map_err(|e| e.reason)
.map_err(|e| e.reason.into())
}
/// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance.
@@ -611,7 +611,7 @@ decl_module! {
#[compact] gas_limit: Gas,
code_hash: CodeHash<T>,
data: Vec<u8>
) -> Result {
) -> DispatchResult {
let origin = ensure_signed(origin)?;
Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
@@ -619,7 +619,7 @@ decl_module! {
.map(|(_address, output)| output)
})
.map(|_| ())
.map_err(|e| e.reason)
.map_err(|e| e.reason.into())
}
/// Allows block producers to claim a small reward for evicting a contract. If a block producer
@@ -636,10 +636,10 @@ decl_module! {
(Ok(frame_system::RawOrigin::None), Some(aux_sender)) => {
(false, aux_sender)
},
_ => return Err(
_ => Err(
"Invalid surcharge claim: origin must be signed or \
inherent and auxiliary sender only provided on inherent"
),
)?,
};
// Add some advantage for block producers (who send unsigned extrinsics) by
@@ -783,7 +783,7 @@ impl<T: Trait> Module<T> {
code_hash: CodeHash<T>,
rent_allowance: BalanceOf<T>,
delta: Vec<exec::StorageKey>
) -> Result {
) -> DispatchResult {
let mut origin_contract = <ContractInfoOf<T>>::get(&origin)
.and_then(|c| c.get_alive())
.ok_or("Cannot restore from inexisting or tombstone contract")?;
@@ -791,7 +791,7 @@ impl<T: Trait> Module<T> {
let current_block = <frame_system::Module<T>>::block_number();
if origin_contract.last_write == Some(current_block) {
return Err("Origin TrieId written in the current block");
Err("Origin TrieId written in the current block")?
}
let dest_tombstone = <ContractInfoOf<T>>::get(&dest)
@@ -816,7 +816,7 @@ impl<T: Trait> Module<T> {
origin_contract.child_trie_unique_id(),
&blake2_256(key),
);
(key, value)
})
})
@@ -841,7 +841,7 @@ impl<T: Trait> Module<T> {
);
}
return Err("Tombstones don't match");
return Err("Tombstones don't match".into());
}
origin_contract.storage_size -= key_values_taken.iter()