事务失败时,是否可以在Substrate UI中读取SRML错误消息?

时间:2019-08-08 10:53:10

标签: substrate

我不确定Substrate运行时中与Substrate UI有关的错误消息的行为,以及它们是否固有地导致事务失败。

例如,在democracy SRML中,我看到以下行:

ensure!(!<Cancellations<T>>::exists(h), "cannot cancel the same proposal twice");

大概是一个宏,如果h(建议哈希)已存在,则该宏可确保事务失败或停止处理。显然有一条消息与此错误相关。

当测试失败时,我是否可以假定事务失败(不执行其余SRML代码)?

如果是这样,我如何在Substrate UI中检测到故障,并可能看到消息本身?

如果没有,则可能在运行时模块中需要一些其他代码,这些代码会显式创建错误。我见过Err()-但没有与ensure!()

一起使用

2 个答案:

答案 0 :(得分:3)

https://github.com/paritytech/substrate/pull/3433合并后,ExtrinsicFailed事件现在包含一个DispatchError,它将提供其他错误代码。

可用的文档很少,因此我仅以system模块为例。

首先,您需要decl_error,请注意错误变体只能是简单的C(例如枚举)

https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L334

decl_error! {
    /// Error for the System module
    pub enum Error {
        BadSignature,
        BlockFull,
        RequireSignedOrigin,
        RequireRootOrigin,
        RequireNoOrigin,
    }
}

然后,您需要关联已声明的Error类型 https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L253

decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        type Error = Error;

然后,您可以在发生故障时通过调度调用返回Error

https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L543

pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), Error>
    where OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>
{
    match o.into() {
        Ok(RawOrigin::Root) => Ok(()),
        _ => Err(Error::RequireRootOrigin),
    }
}

现在,您只能从JS端看到两个数字,模块索引和错误代码。稍后可能会支持将错误详细信息包含在元数据中,以便前端将能够提供更好的响应。

相关问题: https://github.com/paritytech/substrate/issues/2954

答案 1 :(得分:0)

ensure!宏的解释为:

#[macro_export]
macro_rules! fail {
    ( $y:expr ) => {{
        return Err($y);
    }}
}

#[macro_export]
macro_rules! ensure {
    ( $x:expr, $y:expr ) => {{
        if !$x {
            $crate::fail!($y);
        }
    }}
}

因此,基本上,这只是返回Err的较快方法。在1.0时,错误味精将仅输出到stdout(至少我到目前为止已经测试过),不知道将来是否会将其包含在区块链中(因此可以在用户界面ui中查看)。