From 57a8842cf8d8c9223c2ea85a2e7538085cec4d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Fri, 30 Oct 2020 11:02:05 +0100 Subject: [PATCH 1/2] Implement serde::Deserialize for DispatchError if std This is needed to use this type in the contracts RPC. --- primitives/runtime/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index eb20418203a9b..e6c707e906edc 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -388,10 +388,10 @@ pub type DispatchResultWithInfo = sp_std::result::Result, }, } From c8c83e60c734b5ba19ad2401bbcf0d301d8c9a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Tue, 27 Oct 2020 11:19:27 +0100 Subject: [PATCH 2/2] contracts: Change contract_call RPC to return more information --- frame/contracts/rpc/src/lib.rs | 51 ++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index 84df1e25a3b38..6d43ea75c035f 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -31,6 +31,7 @@ use sp_rpc::number; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Header as HeaderT}, + DispatchError, }; use std::convert::TryInto; use pallet_contracts_primitives::ContractExecResult; @@ -83,33 +84,47 @@ pub struct CallRequest { input_data: Bytes, } +#[derive(Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +struct RpcContractExecSuccess { + /// The return flags. See `pallet_contracts_primitives::ReturnFlags`. + flags: u32, + /// Data as returned by the contract. + data: Bytes, +} + /// An RPC serializable result of contract execution #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] -pub enum RpcContractExecResult { - /// Successful execution - Success { - /// The return flags - flags: u32, - /// Output data - data: Bytes, - /// How much gas was consumed by the call. - gas_consumed: u64, - }, - /// Error execution - Error(()), +pub struct RpcContractExecResult { + /// How much gas was consumed by the call. In case of an error this is the amount + /// that was used up until the error occurred. + gas_consumed: u64, + /// Additional dynamic human readable error information for debugging. An empty string + /// indicates that no additional information is available. + debug_message: String, + /// Indicates whether the contract execution was successful or not. + result: std::result::Result, } impl From for RpcContractExecResult { fn from(r: ContractExecResult) -> Self { match r.exec_result { - Ok(val) => RpcContractExecResult::Success { - flags: val.flags.bits(), - data: val.data.into(), + Ok(val) => RpcContractExecResult { + gas_consumed: r.gas_consumed, + debug_message: String::new(), + result: Ok(RpcContractExecSuccess { + flags: val.flags.bits(), + data: val.data.into(), + }), + }, + Err(err) => RpcContractExecResult { gas_consumed: r.gas_consumed, + debug_message: String::new(), + result: Err(err.error), }, - _ => RpcContractExecResult::Error(()), } } } @@ -310,7 +325,7 @@ mod tests { let actual = serde_json::to_string(&res).unwrap(); assert_eq!(actual, expected); } - test(r#"{"success":{"flags":5,"data":"0x1234","gas_consumed":5000}}"#); - test(r#"{"error":null}"#); + test(r#"{"gasConsumed":5000,"debugMessage":"helpOk","result":{"Ok":{"flags":5,"data":"0x1234"}}}"#); + test(r#"{"gasConsumed":3400,"debugMessage":"helpErr","result":{"Err":"BadOrigin"}}"#); } }