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