partner_chains_mock_data_sources/
block.rs

1use crate::Result;
2use sidechain_domain::*;
3use sp_timestamp::Timestamp;
4
5/// Mock block data data source, for internal use by other mock data sources
6///
7/// This data source serves synthetic block data generated deterministically from the inputs.
8pub struct BlockDataSourceMock {
9	/// Duration of a mainchain epoch in milliseconds
10	mc_epoch_duration_millis: u32,
11}
12
13impl BlockDataSourceMock {
14	pub(crate) async fn get_latest_block_info(&self) -> Result<MainchainBlock> {
15		Ok(self
16			.get_latest_stable_block_for(Timestamp::new(BlockDataSourceMock::millis_now()))
17			.await
18			.unwrap()
19			.unwrap())
20	}
21
22	pub(crate) async fn get_latest_stable_block_for(
23		&self,
24		reference_timestamp: Timestamp,
25	) -> Result<Option<MainchainBlock>> {
26		let block_number = (reference_timestamp.as_millis() / 20000) as u32;
27		let epoch = block_number / self.block_per_epoch();
28		let mut hash_arr = [0u8; 32];
29		hash_arr[..4].copy_from_slice(&block_number.to_be_bytes());
30		Ok(Some(MainchainBlock {
31			number: McBlockNumber(block_number),
32			hash: McBlockHash(hash_arr),
33			epoch: McEpochNumber(epoch),
34			slot: McSlotNumber(block_number as u64),
35			timestamp: reference_timestamp.as_millis(),
36		}))
37	}
38
39	pub(crate) async fn get_stable_block_for(
40		&self,
41		_hash: McBlockHash,
42		reference_timestamp: Timestamp,
43	) -> Result<Option<MainchainBlock>> {
44		self.get_latest_stable_block_for(reference_timestamp).await
45	}
46
47	pub(crate) async fn get_block_by_hash(
48		&self,
49		hash: McBlockHash,
50	) -> Result<Option<MainchainBlock>> {
51		// reverse of computation in `get_latest_stable_block_for`
52		let block_number = u32::from_be_bytes(hash.0[..4].try_into().unwrap());
53		let timestamp = block_number * 20000;
54		let epoch = block_number / self.block_per_epoch();
55		Ok(Some(MainchainBlock {
56			number: McBlockNumber(block_number),
57			hash,
58			epoch: McEpochNumber(epoch),
59			slot: McSlotNumber(epoch.into()),
60			timestamp: timestamp.into(),
61		}))
62	}
63}
64
65impl BlockDataSourceMock {
66	/// Creates new data source
67	pub fn new(mc_epoch_duration_millis: u32) -> Self {
68		Self { mc_epoch_duration_millis }
69	}
70
71	/// Creates new data source, reading configuration from environment
72	pub fn new_from_env() -> Result<Self> {
73		let mc_epoch_duration_millis: u32 =
74			std::env::var("MC__EPOCH_DURATION_MILLIS")?.parse::<u32>()?;
75		Ok(Self::new(mc_epoch_duration_millis))
76	}
77
78	fn block_per_epoch(&self) -> u32 {
79		self.mc_epoch_duration_millis / 20000
80	}
81
82	fn millis_now() -> u64 {
83		std::time::SystemTime::now()
84			.duration_since(std::time::UNIX_EPOCH)
85			.unwrap()
86			.as_millis() as u64
87	}
88}