mithril_common/chain_observer/
fake_observer.rs1use async_trait::async_trait;
2use tokio::sync::RwLock;
3
4use crate::chain_observer::interface::*;
5use crate::chain_observer::{ChainAddress, TxDatum};
6use crate::crypto_helper::{KESPeriod, OpCert};
7use crate::{entities::*, test_utils::fake_data};
8
9pub struct FakeObserver {
11 pub signers: RwLock<Vec<SignerWithStake>>,
15
16 pub current_time_point: RwLock<Option<TimePoint>>,
20
21 pub datums: RwLock<Vec<TxDatum>>,
25
26 pub current_era: RwLock<String>,
30}
31
32impl FakeObserver {
33 pub fn new(current_time_point: Option<TimePoint>) -> Self {
35 Self {
36 signers: RwLock::new(vec![]),
37 current_time_point: RwLock::new(current_time_point.clone()),
38 datums: RwLock::new(vec![]),
39 current_era: RwLock::new(String::new()),
40 }
41 }
42
43 pub async fn next_epoch(&self) -> Option<Epoch> {
45 let mut current_time_point = self.current_time_point.write().await;
46 *current_time_point = current_time_point.as_ref().map(|time_point| TimePoint {
47 epoch: time_point.epoch + 1,
48 ..time_point.clone()
49 });
50
51 current_time_point.as_ref().map(|b| b.epoch)
52 }
53
54 pub async fn increase_block_number(&self, increment: u64) -> Option<BlockNumber> {
57 self.change_block_number(|actual_block_number| actual_block_number + increment)
58 .await
59 }
60
61 pub async fn decrease_block_number(&self, decrement: u64) -> Option<BlockNumber> {
64 self.change_block_number(|actual_block_number| actual_block_number - decrement)
65 .await
66 }
67
68 async fn change_block_number(
69 &self,
70 change_to_apply: impl Fn(BlockNumber) -> BlockNumber,
71 ) -> Option<BlockNumber> {
72 let mut current_time_point = self.current_time_point.write().await;
73
74 *current_time_point = current_time_point.as_ref().map(|time_point| TimePoint {
75 chain_point: ChainPoint {
76 block_number: change_to_apply(time_point.chain_point.block_number),
77 ..time_point.chain_point.clone()
78 },
79 ..time_point.clone()
80 });
81
82 current_time_point
83 .as_ref()
84 .map(|b| b.chain_point.block_number)
85 }
86
87 pub async fn increase_slot_number(&self, increment: u64) -> Option<SlotNumber> {
90 self.change_slot_number(|actual_slot_number| actual_slot_number + increment)
91 .await
92 }
93
94 pub async fn decrease_slot_number(&self, decrement: u64) -> Option<SlotNumber> {
97 self.change_slot_number(|actual_slot_number| actual_slot_number - decrement)
98 .await
99 }
100
101 async fn change_slot_number(
102 &self,
103 change_to_apply: impl Fn(SlotNumber) -> SlotNumber,
104 ) -> Option<SlotNumber> {
105 let mut current_time_point = self.current_time_point.write().await;
106
107 *current_time_point = current_time_point.as_ref().map(|time_point| TimePoint {
108 chain_point: ChainPoint {
109 slot_number: change_to_apply(time_point.chain_point.slot_number),
110 ..time_point.chain_point.clone()
111 },
112 ..time_point.clone()
113 });
114
115 current_time_point
116 .as_ref()
117 .map(|b| b.chain_point.slot_number)
118 }
119
120 pub async fn set_signers(&self, new_signers: Vec<SignerWithStake>) {
123 let mut signers = self.signers.write().await;
124 *signers = new_signers;
125 }
126
127 pub async fn set_current_time_point(&self, new_current_time_point: Option<TimePoint>) {
129 let mut current_time_point = self.current_time_point.write().await;
130 *current_time_point = new_current_time_point;
131 }
132
133 pub async fn set_datums(&self, new_datums: Vec<TxDatum>) {
136 let mut datums = self.datums.write().await;
137 *datums = new_datums;
138 }
139
140 pub async fn set_current_era(&self, new_current_era: String) {
143 let mut current_era = self.current_era.write().await;
144 *current_era = new_current_era;
145 }
146}
147
148impl Default for FakeObserver {
149 fn default() -> Self {
150 let mut observer = Self::new(Some(TimePoint::dummy()));
151 observer.signers = RwLock::new(fake_data::signers_with_stakes(2));
152
153 observer
154 }
155}
156
157#[async_trait]
158impl ChainObserver for FakeObserver {
159 async fn get_current_datums(
160 &self,
161 _address: &ChainAddress,
162 ) -> Result<Vec<TxDatum>, ChainObserverError> {
163 let datums = self.datums.read().await;
164 Ok(datums.to_vec())
165 }
166
167 async fn get_current_era(&self) -> Result<Option<String>, ChainObserverError> {
168 Ok(Some(self.current_era.read().await.clone()))
169 }
170
171 async fn get_current_epoch(&self) -> Result<Option<Epoch>, ChainObserverError> {
172 Ok(self
173 .current_time_point
174 .read()
175 .await
176 .as_ref()
177 .map(|time_point| time_point.epoch))
178 }
179
180 async fn get_current_chain_point(&self) -> Result<Option<ChainPoint>, ChainObserverError> {
181 Ok(self
182 .current_time_point
183 .read()
184 .await
185 .as_ref()
186 .map(|time_point| time_point.chain_point.clone()))
187 }
188
189 async fn get_current_stake_distribution(
190 &self,
191 ) -> Result<Option<StakeDistribution>, ChainObserverError> {
192 Ok(Some(
193 self.signers
194 .read()
195 .await
196 .iter()
197 .map(|signer| (signer.party_id.clone() as PartyId, signer.stake as Stake))
198 .collect::<StakeDistribution>(),
199 ))
200 }
201
202 async fn get_current_kes_period(
203 &self,
204 _opcert: &OpCert,
205 ) -> Result<Option<KESPeriod>, ChainObserverError> {
206 Ok(Some(0))
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use crate::test_utils::fake_data;
213
214 use super::*;
215
216 #[tokio::test]
217 async fn test_get_current_epoch() {
218 let time_point = TimePoint::dummy();
219 let fake_observer = FakeObserver::new(Some(time_point.clone()));
220 let current_epoch = fake_observer.get_current_epoch().await.unwrap();
221
222 assert_eq!(Some(time_point.epoch), current_epoch);
223 }
224
225 #[tokio::test]
226 async fn test_get_current_chain_point() {
227 let fake_observer = FakeObserver::new(None);
228 fake_observer
229 .set_current_time_point(Some(TimePoint::dummy()))
230 .await;
231 let chain_point = fake_observer.get_current_chain_point().await.unwrap();
232
233 assert_eq!(
234 Some(TimePoint::dummy().chain_point),
235 chain_point,
236 "get current chain point should not fail"
237 );
238 }
239
240 #[tokio::test]
241 async fn test_get_current_stake_distribution() {
242 let fake_observer = FakeObserver::new(None);
243 fake_observer
244 .set_signers(fake_data::signers_with_stakes(2))
245 .await;
246 let stake_distribution = fake_observer.get_current_stake_distribution().await;
247
248 assert_eq!(
249 2,
250 stake_distribution.unwrap().unwrap().len(),
251 "get current stake distribution should not fail and should not be empty"
252 );
253 }
254
255 #[tokio::test]
256 async fn test_get_current_datums() {
257 let fake_address = "addr_test_123456".to_string();
258 let fake_datums = vec![
259 TxDatum("tx_datum_1".to_string()),
260 TxDatum("tx_datum_2".to_string()),
261 ];
262 let fake_observer = FakeObserver::new(None);
263 fake_observer.set_datums(fake_datums.clone()).await;
264 let datums = fake_observer
265 .get_current_datums(&fake_address)
266 .await
267 .expect("get_current_datums should not fail");
268
269 assert_eq!(fake_datums, datums);
270 }
271
272 #[tokio::test]
273 async fn test_increase_block_number() {
274 let fake_observer = FakeObserver::new(None);
275 fake_observer
276 .set_current_time_point(Some(TimePoint::dummy()))
277 .await;
278 fake_observer.increase_block_number(375).await;
279
280 let chain_point = fake_observer.get_current_chain_point().await.unwrap();
281 assert_eq!(
282 Some(ChainPoint {
283 block_number: TimePoint::dummy().chain_point.block_number + 375,
284 ..TimePoint::dummy().chain_point
285 }),
286 chain_point,
287 "get current chain point should not fail"
288 );
289 }
290
291 #[tokio::test]
292 async fn test_decrease_block_number() {
293 let fake_observer = FakeObserver::new(None);
294 fake_observer
295 .set_current_time_point(Some(TimePoint {
296 chain_point: ChainPoint {
297 block_number: BlockNumber(1000),
298 ..TimePoint::dummy().chain_point
299 },
300 ..TimePoint::dummy()
301 }))
302 .await;
303 fake_observer.decrease_block_number(800).await;
304
305 let chain_point = fake_observer.get_current_chain_point().await.unwrap();
306 assert_eq!(
307 Some(ChainPoint {
308 block_number: BlockNumber(200),
309 ..TimePoint::dummy().chain_point
310 }),
311 chain_point,
312 "get current chain point should not fail"
313 );
314 }
315
316 #[tokio::test]
317 async fn test_increase_slot_number() {
318 let fake_observer = FakeObserver::new(None);
319 fake_observer
320 .set_current_time_point(Some(TimePoint::dummy()))
321 .await;
322 fake_observer.increase_slot_number(375).await;
323
324 let chain_point = fake_observer.get_current_chain_point().await.unwrap();
325 assert_eq!(
326 Some(ChainPoint {
327 slot_number: TimePoint::dummy().chain_point.slot_number + 375,
328 ..TimePoint::dummy().chain_point
329 }),
330 chain_point,
331 "get current chain point should not fail"
332 );
333 }
334
335 #[tokio::test]
336 async fn test_decrease_slot_number() {
337 let fake_observer = FakeObserver::new(None);
338 fake_observer
339 .set_current_time_point(Some(TimePoint {
340 chain_point: ChainPoint {
341 slot_number: SlotNumber(1000),
342 ..TimePoint::dummy().chain_point
343 },
344 ..TimePoint::dummy()
345 }))
346 .await;
347 fake_observer.decrease_slot_number(800).await;
348
349 let chain_point = fake_observer.get_current_chain_point().await.unwrap();
350 assert_eq!(
351 Some(ChainPoint {
352 slot_number: SlotNumber(200),
353 ..TimePoint::dummy().chain_point
354 }),
355 chain_point,
356 "get current chain point should not fail"
357 );
358 }
359
360 #[tokio::test]
361 async fn test_get_current_era() {
362 let fake_observer = FakeObserver::new(None);
363
364 let current_era = fake_observer
365 .get_current_era()
366 .await
367 .expect("get_current_era should not fail");
368 assert_ne!(Some("Conway".to_string()), current_era);
369
370 fake_observer.set_current_era("Conway".to_string()).await;
371 let current_era = fake_observer
372 .get_current_era()
373 .await
374 .expect("get_current_era should not fail");
375 assert_eq!(Some("Conway".to_string()), current_era);
376 }
377}