From 85a78bc8d84f26f4b08efa451399cc826b4dc51d Mon Sep 17 00:00:00 2001 From: Xiliang Chen <xlchen1291@gmail.com> Date: Mon, 29 Jun 2020 13:44:10 +1200 Subject: [PATCH] add with_transaction_result (#217) --- utilities/Cargo.toml | 4 +++ utilities/src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/utilities/Cargo.toml b/utilities/Cargo.toml index 5d73bc2..47adf0d 100644 --- a/utilities/Cargo.toml +++ b/utilities/Cargo.toml @@ -10,11 +10,14 @@ edition = "2018" [dependencies] serde = { version = "1.0.111", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } +frame-support = { version = "2.0.0-rc4", default-features = false } sp-runtime = { version = "2.0.0-rc4", default-features = false } sp-std = { version = "2.0.0-rc4", default-features = false } [dev-dependencies] serde_json = "1.0.53" +frame-system = { version = "2.0.0-rc4" } +sp-io = { version = "2.0.0-rc4" } clear_on_drop = { version = "0.2.4", features = ["no_cc"] } # https://github.com/paritytech/substrate/issues/4179 @@ -23,6 +26,7 @@ default = ["std"] std = [ "serde", "codec/std", + "frame-support/std", "sp-runtime/std", "sp-std/std", ] diff --git a/utilities/src/lib.rs b/utilities/src/lib.rs index 2741e62..c7d523a 100644 --- a/utilities/src/lib.rs +++ b/utilities/src/lib.rs @@ -1,5 +1,82 @@ #![cfg_attr(not(feature = "std"), no_std)] +use frame_support::storage::{with_transaction, TransactionOutcome}; +use sp_runtime::DispatchError; +use sp_std::result::Result; + pub mod ordered_set; pub use ordered_set::OrderedSet; + +pub fn with_transaction_result<R>(f: impl FnOnce() -> Result<R, DispatchError>) -> Result<R, DispatchError> { + with_transaction(|| { + let res = f(); + if res.is_ok() { + TransactionOutcome::Commit(res) + } else { + TransactionOutcome::Rollback(res) + } + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{assert_err, assert_ok, decl_module, decl_storage}; + use sp_io::TestExternalities; + use sp_runtime::{DispatchError, DispatchResult}; + + pub trait Trait: frame_system::Trait {} + + decl_module! { + pub struct Module<T: Trait> for enum Call where origin: T::Origin {} + } + + decl_storage! { + trait Store for Module<T: Trait> as StorageTransactions { + pub Value: u32; + pub Map: map hasher(twox_64_concat) String => u32; + } + } + + #[test] + fn storage_transaction_basic_commit() { + TestExternalities::default().execute_with(|| { + assert_eq!(Value::get(), 0); + assert!(!Map::contains_key("val0")); + + assert_ok!(with_transaction_result(|| -> DispatchResult { + Value::set(99); + Map::insert("val0", 99); + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + Ok(()) + })); + + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + }); + } + + #[test] + fn storage_transaction_basic_rollback() { + TestExternalities::default().execute_with(|| { + assert_eq!(Value::get(), 0); + assert_eq!(Map::get("val0"), 0); + + assert_err!( + with_transaction_result(|| -> DispatchResult { + Value::set(99); + Map::insert("val0", 99); + assert_eq!(Value::get(), 99); + assert_eq!(Map::get("val0"), 99); + Err("test".into()) + }), + DispatchError::Other("test") + ); + + assert_eq!(Value::get(), 0); + assert_eq!(Map::get("val0"), 0); + }); + } +} -- GitLab