From be6d84f14b3a3beb31035e502aa18d2e0850562d Mon Sep 17 00:00:00 2001
From: wangjj9219 <183318287@qq.com>
Date: Thu, 27 Aug 2020 15:27:04 +0800
Subject: [PATCH] Refactor oracle feed_values with to signed tx (#263)

* Refactor oracle feed_values with to signed tx

* remove nonce, block and signature
---
 oracle/src/default_combine_data.rs |   8 +-
 oracle/src/lib.rs                  | 219 +++++++++--------------------
 oracle/src/mock.rs                 |  36 +++--
 oracle/src/tests.rs                | 208 ++++++++-------------------
 4 files changed, 150 insertions(+), 321 deletions(-)

diff --git a/oracle/src/default_combine_data.rs b/oracle/src/default_combine_data.rs
index c97f406..56cf6b8 100644
--- a/oracle/src/default_combine_data.rs
+++ b/oracle/src/default_combine_data.rs
@@ -1,14 +1,16 @@
-use crate::{Instance, MomentOf, TimestampedValueOf, Trait};
+use crate::{DefaultInstance, Instance, MomentOf, TimestampedValueOf, Trait};
 use frame_support::traits::{Get, Time};
 use orml_traits::CombineData;
 use sp_std::{marker, prelude::*};
 
 /// Sort by value and returns median timestamped value.
 /// Returns prev_value if not enough valid values.
-pub struct DefaultCombineData<T, I, MinimumCount, ExpiresIn>(marker::PhantomData<(T, I, MinimumCount, ExpiresIn)>);
+pub struct DefaultCombineData<T, MinimumCount, ExpiresIn, I = DefaultInstance>(
+	marker::PhantomData<(T, I, MinimumCount, ExpiresIn)>,
+);
 
 impl<T, I, MinimumCount, ExpiresIn> CombineData<<T as Trait<I>>::OracleKey, TimestampedValueOf<T, I>>
-	for DefaultCombineData<T, I, MinimumCount, ExpiresIn>
+	for DefaultCombineData<T, MinimumCount, ExpiresIn, I>
 where
 	T: Trait<I>,
 	I: Instance,
diff --git a/oracle/src/lib.rs b/oracle/src/lib.rs
index 7e3ac7f..45b1d29 100644
--- a/oracle/src/lib.rs
+++ b/oracle/src/lib.rs
@@ -23,52 +23,35 @@ mod default_combine_data;
 mod mock;
 mod tests;
 
-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,
+	decl_error, decl_event, decl_module, decl_storage,
+	dispatch::DispatchResultWithPostInfo,
+	ensure,
 	traits::{ChangeMembers, Get, InitializeMembers, Time},
-	weights::{DispatchClass, Weight},
+	weights::{DispatchClass, Pays, Weight},
 	IterableStorageMap, Parameter,
 };
-use frame_system::{ensure_none, ensure_root, ensure_signed};
-pub use orml_traits::{CombineData, DataFeeder, DataProvider, DataProviderExtended, OnNewData, TimestampedValue};
+use frame_system::{ensure_root, ensure_signed};
+pub use orml_traits::{CombineData, DataFeeder, DataProvider, DataProviderExtended, OnNewData};
 use orml_utilities::OrderedSet;
-use sp_runtime::{
-	traits::Member,
-	transaction_validity::{
-		InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, ValidTransaction,
-	},
-	DispatchResult,
-};
-use sp_std::{convert::TryInto, prelude::*, vec};
-
-use sp_application_crypto::{KeyTypeId, RuntimeAppPublic};
-pub const ORACLE: KeyTypeId = KeyTypeId(*b"orac");
-
-mod app_sr25519 {
-	use sp_application_crypto::{app_crypto, sr25519};
-	app_crypto!(sr25519, super::ORACLE);
+#[cfg(feature = "std")]
+use serde::{Deserialize, Serialize};
+use sp_runtime::{traits::Member, DispatchResult, RuntimeDebug};
+use sp_std::{prelude::*, vec};
+
+type MomentOf<T, I = DefaultInstance> = <<T as Trait<I>>::Time as Time>::Moment;
+pub type TimestampedValueOf<T, I = DefaultInstance> = TimestampedValue<<T as Trait<I>>::OracleValue, MomentOf<T, I>>;
+
+#[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,
 }
 
-sp_application_crypto::with_pair! {
-	/// An oracle keypair using sr25519 as its crypto.
-	pub type AuthorityPair = app_sr25519::Pair;
-}
-
-/// An oracle signature using sr25519 as its crypto.
-pub type AuthoritySignature = app_sr25519::Signature;
-
-/// An oracle identifier using sr25519 as its crypto.
-pub type AuthorityId = app_sr25519::Public;
-
-type MomentOf<T, I> = <<T as Trait<I>>::Time as Time>::Moment;
-pub type TimestampedValueOf<T, I> = TimestampedValue<<T as Trait<I>>::OracleValue, MomentOf<T, I>>;
-
-/// Number of blocks before an unconfirmed unsigned transaction expires.
-pub const EXTRINSIC_LONGEVITY: u32 = 100;
-
-pub trait Trait<I: Instance>: frame_system::Trait {
+pub trait Trait<I: Instance = DefaultInstance>: frame_system::Trait {
 	type Event: From<Event<Self, I>> + Into<<Self as frame_system::Trait>::Event>;
 
 	/// Hook on new data received
@@ -87,27 +70,41 @@ pub trait Trait<I: Instance>: frame_system::Trait {
 	/// The data value type
 	type OracleValue: Parameter + Member + Ord;
 
-	/// A configuration for base priority of unsigned transactions.
-	///
-	/// This is exposed so that it can be tuned for particular runtime, when
-	/// multiple pallets send unsigned transactions.
-	type UnsignedPriority: Get<TransactionPriority>;
+	/// The root operator account id, recorad all sudo feeds on this account.
+	type RootOperatorAccountId: Get<Self::AccountId>;
+}
 
-	/// The identifier type for an authority.
-	type AuthorityId: Member + Parameter + RuntimeAppPublic + Default + Ord;
+decl_error! {
+	pub enum Error for Module<T: Trait<I>, I: Instance> {
+		/// Sender does not have permission
+		NoPermission,
+		/// Feeder has already feeded at this block
+		AlreadyFeeded,
+	}
 }
 
+decl_event!(
+	pub enum Event<T, I=DefaultInstance> where
+		<T as frame_system::Trait>::AccountId,
+		<T as Trait<I>>::OracleKey,
+		<T as Trait<I>>::OracleValue,
+	{
+		/// New feed data is submitted. [sender, values]
+		NewFeedData(AccountId, Vec<(OracleKey, OracleValue)>),
+	}
+);
+
 decl_storage! {
-	trait Store for Module<T: Trait<I>, I: Instance> as Oracle {
+	trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Oracle {
 
 		/// Raw values for each oracle operators
 		pub RawValues get(fn raw_values): double_map hasher(twox_64_concat) T::AccountId, hasher(twox_64_concat) T::OracleKey => Option<TimestampedValueOf<T, I>>;
 
 		/// True if Self::values(key) is up to date, otherwise the value is stale
-		pub IsUpdated get(fn is_updated): map hasher(twox_64_concat) T::OracleKey => bool;
+		pub IsUpdated get(fn is_updated): map hasher(twox_64_concat) <T as Trait<I>>::OracleKey => bool;
 
 		/// Combined value, may not be up to date
-		pub Values get(fn values): map hasher(twox_64_concat) T::OracleKey => Option<TimestampedValueOf<T, I>>;
+		pub Values get(fn values): map hasher(twox_64_concat) <T as Trait<I>>::OracleKey => Option<TimestampedValueOf<T, I>>;
 
 		/// If an oracle operator has feed a value in this block
 		HasDispatched: OrderedSet<T::AccountId>;
@@ -116,22 +113,16 @@ decl_storage! {
 		/// The current members of the collective. This is stored sorted (just by value).
 		pub Members get(fn members) config(): OrderedSet<T::AccountId>;
 
-		/// Session key for oracle operators
-		pub SessionKeys get(fn session_keys) config(): map hasher(twox_64_concat) T::AccountId => Option<T::AuthorityId>;
-
 		pub Nonces get(fn nonces): map hasher(twox_64_concat) T::AccountId => u32;
 	}
-}
 
-decl_error! {
-	pub enum Error for Module<T: Trait<I>, I: Instance> {
-		/// Sender does not have permission
-		NoPermission,
+	add_extra_genesis {
+		config(phantom): sp_std::marker::PhantomData<I>;
 	}
 }
 
 decl_module! {
-	pub struct Module<T: Trait<I>, I: Instance> for enum Call where origin: T::Origin {
+	pub struct Module<T: Trait<I>, I: Instance=DefaultInstance> for enum Call where origin: T::Origin {
 		type Error = Error<T, I>;
 
 		fn deposit_event() = default;
@@ -143,27 +134,10 @@ decl_module! {
 		pub fn feed_values(
 			origin,
 			values: Vec<(T::OracleKey, T::OracleValue)>,
-			#[compact] index: u32,
-			_block: T::BlockNumber,
-			// since signature verification is done in `validate_unsigned`
-			// we can skip doing it here again.
-			_signature: <T::AuthorityId as RuntimeAppPublic>::Signature,
-		) {
-			ensure_none(origin.clone()).or_else(|_| ensure_root(origin))?;
-			// validate_unsigned already unsure index is valid
-			let who = Self::members().0.get(index as usize)
-				.expect("`validate_unsigned` ensures index is in bound; qed`")
-				.clone();
-			Self::do_feed_values(who, values);
-		}
-
-		/// Update the session key.
-		#[weight = 10_000_000]
-		pub fn set_session_key(origin, key: T::AuthorityId) {
-			let who = ensure_signed(origin)?;
-			ensure!(Self::members().contains(&who), Error::<T, I>::NoPermission);
-
-			SessionKeys::<T, I>::insert(who, key);
+		) -> DispatchResultWithPostInfo {
+			let feeder = ensure_signed(origin.clone()).or_else(|_| ensure_root(origin).map(|_| T::RootOperatorAccountId::get()))?;
+			Self::do_feed_values(feeder, values)?;
+			Ok(Pays::No.into())
 		}
 
 		/// dummy `on_initialize` to return the weight used in `on_finalize`.
@@ -179,17 +153,6 @@ decl_module! {
 	}
 }
 
-decl_event!(
-	pub enum Event<T, I> where
-		<T as frame_system::Trait>::AccountId,
-		<T as Trait<I>>::OracleKey,
-		<T as Trait<I>>::OracleValue,
-	{
-		/// New feed data is submitted. [sender, values]
-		NewFeedData(AccountId, Vec<(OracleKey, OracleValue)>),
-	}
-);
-
 impl<T: Trait<I>, I: Instance> Module<T, I> {
 	pub fn read_raw_values(key: &T::OracleKey) -> Vec<TimestampedValueOf<T, I>> {
 		Self::members()
@@ -240,9 +203,20 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 		T::CombineData::combine_data(key, values, Self::values(key))
 	}
 
-	fn do_feed_values(who: T::AccountId, values: Vec<(T::OracleKey, T::OracleValue)>) {
-		let now = T::Time::now();
+	fn do_feed_values(who: T::AccountId, values: Vec<(T::OracleKey, T::OracleValue)>) -> DispatchResult {
+		// ensure feeder is authorized
+		ensure!(
+			Self::members().contains(&who) || who == T::RootOperatorAccountId::get(),
+			Error::<T, I>::NoPermission
+		);
 
+		// ensure account hasn't dispatched an updated yet
+		ensure!(
+			HasDispatched::<T, I>::mutate(|set| set.insert(who.clone())),
+			Error::<T, I>::AlreadyFeeded
+		);
+
+		let now = T::Time::now();
 		for (key, value) in &values {
 			let timestamped = TimestampedValue {
 				value: value.clone(),
@@ -253,8 +227,8 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
 			T::OnNewData::on_new_data(&who, &key, &value);
 		}
-
 		Self::deposit_event(RawEvent::NewFeedData(who, values));
+		Ok(())
 	}
 }
 
@@ -271,9 +245,7 @@ impl<T: Trait<I>, I: Instance> ChangeMembers<T::AccountId> for Module<T, I> {
 	fn change_members_sorted(_incoming: &[T::AccountId], outgoing: &[T::AccountId], new: &[T::AccountId]) {
 		// remove session keys and its values
 		for removed in outgoing {
-			SessionKeys::<T, I>::remove(removed);
 			RawValues::<T, I>::remove_prefix(removed);
-			Nonces::<T, I>::remove(removed);
 		}
 
 		Members::<T, I>::put(OrderedSet::from_sorted_set(new.into()));
@@ -304,64 +276,7 @@ impl<T: Trait<I>, I: Instance> DataProviderExtended<T::OracleKey, TimestampedVal
 
 impl<T: Trait<I>, I: Instance> DataFeeder<T::OracleKey, T::OracleValue, T::AccountId> for Module<T, I> {
 	fn feed_value(who: T::AccountId, key: T::OracleKey, value: T::OracleValue) -> DispatchResult {
-		Self::do_feed_values(who, vec![(key, value)]);
+		Self::do_feed_values(who, vec![(key, value)])?;
 		Ok(())
 	}
 }
-
-impl<T: Trait<I>, I: Instance> frame_support::unsigned::ValidateUnsigned for Module<T, I> {
-	type Call = Call<T, I>;
-
-	fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
-		if let Call::feed_values(value, index, block, signature) = call {
-			let now = <frame_system::Module<T>>::block_number();
-
-			if now > *block + EXTRINSIC_LONGEVITY.into() {
-				return Err(InvalidTransaction::Stale.into());
-			}
-			if now < *block {
-				return Err(InvalidTransaction::Future.into());
-			}
-
-			let members = Module::<T, I>::members();
-			let who = members.0.get(*index as usize);
-			if let Some(who) = who {
-				let nonce = Module::<T, I>::nonces(&who);
-
-				let signature_valid = Module::<T, I>::session_keys(&who)
-					.map(|session_key| {
-						(nonce, block, value).using_encoded(|payload| session_key.verify(&payload, &signature))
-					})
-					.unwrap_or(false);
-
-				if !signature_valid {
-					return InvalidTransaction::BadProof.into();
-				}
-
-				// ensure account hasn't dispatched an updated yet
-				let ok = HasDispatched::<T, I>::mutate(|set| set.insert(who.clone()));
-				if !ok {
-					// we already received a feed for this operator
-					return Err(InvalidTransaction::Stale.into());
-				}
-
-				Nonces::<T, I>::insert(who, nonce + 1);
-
-				// make priority less likely to overflow.
-				// this ensures tx sent later overrides old one
-				let add_priority = TryInto::<TransactionPriority>::try_into(*block % 1000.into()).unwrap_or(0);
-
-				ValidTransaction::with_tag_prefix("orml-oracle")
-					.priority(T::UnsignedPriority::get().saturating_add(add_priority))
-					.and_provides((who, nonce))
-					.longevity(EXTRINSIC_LONGEVITY.into())
-					.propagate(true)
-					.build()
-			} else {
-				InvalidTransaction::BadProof.into()
-			}
-		} else {
-			InvalidTransaction::Call.into()
-		}
-	}
-}
diff --git a/oracle/src/mock.rs b/oracle/src/mock.rs
index d89960b..09d5026 100644
--- a/oracle/src/mock.rs
+++ b/oracle/src/mock.rs
@@ -2,16 +2,27 @@
 
 use super::*;
 
-use frame_support::{impl_outer_dispatch, impl_outer_origin, parameter_types, weights::Weight};
+use frame_support::{impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, weights::Weight};
 use sp_core::H256;
 use sp_runtime::{
-	testing::{Header, UintAuthorityId},
+	testing::Header,
 	traits::{BlakeTwo256, IdentityLookup},
 	Perbill,
 };
 
 use std::cell::RefCell;
 
+mod oracle {
+	pub use super::super::*;
+}
+
+impl_outer_event! {
+	pub enum TestEvent for Test {
+		frame_system<T>,
+		oracle<T>,
+	}
+}
+
 impl_outer_origin! {
 	pub enum Origin for Test {}
 }
@@ -22,7 +33,6 @@ impl_outer_dispatch! {
 	}
 }
 
-pub type OracleCall = super::Call<Test, Instance1>;
 pub type AccountId = u128;
 type Key = u32;
 type Value = u32;
@@ -48,7 +58,7 @@ impl frame_system::Trait for Test {
 	type AccountId = AccountId;
 	type Lookup = IdentityLookup<Self::AccountId>;
 	type Header = Header;
-	type Event = ();
+	type Event = TestEvent;
 	type BlockHashCount = BlockHashCount;
 	type MaximumBlockWeight = MaximumBlockWeight;
 	type MaximumBlockLength = MaximumBlockLength;
@@ -65,6 +75,7 @@ impl frame_system::Trait for Test {
 	type BaseCallFilter = ();
 	type SystemWeightInfo = ();
 }
+pub type System = frame_system::Module<Test>;
 
 thread_local! {
 	static TIME: RefCell<u32> = RefCell::new(0);
@@ -88,29 +99,28 @@ impl Timestamp {
 parameter_types! {
 	pub const MinimumCount: u32 = 3;
 	pub const ExpiresIn: u32 = 600;
-	pub const UnsignedPriority: TransactionPriority = 32u64;
+	pub const RootOperatorAccountId: AccountId = 4;
 }
 
-impl Trait<Instance1> for Test {
-	type Event = ();
+impl Trait for Test {
+	type Event = TestEvent;
 	type OnNewData = ();
-	type CombineData = DefaultCombineData<Self, Instance1, MinimumCount, ExpiresIn>;
+	type CombineData = DefaultCombineData<Self, MinimumCount, ExpiresIn>;
 	type Time = Timestamp;
 	type OracleKey = Key;
 	type OracleValue = Value;
-	type UnsignedPriority = UnsignedPriority;
-	type AuthorityId = UintAuthorityId;
+	type RootOperatorAccountId = RootOperatorAccountId;
 }
 
-pub type ModuleOracle = Module<Test, Instance1>;
+pub type ModuleOracle = Module<Test>;
 // This function basically just builds a genesis storage key/value store
 // according to our desired mockup.
 pub fn new_test_ext() -> sp_io::TestExternalities {
 	let mut storage = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
 
-	let _ = GenesisConfig::<Test, Instance1> {
+	let _ = GenesisConfig::<Test> {
 		members: vec![1, 2, 3].into(),
-		session_keys: vec![(1, 10.into()), (2, 20.into()), (3, 30.into())],
+		phantom: Default::default(),
 	}
 	.assimilate_storage(&mut storage);
 
diff --git a/oracle/src/tests.rs b/oracle/src/tests.rs
index 0455868..270203c 100644
--- a/oracle/src/tests.rs
+++ b/oracle/src/tests.rs
@@ -1,55 +1,37 @@
 #![cfg(test)]
 
 use crate::{
-	mock::{new_test_ext, AccountId, ModuleOracle, OracleCall, Origin, Test, Timestamp},
-	TimestampedValue,
+	mock::{new_test_ext, AccountId, ModuleOracle, Origin, RootOperatorAccountId, System, Test, TestEvent, Timestamp},
+	Error, RawEvent, TimestampedValue,
 };
-use codec::Encode;
 use frame_support::{
-	assert_noop, assert_ok, dispatch,
+	assert_noop, assert_ok,
 	traits::{ChangeMembers, OnFinalize},
-	unsigned::ValidateUnsigned,
+	weights::Pays,
 };
-use sp_runtime::{
-	testing::{TestSignature, UintAuthorityId},
-	transaction_validity::{InvalidTransaction, TransactionSource, TransactionValidityError},
-	RuntimeAppPublic,
-};
-
-fn feed_values_from_session_key(
-	id: UintAuthorityId,
-	index: u32,
-	nonce: u32,
-	values: Vec<(u32, u32)>,
-) -> Result<dispatch::DispatchResult, TransactionValidityError> {
-	let now = <frame_system::Module<Test>>::block_number();
-	let sig = id.sign(&(nonce, now, &values).encode()).unwrap();
-
-	<ModuleOracle as ValidateUnsigned>::validate_unsigned(
-		TransactionSource::External,
-		&OracleCall::feed_values(values.clone(), index, now, sig.clone()),
-	)?;
-
-	Ok(ModuleOracle::feed_values(Origin::none(), values, index, now, sig))
-}
-
-fn feed_values(
-	from: AccountId,
-	index: u32,
-	nonce: u32,
-	values: Vec<(u32, u32)>,
-) -> Result<dispatch::DispatchResult, TransactionValidityError> {
-	let id = ModuleOracle::session_keys(from).unwrap();
-
-	feed_values_from_session_key(id, index, nonce, values)
-}
 
 #[test]
-fn should_feed_values() {
+fn should_feed_values_from_member() {
 	new_test_ext().execute_with(|| {
+		System::set_block_number(1);
 		let account_id: AccountId = 1;
 
-		assert_ok!(feed_values(account_id, 0, 0, vec![(50, 1000), (51, 900), (52, 800)]));
+		assert_noop!(
+			ModuleOracle::feed_values(Origin::signed(5), vec![(50, 1000), (51, 900), (52, 800)]),
+			Error::<Test, _>::NoPermission,
+		);
+
+		assert_eq!(
+			ModuleOracle::feed_values(Origin::signed(account_id), vec![(50, 1000), (51, 900), (52, 800)])
+				.unwrap()
+				.pays_fee,
+			Pays::No
+		);
+
+		let new_feed_data_event = TestEvent::oracle(RawEvent::NewFeedData(1, vec![(50, 1000), (51, 900), (52, 800)]));
+		assert!(System::events()
+			.iter()
+			.any(|record| record.event == new_feed_data_event));
 
 		assert_eq!(
 			ModuleOracle::raw_values(&account_id, &50),
@@ -80,18 +62,15 @@ fn should_feed_values() {
 #[test]
 fn should_feed_values_from_root() {
 	new_test_ext().execute_with(|| {
-		let account_id: AccountId = 1;
+		let root_feeder: AccountId = RootOperatorAccountId::get();
 
 		assert_ok!(ModuleOracle::feed_values(
 			Origin::root(),
-			vec![(50, 1000), (51, 900), (52, 800)],
-			0,
-			0,
-			TestSignature(0, vec![])
+			vec![(50, 1000), (51, 900), (52, 800)]
 		));
 
 		assert_eq!(
-			ModuleOracle::raw_values(&account_id, &50),
+			ModuleOracle::raw_values(&root_feeder, &50),
 			Some(TimestampedValue {
 				value: 1000,
 				timestamp: 12345,
@@ -99,7 +78,7 @@ fn should_feed_values_from_root() {
 		);
 
 		assert_eq!(
-			ModuleOracle::raw_values(&account_id, &51),
+			ModuleOracle::raw_values(&root_feeder, &51),
 			Some(TimestampedValue {
 				value: 900,
 				timestamp: 12345,
@@ -107,7 +86,7 @@ fn should_feed_values_from_root() {
 		);
 
 		assert_eq!(
-			ModuleOracle::raw_values(&account_id, &52),
+			ModuleOracle::raw_values(&root_feeder, &52),
 			Some(TimestampedValue {
 				value: 800,
 				timestamp: 12345,
@@ -121,9 +100,9 @@ fn should_update_is_updated() {
 	new_test_ext().execute_with(|| {
 		let key: u32 = 50;
 		assert_eq!(ModuleOracle::is_updated(key), false);
-		assert_ok!(feed_values(1, 0, 0, vec![(key, 1000)]));
-		assert_ok!(feed_values(2, 1, 0, vec![(key, 1000)]));
-		assert_ok!(feed_values(3, 2, 0, vec![(key, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(key, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(key, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(key, 1000)]));
 		assert_eq!(ModuleOracle::is_updated(key), false);
 		assert_eq!(
 			ModuleOracle::get(&key).unwrap(),
@@ -134,50 +113,11 @@ fn should_update_is_updated() {
 		);
 		assert_eq!(ModuleOracle::is_updated(key), true);
 		ModuleOracle::on_finalize(1);
-		assert_ok!(feed_values(1, 0, 1, vec![(key, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(key, 1000)]));
 		assert_eq!(ModuleOracle::is_updated(key), false);
 	});
 }
 
-#[test]
-fn should_validate_index() {
-	new_test_ext().execute_with(|| {
-		assert_noop!(
-			feed_values(1, 1, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-
-		assert_noop!(
-			feed_values(2, 0, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-	});
-}
-
-#[test]
-fn should_validate_nonce() {
-	new_test_ext().execute_with(|| {
-		assert_noop!(
-			feed_values(1, 0, 1, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-
-		assert_ok!(feed_values(1, 0, 0, vec![(50, 1000)]));
-
-		assert_eq!(ModuleOracle::nonces(&1), 1);
-		ModuleOracle::on_finalize(1);
-
-		assert_noop!(
-			feed_values(1, 0, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-
-		assert_ok!(feed_values(1, 0, 1, vec![(50, 1000)]));
-
-		assert_eq!(ModuleOracle::nonces(&1), 2);
-	});
-}
-
 #[test]
 fn should_read_raw_values() {
 	new_test_ext().execute_with(|| {
@@ -186,8 +126,8 @@ fn should_read_raw_values() {
 		let raw_values = ModuleOracle::read_raw_values(&key);
 		assert_eq!(raw_values, vec![]);
 
-		assert_ok!(feed_values(1, 0, 0, vec![(key, 1000)]));
-		assert_ok!(feed_values(2, 1, 0, vec![(key, 1200)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(key, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(key, 1200)]));
 
 		let raw_values = ModuleOracle::read_raw_values(&key);
 		assert_eq!(
@@ -211,9 +151,9 @@ fn should_combined_data() {
 	new_test_ext().execute_with(|| {
 		let key: u32 = 50;
 
-		assert_ok!(feed_values(1, 0, 0, vec![(key, 1300)]));
-		assert_ok!(feed_values(2, 1, 0, vec![(key, 1000)]));
-		assert_ok!(feed_values(3, 2, 0, vec![(key, 1200)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(key, 1300)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(key, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(key, 1200)]));
 
 		let expected = Some(TimestampedValue {
 			value: 1200,
@@ -238,15 +178,15 @@ fn should_return_none_for_non_exist_key() {
 #[test]
 fn multiple_calls_should_fail() {
 	new_test_ext().execute_with(|| {
-		assert_ok!(feed_values(1, 0, 0, vec![(50, 1300)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1300)]));
 		assert_noop!(
-			feed_values(1, 0, 1, vec![(50, 1300)]),
-			TransactionValidityError::Invalid(InvalidTransaction::Stale)
+			ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1300)]),
+			Error::<Test, _>::AlreadyFeeded,
 		);
 
 		ModuleOracle::on_finalize(1);
 
-		assert_ok!(feed_values(1, 0, 1, vec![(50, 1300)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1300)]));
 	});
 }
 
@@ -259,9 +199,9 @@ fn get_all_values_should_work() {
 		assert_eq!(ModuleOracle::get_all_values(), vec![]);
 
 		// feed eur & jpy
-		assert_ok!(feed_values(1, 0, 0, vec![(eur, 1300)]));
-		assert_ok!(feed_values(2, 1, 0, vec![(eur, 1000)]));
-		assert_ok!(feed_values(3, 2, 0, vec![(jpy, 9000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(eur, 1300)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(eur, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(jpy, 9000)]));
 
 		// not enough eur & jpy prices
 		assert_eq!(ModuleOracle::get(&eur), None);
@@ -272,8 +212,8 @@ fn get_all_values_should_work() {
 		ModuleOracle::on_finalize(1);
 
 		// feed eur & jpy
-		assert_ok!(feed_values(3, 2, 1, vec![(eur, 1200)]));
-		assert_ok!(feed_values(1, 0, 1, vec![(jpy, 8000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(eur, 1200)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(jpy, 8000)]));
 
 		// enough eur prices
 		let eur_price = Some(TimestampedValue {
@@ -288,7 +228,7 @@ fn get_all_values_should_work() {
 		assert_eq!(ModuleOracle::get_all_values(), vec![(eur, eur_price)]);
 
 		// feed jpy
-		assert_ok!(feed_values(2, 1, 1, vec![(jpy, 7000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(jpy, 7000)]));
 
 		// enough jpy prices
 		let jpy_price = Some(TimestampedValue {
@@ -301,47 +241,25 @@ fn get_all_values_should_work() {
 	});
 }
 
-#[test]
-fn bad_index() {
-	new_test_ext().execute_with(|| {
-		assert_noop!(
-			feed_values(1, 255, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-	});
-}
-
 #[test]
 fn change_member_should_work() {
 	new_test_ext().execute_with(|| {
 		<ModuleOracle as ChangeMembers<AccountId>>::change_members_sorted(&[4], &[1], &[2, 3, 4]);
-
 		assert_noop!(
-			feed_values_from_session_key(10.into(), 0, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
+			ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1000)]),
+			Error::<Test, _>::NoPermission,
 		);
-
-		assert_ok!(feed_values(2, 0, 0, vec![(50, 1000)]));
-
-		assert_noop!(
-			feed_values_from_session_key(40.into(), 2, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-
-		assert_eq!(ModuleOracle::session_keys(&4), None);
-
-		assert_ok!(ModuleOracle::set_session_key(Origin::signed(4), 40.into()));
-
-		assert_ok!(feed_values(4, 2, 0, vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(4), vec![(50, 1000)]));
 	});
 }
 
 #[test]
 fn should_clear_is_updated_on_change_member() {
 	new_test_ext().execute_with(|| {
-		assert_ok!(feed_values(1, 0, 0, vec![(50, 1000)]));
-		assert_ok!(feed_values(2, 1, 0, vec![(50, 1000)]));
-		assert_ok!(feed_values(3, 2, 0, vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(50, 1000)]));
 
 		assert_eq!(
 			ModuleOracle::get(&50).unwrap(),
@@ -361,27 +279,11 @@ fn should_clear_is_updated_on_change_member() {
 #[test]
 fn should_clear_data_for_removed_members() {
 	new_test_ext().execute_with(|| {
-		assert_ok!(feed_values(1, 0, 0, vec![(50, 1000)]));
-		assert_ok!(feed_values(2, 1, 0, vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1000)]));
+		assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(50, 1000)]));
 
 		ModuleOracle::change_members_sorted(&[4], &[1], &[2, 3, 4]);
 
 		assert_eq!(ModuleOracle::raw_values(&1, 50), None);
-		assert_eq!(ModuleOracle::session_keys(&1), None);
-		assert_eq!(ModuleOracle::nonces(&1), 0);
-	});
-}
-
-#[test]
-fn change_session_key() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(ModuleOracle::set_session_key(Origin::signed(1), 11.into()));
-
-		assert_noop!(
-			feed_values_from_session_key(10.into(), 0, 0, vec![(50, 1000)]),
-			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
-		);
-
-		assert_ok!(feed_values_from_session_key(11.into(), 0, 0, vec![(50, 1000)]));
 	});
 }
-- 
GitLab