From d8311a181a600a09d1105529a18e2c04a9cbe669 Mon Sep 17 00:00:00 2001
From: Xiliang Chen <xlchen1291@gmail.com>
Date: Tue, 30 Jun 2020 10:56:17 +1200
Subject: [PATCH] Refactor (#220)

* refactor auction

* refactor gradually-update

* oracle cleanup
---
 auction/src/lib.rs                 | 74 +++++++++++++++--------------
 gradually-update/src/lib.rs        | 76 +++++++++++++++---------------
 oracle/src/default_combine_data.rs | 14 +++---
 oracle/src/lib.rs                  | 29 ++++++++----
 oracle/src/timestamped_value.rs    | 12 -----
 5 files changed, 102 insertions(+), 103 deletions(-)
 delete mode 100644 oracle/src/timestamped_value.rs

diff --git a/auction/src/lib.rs b/auction/src/lib.rs
index 6cd3a7a..ef08e4d 100644
--- a/auction/src/lib.rs
+++ b/auction/src/lib.rs
@@ -70,40 +70,44 @@ decl_module! {
 		pub fn bid(origin, id: T::AuctionId, #[compact] value: T::Balance) {
 			let from = ensure_signed(origin)?;
 
-			let mut auction = <Auctions<T>>::get(id).ok_or(Error::<T>::AuctionNotExist)?;
+			<Auctions<T>>::try_mutate_exists(id, |auction| -> DispatchResult {
+				let mut auction = auction.as_mut().ok_or(Error::<T>::AuctionNotExist)?;
+
+				let block_number = <frame_system::Module<T>>::block_number();
+
+				// make sure auction is started
+				ensure!(block_number >= auction.start, Error::<T>::AuctionNotStarted);
+
+				if let Some(ref current_bid) = auction.bid {
+					ensure!(value > current_bid.1, Error::<T>::InvalidBidPrice);
+				} else {
+					ensure!(!value.is_zero(), Error::<T>::InvalidBidPrice);
+				}
+				let bid_result = T::Handler::on_new_bid(
+					block_number,
+					id,
+					(from.clone(), value),
+					auction.bid.clone(),
+				);
+
+				ensure!(bid_result.accept_bid, Error::<T>::BidNotAccepted);
+				match bid_result.auction_end_change {
+					Change::NewValue(new_end) => {
+						if let Some(old_end_block) = auction.end {
+							<AuctionEndTime<T>>::remove(&old_end_block, id);
+						}
+						if let Some(new_end_block) = new_end {
+							<AuctionEndTime<T>>::insert(&new_end_block, id, ());
+						}
+						auction.end = new_end;
+					},
+					Change::NoChange => {},
+				}
+				auction.bid = Some((from.clone(), value));
+
+				Ok(())
+			})?;
 
-			let block_number = <frame_system::Module<T>>::block_number();
-
-			// make sure auction is started
-			ensure!(block_number >= auction.start, Error::<T>::AuctionNotStarted);
-
-			if let Some(ref current_bid) = auction.bid {
-				ensure!(value > current_bid.1, Error::<T>::InvalidBidPrice);
-			} else {
-				ensure!(!value.is_zero(), Error::<T>::InvalidBidPrice);
-			}
-			let bid_result = T::Handler::on_new_bid(
-				block_number,
-				id,
-				(from.clone(), value),
-				auction.bid.clone(),
-			);
-
-			ensure!(bid_result.accept_bid, Error::<T>::BidNotAccepted);
-			match bid_result.auction_end_change {
-				Change::NewValue(new_end) => {
-					if let Some(old_end_block) = auction.end {
-						<AuctionEndTime<T>>::remove(&old_end_block, id);
-					}
-					if let Some(new_end_block) = new_end {
-						<AuctionEndTime<T>>::insert(&new_end_block, id, ());
-					}
-					auction.end = new_end;
-				},
-				Change::NoChange => {},
-			}
-			auction.bid = Some((from.clone(), value));
-			<Auctions<T>>::insert(id, auction);
 			Self::deposit_event(RawEvent::Bid(id, from, value));
 		}
 
@@ -127,7 +131,7 @@ impl<T: Trait> Module<T> {
 	fn _on_finalize(now: T::BlockNumber) {
 		for (auction_id, _) in <AuctionEndTime<T>>::drain_prefix(&now) {
 			if let Some(auction) = <Auctions<T>>::take(&auction_id) {
-				T::Handler::on_auction_ended(auction_id, auction.bid.clone());
+				T::Handler::on_auction_ended(auction_id, auction.bid);
 			}
 		}
 	}
@@ -171,7 +175,7 @@ impl<T: Trait> Auction<T::AccountId, T::BlockNumber> for Module<T> {
 	fn remove_auction(id: Self::AuctionId) {
 		if let Some(auction) = <Auctions<T>>::take(&id) {
 			if let Some(end_block) = auction.end {
-				<AuctionEndTime<T>>::remove(&end_block, id);
+				<AuctionEndTime<T>>::remove(end_block, id);
 			}
 		}
 	}
diff --git a/gradually-update/src/lib.rs b/gradually-update/src/lib.rs
index 6290afd..7553d3c 100644
--- a/gradually-update/src/lib.rs
+++ b/gradually-update/src/lib.rs
@@ -9,7 +9,7 @@ use frame_support::{
 };
 use frame_system::{self as system, ensure_root};
 
-use sp_runtime::{traits::SaturatedConversion, RuntimeDebug};
+use sp_runtime::{traits::SaturatedConversion, DispatchResult, RuntimeDebug};
 use sp_std::prelude::Vec;
 
 mod mock;
@@ -83,11 +83,13 @@ decl_module! {
 				ensure!(current_value.len() == update.target_value.len(), Error::<T>::InvalidTargetValue);
 			}
 
-			let mut gradually_updates = GraduallyUpdates::get();
-			ensure!(!gradually_updates.contains(&update), Error::<T>::GraduallyUpdateHasExisted);
+			GraduallyUpdates::try_mutate(|gradually_updates| -> DispatchResult {
+				ensure!(!gradually_updates.contains(&update), Error::<T>::GraduallyUpdateHasExisted);
 
-			gradually_updates.push(update.clone());
-			GraduallyUpdates::put(gradually_updates);
+				gradually_updates.push(update.clone());
+
+				Ok(())
+			})?;
 
 			Self::deposit_event(RawEvent::GraduallyUpdate(update.key, update.per_block, update.target_value));
 		}
@@ -97,13 +99,14 @@ decl_module! {
 		pub fn cancel_gradually_update(origin, key: StorageKey) {
 			T::DispatchOrigin::try_origin(origin).map(|_| ()).or_else(ensure_root)?;
 
-			let gradually_updates: Vec<GraduallyUpdate> = GraduallyUpdates::get()
-				.into_iter()
-				.filter(|item| item.key != key)
-				.collect();
+			GraduallyUpdates::try_mutate(|gradually_updates| -> DispatchResult {
+				let old_len = gradually_updates.len();
+				gradually_updates.retain(|item| item.key != key);
 
-			ensure!(GraduallyUpdates::decode_len().unwrap_or_default() - gradually_updates.len() == 1, Error::<T>::CancelGradullyUpdateNotExisted);
-			GraduallyUpdates::put(gradually_updates);
+				ensure!(gradually_updates.len() != old_len, Error::<T>::CancelGradullyUpdateNotExisted);
+
+				Ok(())
+			})?;
 
 			Self::deposit_event(RawEvent::CancelGraduallyUpdate(key));
 		}
@@ -121,44 +124,41 @@ impl<T: Trait> Module<T> {
 			return;
 		}
 
-		let gradually_updates = GraduallyUpdates::get();
+		let mut gradually_updates = GraduallyUpdates::get();
 		let initial_count = gradually_updates.len();
 
-		let gradually_updates = gradually_updates
-			.into_iter()
-			.filter(|update| {
-				let mut keep = true;
-				let current_value = storage::unhashed::get::<StorageValue>(&update.key).unwrap_or_default();
-				let current_value_u128 = u128::from_le_bytes(Self::convert_vec_to_u8(&current_value));
+		gradually_updates.retain(|update| {
+			let mut keep = true;
+			let current_value = storage::unhashed::get::<StorageValue>(&update.key).unwrap_or_default();
+			let current_value_u128 = u128::from_le_bytes(Self::convert_vec_to_u8(&current_value));
 
-				let frequency_u128: u128 = T::UpdateFrequency::get().saturated_into();
+			let frequency_u128: u128 = T::UpdateFrequency::get().saturated_into();
 
-				let step = u128::from_le_bytes(Self::convert_vec_to_u8(&update.per_block));
-				let step_u128 = step.checked_mul(frequency_u128).unwrap();
+			let step = u128::from_le_bytes(Self::convert_vec_to_u8(&update.per_block));
+			let step_u128 = step.checked_mul(frequency_u128).unwrap();
 
-				let target_u128 = u128::from_le_bytes(Self::convert_vec_to_u8(&update.target_value));
+			let target_u128 = u128::from_le_bytes(Self::convert_vec_to_u8(&update.target_value));
 
-				let new_value_u128 = if current_value_u128 > target_u128 {
-					(current_value_u128.checked_sub(step_u128).unwrap()).max(target_u128)
-				} else {
-					(current_value_u128.checked_add(step_u128).unwrap()).min(target_u128)
-				};
+			let new_value_u128 = if current_value_u128 > target_u128 {
+				(current_value_u128.checked_sub(step_u128).unwrap()).max(target_u128)
+			} else {
+				(current_value_u128.checked_add(step_u128).unwrap()).min(target_u128)
+			};
 
-				// current_value equal target_value, remove gradually_update
-				if new_value_u128 == target_u128 {
-					keep = false;
-				}
+			// current_value equal target_value, remove gradually_update
+			if new_value_u128 == target_u128 {
+				keep = false;
+			}
 
-				let mut value = new_value_u128.encode();
-				value.truncate(update.target_value.len());
+			let mut value = new_value_u128.encode();
+			value.truncate(update.target_value.len());
 
-				storage::unhashed::put(&update.key, &value);
+			storage::unhashed::put(&update.key, &value);
 
-				Self::deposit_event(RawEvent::GraduallyUpdateBlockNumber(now, update.key.clone(), value));
+			Self::deposit_event(RawEvent::GraduallyUpdateBlockNumber(now, update.key.clone(), value));
 
-				keep
-			})
-			.collect::<Vec<_>>();
+			keep
+		});
 
 		// gradually_update has finished. Remove it from GraduallyUpdates.
 		if gradually_updates.len() < initial_count {
diff --git a/oracle/src/default_combine_data.rs b/oracle/src/default_combine_data.rs
index cdcd9ac..3a0f727 100644
--- a/oracle/src/default_combine_data.rs
+++ b/oracle/src/default_combine_data.rs
@@ -17,25 +17,23 @@ where
 {
 	fn combine_data(
 		_key: &T::OracleKey,
-		values: Vec<TimestampedValueOf<T>>,
+		mut values: Vec<TimestampedValueOf<T>>,
 		prev_value: Option<TimestampedValueOf<T>>,
 	) -> Option<TimestampedValueOf<T>> {
 		let expires_in = ExpiresIn::get();
 		let now = T::Time::now();
-		let mut valid_values = values
-			.into_iter()
-			.filter(|x| x.timestamp + expires_in > now)
-			.collect::<Vec<TimestampedValueOf<T>>>();
 
-		let count = valid_values.len() as u32;
+		values.retain(|x| x.timestamp + expires_in > now);
+
+		let count = values.len() as u32;
 		let minimum_count = MinimumCount::get();
 		if count < minimum_count {
 			return prev_value;
 		}
 
-		valid_values.sort_by(|a, b| a.value.cmp(&b.value));
+		values.sort_by(|a, b| a.value.cmp(&b.value));
 
 		let median_index = count / 2;
-		Some(valid_values[median_index as usize].clone())
+		Some(values[median_index as usize].clone())
 	}
 }
diff --git a/oracle/src/lib.rs b/oracle/src/lib.rs
index e2a0896..8f9b65c 100644
--- a/oracle/src/lib.rs
+++ b/oracle/src/lib.rs
@@ -5,9 +5,8 @@
 mod default_combine_data;
 mod mock;
 mod tests;
-mod timestamped_value;
 
-use codec::Encode;
+use codec::{Decode, Encode};
 pub use default_combine_data::DefaultCombineData;
 use frame_support::{
 	decl_error, decl_event, decl_module, decl_storage, ensure,
@@ -15,12 +14,14 @@ use frame_support::{
 	weights::{DispatchClass, Pays},
 	IterableStorageMap, Parameter,
 };
+#[cfg(feature = "std")]
+use serde::{Deserialize, Serialize};
 use sp_runtime::{
 	traits::Member,
 	transaction_validity::{
 		InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, ValidTransaction,
 	},
-	DispatchResult,
+	DispatchResult, RuntimeDebug,
 };
 use sp_std::{convert::TryInto, prelude::*, vec};
 // FIXME: `pallet/frame-` prefix should be used for all pallet modules, but currently `frame_system`
@@ -29,7 +30,6 @@ use sp_std::{convert::TryInto, prelude::*, vec};
 use frame_system::{self as system, ensure_none, ensure_root, ensure_signed};
 pub use orml_traits::{CombineData, DataProvider, DataProviderExtended, OnNewData, OnRedundantCall};
 use orml_utilities::OrderedSet;
-pub use timestamped_value::TimestampedValue;
 
 use sp_application_crypto::{KeyTypeId, RuntimeAppPublic};
 pub const ORACLE: KeyTypeId = KeyTypeId(*b"orac");
@@ -53,6 +53,13 @@ pub type AuthorityId = app_sr25519::Public;
 type MomentOf<T> = <<T as Trait>::Time as Time>::Moment;
 pub type TimestampedValueOf<T> = TimestampedValue<<T as Trait>::OracleValue, MomentOf<T>>;
 
+#[derive(Encode, Decode, RuntimeDebug, Eq, PartialEq, Clone, Copy)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct TimestampedValue<Value, Moment> {
+	pub value: Value,
+	pub timestamp: Moment,
+}
+
 pub trait Trait: frame_system::Trait {
 	type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
 	type OnNewData: OnNewData<Self::AccountId, Self::OracleKey, Self::OracleValue>;
@@ -126,7 +133,7 @@ decl_module! {
 		) {
 			ensure_none(origin.clone()).or_else(|_| ensure_root(origin))?;
 			let who = Self::members().0[index as usize].clone();
-			Self::_feed_values(who, values)?;
+			Self::do_feed_values(who, values);
 		}
 
 		#[weight = 10_000_000]
@@ -192,7 +199,10 @@ impl<T: Trait> Module<T> {
 	pub fn get_all_values() -> Vec<(T::OracleKey, Option<TimestampedValueOf<T>>)> {
 		<Values<T>>::iter()
 			.map(|(key, _)| key)
-			.map(|key| (key.clone(), Self::get_no_op(&key)))
+			.map(|key| {
+				let v = Self::get_no_op(&key);
+				(key, v)
+			})
 			.collect()
 	}
 
@@ -201,7 +211,7 @@ impl<T: Trait> Module<T> {
 		T::CombineData::combine_data(key, values, Self::values(key))
 	}
 
-	fn _feed_values(who: T::AccountId, values: Vec<(T::OracleKey, T::OracleValue)>) -> DispatchResult {
+	fn do_feed_values(who: T::AccountId, values: Vec<(T::OracleKey, T::OracleValue)>) {
 		let now = T::Time::now();
 
 		for (key, value) in &values {
@@ -216,8 +226,6 @@ impl<T: Trait> Module<T> {
 		}
 
 		Self::deposit_event(RawEvent::NewFeedData(who, values));
-
-		Ok(())
 	}
 }
 
@@ -258,7 +266,8 @@ impl<T: Trait> DataProvider<T::OracleKey, T::OracleValue> for Module<T> {
 
 impl<T: Trait> DataProviderExtended<T::OracleKey, T::OracleValue, T::AccountId> for Module<T> {
 	fn feed_value(who: T::AccountId, key: T::OracleKey, value: T::OracleValue) -> DispatchResult {
-		Self::_feed_values(who, vec![(key, value)])
+		Self::do_feed_values(who, vec![(key, value)]);
+		Ok(())
 	}
 }
 
diff --git a/oracle/src/timestamped_value.rs b/oracle/src/timestamped_value.rs
deleted file mode 100644
index 26b80d7..0000000
--- a/oracle/src/timestamped_value.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use codec::{Decode, Encode};
-use sp_runtime::RuntimeDebug;
-
-#[cfg(feature = "std")]
-use serde::{Deserialize, Serialize};
-
-#[derive(Encode, Decode, RuntimeDebug, Eq, PartialEq, Clone, Copy)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct TimestampedValue<Value, Moment> {
-	pub value: Value,
-	pub timestamp: Moment,
-}
-- 
GitLab