Skip to content

Commit c439a50

Browse files
syan095Roy Yang
and
Roy Yang
authored
Changed the way values are updated (#720)
* Changed the way values are updated. Instead of updating on "get", values are updated on feed. * minor improvement * Addressed some PR comments * Simplified get_all_values function. * formatted Co-authored-by: Roy Yang <[email protected]>
1 parent 2d28694 commit c439a50

File tree

2 files changed

+26
-83
lines changed

2 files changed

+26
-83
lines changed

oracle/src/lib.rs

+11-44
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,13 @@ pub mod module {
119119
pub type RawValues<T: Config<I>, I: 'static = ()> =
120120
StorageDoubleMap<_, Twox64Concat, T::AccountId, Twox64Concat, T::OracleKey, TimestampedValueOf<T, I>>;
121121

122-
/// True if Self::values(key) is up to date, otherwise the value is stale
123-
#[pallet::storage]
124-
#[pallet::getter(fn is_updated)]
125-
pub type IsUpdated<T: Config<I>, I: 'static = ()> =
126-
StorageMap<_, Twox64Concat, <T as Config<I>>::OracleKey, bool, ValueQuery>;
127-
128-
/// Combined value, may not be up to date
122+
/// Up to date combined value from Raw Values
129123
#[pallet::storage]
130124
#[pallet::getter(fn values)]
131125
pub type Values<T: Config<I>, I: 'static = ()> =
132126
StorageMap<_, Twox64Concat, <T as Config<I>>::OracleKey, TimestampedValueOf<T, I>>;
133127

134-
/// If an oracle operator has feed a value in this block
128+
/// If an oracle operator has fed a value in this block
135129
#[pallet::storage]
136130
pub(crate) type HasDispatched<T: Config<I>, I: 'static = ()> =
137131
StorageValue<_, OrderedSet<T::AccountId, T::MaxHasDispatchedSize>, ValueQuery>;
@@ -182,42 +176,14 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
182176
.collect()
183177
}
184178

185-
/// Returns fresh combined value if has update, or latest combined
186-
/// value.
187-
///
188-
/// Note this will update values storage if has update.
179+
/// Fetch current combined value.
189180
pub fn get(key: &T::OracleKey) -> Option<TimestampedValueOf<T, I>> {
190-
if Self::is_updated(key) {
191-
<Values<T, I>>::get(key)
192-
} else {
193-
let timestamped = Self::combined(key)?;
194-
<Values<T, I>>::insert(key, timestamped.clone());
195-
IsUpdated::<T, I>::insert(key, true);
196-
Some(timestamped)
197-
}
198-
}
199-
200-
/// Returns fresh combined value if has update, or latest combined
201-
/// value.
202-
///
203-
/// This is a no-op function which would not change storage.
204-
pub fn get_no_op(key: &T::OracleKey) -> Option<TimestampedValueOf<T, I>> {
205-
if Self::is_updated(key) {
206-
Self::values(key)
207-
} else {
208-
Self::combined(key)
209-
}
181+
Self::values(key)
210182
}
211183

212184
#[allow(clippy::complexity)]
213185
pub fn get_all_values() -> Vec<(T::OracleKey, Option<TimestampedValueOf<T, I>>)> {
214-
<Values<T, I>>::iter()
215-
.map(|(key, _)| key)
216-
.map(|key| {
217-
let v = Self::get_no_op(&key);
218-
(key, v)
219-
})
220-
.collect()
186+
<Values<T, I>>::iter().map(|(k, v)| (k, Some(v))).collect()
221187
}
222188

223189
fn combined(key: &T::OracleKey) -> Option<TimestampedValueOf<T, I>> {
@@ -247,7 +213,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
247213
timestamp: now,
248214
};
249215
RawValues::<T, I>::insert(&who, &key, timestamped);
250-
IsUpdated::<T, I>::remove(&key);
216+
217+
// Update `Values` storage if `combined` yielded result.
218+
if let Some(combined) = Self::combined(key) {
219+
<Values<T, I>>::insert(key, combined);
220+
}
251221

252222
T::OnNewData::on_new_data(&who, key, value);
253223
}
@@ -262,9 +232,6 @@ impl<T: Config<I>, I: 'static> ChangeMembers<T::AccountId> for Pallet<T, I> {
262232
for removed in outgoing {
263233
RawValues::<T, I>::remove_prefix(removed, None);
264234
}
265-
266-
// not bothering to track which key needs recompute, just update all
267-
IsUpdated::<T, I>::remove_all(None);
268235
}
269236

270237
fn set_prime(_prime: Option<T::AccountId>) {
@@ -279,7 +246,7 @@ impl<T: Config<I>, I: 'static> DataProvider<T::OracleKey, T::OracleValue> for Pa
279246
}
280247
impl<T: Config<I>, I: 'static> DataProviderExtended<T::OracleKey, TimestampedValueOf<T, I>> for Pallet<T, I> {
281248
fn get_no_op(key: &T::OracleKey) -> Option<TimestampedValueOf<T, I>> {
282-
Self::get_no_op(key)
249+
Self::get(key)
283250
}
284251

285252
#[allow(clippy::complexity)]

oracle/src/tests.rs

+15-39
Original file line numberDiff line numberDiff line change
@@ -100,29 +100,6 @@ fn should_not_feed_values_from_root_directly() {
100100
});
101101
}
102102

103-
#[test]
104-
fn should_update_is_updated() {
105-
new_test_ext().execute_with(|| {
106-
let key: u32 = 50;
107-
assert!(!ModuleOracle::is_updated(key));
108-
assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(key, 1000)]));
109-
assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(key, 1000)]));
110-
assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(key, 1000)]));
111-
assert!(!ModuleOracle::is_updated(key));
112-
assert_eq!(
113-
ModuleOracle::get(&key).unwrap(),
114-
TimestampedValue {
115-
value: 1000,
116-
timestamp: 12345
117-
}
118-
);
119-
assert!(ModuleOracle::is_updated(key));
120-
ModuleOracle::on_finalize(1);
121-
assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(key, 1000)]));
122-
assert!(!ModuleOracle::is_updated(key));
123-
});
124-
}
125-
126103
#[test]
127104
fn should_read_raw_values() {
128105
new_test_ext().execute_with(|| {
@@ -261,35 +238,34 @@ fn change_member_should_work() {
261238
}
262239

263240
#[test]
264-
fn should_clear_is_updated_on_change_member() {
241+
fn should_clear_data_for_removed_members() {
265242
new_test_ext().execute_with(|| {
266243
assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1000)]));
267244
assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(50, 1000)]));
268-
assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(50, 1000)]));
269-
270-
assert_eq!(
271-
ModuleOracle::get(&50).unwrap(),
272-
TimestampedValue {
273-
value: 1000,
274-
timestamp: 12345
275-
}
276-
);
277-
assert!(ModuleOracle::is_updated(50));
278245

279246
ModuleOracle::change_members_sorted(&[4], &[1], &[2, 3, 4]);
280247

281-
assert!(!ModuleOracle::is_updated(50));
248+
assert_eq!(ModuleOracle::raw_values(&1, 50), None);
282249
});
283250
}
284251

285252
#[test]
286-
fn should_clear_data_for_removed_members() {
253+
fn values_are_updated_on_feed() {
287254
new_test_ext().execute_with(|| {
288-
assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 1000)]));
255+
assert_ok!(ModuleOracle::feed_values(Origin::signed(1), vec![(50, 900)]));
289256
assert_ok!(ModuleOracle::feed_values(Origin::signed(2), vec![(50, 1000)]));
290257

291-
ModuleOracle::change_members_sorted(&[4], &[1], &[2, 3, 4]);
258+
assert_eq!(ModuleOracle::values(50), None);
292259

293-
assert_eq!(ModuleOracle::raw_values(&1, 50), None);
260+
// Upon the third price feed, the value is updated immediately after `combine`
261+
// can produce valid result.
262+
assert_ok!(ModuleOracle::feed_values(Origin::signed(3), vec![(50, 1100)]));
263+
assert_eq!(
264+
ModuleOracle::values(50),
265+
Some(TimestampedValue {
266+
value: 1000,
267+
timestamp: 12345,
268+
})
269+
);
294270
});
295271
}

0 commit comments

Comments
 (0)