1use crate::{
7 Address, BlockHeader, CodeBlobInfo, Digest, HashOf, ProgramStates, ProtocolTimelines, Schedule,
8 SimpleBlockData, ValidatorsVec,
9 events::BlockEvent,
10 gear::StateTransition,
11 injected::{InjectedTransaction, Promise, SignedInjectedTransaction, SignedTxReceipt},
12 malachite::Transactions,
13};
14use alloc::{
15 collections::{BTreeSet, VecDeque},
16 vec::Vec,
17};
18use gear_core::{
19 code::{CodeMetadata, InstrumentedCode},
20 ids::{ActorId, CodeId},
21};
22use gprimitives::H256;
23use parity_scale_codec::{Decode, Encode};
24use scale_info::TypeInfo;
25
26#[derive(Clone, Debug, Default, Encode, Decode, TypeInfo, PartialEq, Eq, Hash)]
28pub struct BlockMeta {
29 pub prepared: bool,
32 pub codes_queue: Option<VecDeque<CodeId>>,
34 pub last_committed_batch: Option<Digest>,
36 pub last_committed_mb: Option<H256>,
38 pub last_committed_eb: Option<H256>,
40 pub latest_era_validators_committed: Option<u64>,
42}
43
44#[auto_impl::auto_impl(&, Box)]
45pub trait HashStorageRO {
46 fn read_by_hash(&self, hash: H256) -> Option<Vec<u8>>;
47}
48
49#[auto_impl::auto_impl(&, Box)]
50pub trait BlockMetaStorageRO {
51 fn block_meta(&self, block_hash: H256) -> BlockMeta;
53}
54
55#[auto_impl::auto_impl(&)]
56pub trait BlockMetaStorageRW: BlockMetaStorageRO {
57 fn mutate_block_meta(&self, block_hash: H256, f: impl FnOnce(&mut BlockMeta));
60}
61
62#[auto_impl::auto_impl(&, Box)]
63pub trait CodesStorageRO {
64 fn original_code_exists(&self, code_id: CodeId) -> bool;
65 fn original_code(&self, code_id: CodeId) -> Option<Vec<u8>>;
66 fn program_code_id(&self, program_id: ActorId) -> Option<CodeId>;
67 fn instrumented_code_exists(&self, runtime_id: u32, code_id: CodeId) -> bool;
68 fn instrumented_code(&self, runtime_id: u32, code_id: CodeId) -> Option<InstrumentedCode>;
69 fn code_metadata(&self, code_id: CodeId) -> Option<CodeMetadata>;
70 fn code_valid(&self, code_id: CodeId) -> Option<bool>;
71 fn valid_codes(&self) -> BTreeSet<CodeId>;
72}
73
74#[auto_impl::auto_impl(&)]
75pub trait CodesStorageRW: CodesStorageRO {
76 fn set_original_code(&self, code: &[u8]) -> CodeId;
77 fn set_program_code_id(&self, program_id: ActorId, code_id: CodeId);
78 fn set_instrumented_code(&self, runtime_id: u32, code_id: CodeId, code: InstrumentedCode);
79 fn set_code_metadata(&self, code_id: CodeId, code_metadata: CodeMetadata);
80 fn set_code_valid(&self, code_id: CodeId, valid: bool);
81}
82
83#[auto_impl::auto_impl(&, Box)]
84pub trait OnChainStorageRO {
85 fn block_header(&self, block_hash: H256) -> Option<BlockHeader>;
86 fn block_events(&self, block_hash: H256) -> Option<Vec<BlockEvent>>;
87 fn code_blob_info(&self, code_id: CodeId) -> Option<CodeBlobInfo>;
88 fn block_synced(&self, block_hash: H256) -> bool;
89 fn validators(&self, era_index: u64) -> Option<ValidatorsVec>;
90
91 fn block_simple_data(&self, block_hash: H256) -> Option<SimpleBlockData> {
92 self.block_header(block_hash).map(|header| SimpleBlockData {
93 hash: block_hash,
94 header,
95 })
96 }
97}
98
99#[auto_impl::auto_impl(&)]
100pub trait OnChainStorageRW: OnChainStorageRO {
101 fn set_block_header(&self, block_hash: H256, header: BlockHeader);
102 fn set_block_events(&self, block_hash: H256, events: &[BlockEvent]);
103 fn set_code_blob_info(&self, code_id: CodeId, code_info: CodeBlobInfo);
104 fn set_validators(&self, era_index: u64, validator_set: ValidatorsVec);
105 fn set_block_synced(&self, block_hash: H256);
106}
107
108#[auto_impl::auto_impl(&)]
109pub trait InjectedStorageRO {
110 fn injected_transaction(
112 &self,
113 hash: HashOf<InjectedTransaction>,
114 ) -> Option<SignedInjectedTransaction>;
115
116 fn promise(&self, hash: HashOf<InjectedTransaction>) -> Option<Promise>;
118
119 fn receipt(&self, hash: HashOf<InjectedTransaction>) -> Option<SignedTxReceipt>;
121}
122
123#[auto_impl::auto_impl(&)]
124pub trait InjectedStorageRW: InjectedStorageRO {
125 fn set_injected_transaction(&self, tx: SignedInjectedTransaction);
126
127 fn set_promise(&self, promise: &Promise);
128
129 fn set_receipt(&self, receipt: &SignedTxReceipt);
130}
131
132#[derive(
135 Debug, Clone, Copy, Default, Encode, Decode, TypeInfo, PartialEq, Eq, Hash, derive_more::Display,
136)]
137#[display("MB(height {height}, parent {parent}, transactions_hash {transactions_hash})")]
138pub struct CompactMb {
139 pub parent: H256,
140 pub height: u64,
141 pub transactions_hash: H256,
142}
143
144#[derive(Debug, Clone, Default, Encode, Decode, TypeInfo, PartialEq, Eq, Hash)]
148pub struct MbMeta {
149 pub computed: bool,
150 pub last_advanced_eb: H256,
151}
152
153#[auto_impl::auto_impl(&, Box)]
154pub trait MbStorageRO {
155 fn mb_compact_block(&self, mb_hash: H256) -> Option<CompactMb>;
159 fn transactions(&self, transactions_hash: H256) -> Option<Transactions>;
161 fn mb_program_states(&self, mb_hash: H256) -> Option<ProgramStates>;
162 fn mb_outcome(&self, mb_hash: H256) -> Option<Vec<StateTransition>>;
163 fn mb_schedule(&self, mb_hash: H256) -> Option<Schedule>;
164 fn mb_meta(&self, mb_hash: H256) -> MbMeta;
165}
166
167#[auto_impl::auto_impl(&)]
168pub trait MbStorageRW: MbStorageRO {
169 fn set_mb_compact_block(&self, mb_hash: H256, compact: CompactMb);
170 fn set_transactions(&self, transactions: Transactions) -> H256;
173 fn set_mb_program_states(&self, mb_hash: H256, program_states: ProgramStates);
174 fn set_mb_outcome(&self, mb_hash: H256, outcome: Vec<StateTransition>);
175 fn set_mb_schedule(&self, mb_hash: H256, schedule: Schedule);
176 fn mutate_mb_meta(&self, mb_hash: H256, f: impl FnOnce(&mut MbMeta));
177}
178
179pub struct PreparedBlockData {
180 pub header: BlockHeader,
181 pub events: Vec<BlockEvent>,
182 pub latest_era_with_committed_validators: u64,
183 pub codes_queue: VecDeque<CodeId>,
184 pub last_committed_batch: Digest,
185 pub last_committed_mb: H256,
186 pub last_committed_eb: H256,
187}
188
189#[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq)]
190pub struct DBConfig {
191 pub version: u32,
192 pub chain_id: u64,
193 pub router_address: Address,
194 pub timelines: ProtocolTimelines,
195 pub genesis_block_hash: H256,
196 pub max_validators: u16,
197}
198
199#[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq)]
200pub struct DBGlobals {
201 pub start_block_hash: H256,
202 pub latest_synced_eb: SimpleBlockData,
203 pub latest_prepared_eb_hash: H256,
204 pub latest_finalized_mb_hash: H256,
209 pub latest_computed_mb_hash: H256,
213}
214
215#[cfg(feature = "std")]
216mod std_interfaces {
217 use super::{DBConfig, DBGlobals};
218 use std::sync::RwLockReadGuard;
219
220 #[auto_impl::auto_impl(&, Box)]
221 pub trait GlobalsStorageRO {
222 fn globals(&self) -> RwLockReadGuard<'_, DBGlobals>;
223 }
224
225 #[auto_impl::auto_impl(&, Box)]
226 pub trait GlobalsStorageRW: GlobalsStorageRO {
227 fn globals_mutate<R>(&self, f: impl FnMut(&mut DBGlobals) -> R) -> R;
228 }
229
230 #[auto_impl::auto_impl(&, Box)]
231 pub trait ConfigStorageRO {
232 fn config(&self) -> RwLockReadGuard<'_, DBConfig>;
233 }
234}
235
236#[cfg(feature = "std")]
237pub use std_interfaces::{ConfigStorageRO, GlobalsStorageRO, GlobalsStorageRW};
238
239#[cfg(feature = "mock")]
240mod mock_interfaces {
241 use super::{DBConfig, DBGlobals};
242
243 #[auto_impl::auto_impl(&, Box)]
244 pub trait SetGlobals {
245 fn set_globals(&self, globals: DBGlobals);
246 }
247
248 #[auto_impl::auto_impl(&, Box)]
249 pub trait SetConfig {
250 fn set_config(&self, config: DBConfig);
251 }
252}
253
254#[cfg(feature = "mock")]
255pub use mock_interfaces::{SetConfig, SetGlobals};
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260 use crate::malachite::Transactions;
261 use indoc::formatdoc;
262 use scale_info::{PortableRegistry, Registry, meta_type};
263 use sha3::{Digest, Sha3_256};
264
265 #[test]
266 fn ensure_types_unchanged() {
267 const EXPECTED_TYPE_INFO_HASH: &str =
268 "d43d8ab319fb6d934231dba55950c9825e28c6ecf603e8076a90e0cab3855671";
269
270 let types = [
271 meta_type::<BlockMeta>(),
272 meta_type::<InstrumentedCode>(),
273 meta_type::<CodeMetadata>(),
274 meta_type::<BlockHeader>(),
275 meta_type::<BlockEvent>(),
276 meta_type::<CodeBlobInfo>(),
277 meta_type::<ValidatorsVec>(),
278 meta_type::<ProtocolTimelines>(),
279 meta_type::<HashOf<InjectedTransaction>>(),
280 meta_type::<SignedInjectedTransaction>(),
281 meta_type::<ProgramStates>(),
282 meta_type::<StateTransition>(),
283 meta_type::<Schedule>(),
284 meta_type::<MbMeta>(),
285 meta_type::<CompactMb>(),
286 meta_type::<Transactions>(),
287 meta_type::<DBConfig>(),
288 meta_type::<DBGlobals>(),
289 ];
290
291 let mut registry = Registry::new();
292 registry.register_types(types);
293
294 let portable_registry = PortableRegistry::from(registry);
295 let encoded_registry = portable_registry.encode();
296 let type_info_hash = hex::encode(Sha3_256::digest(encoded_registry));
297
298 if type_info_hash != EXPECTED_TYPE_INFO_HASH {
299 panic!(
300 "{}",
301 formatdoc!(
302 "
303 Some of database types has been changed.
304
305 It can break existing databases, so be very careful and think at least
306 twice before committing such changes. Ensure that SCALE representations
307 of all changed database types are still the same.
308
309 If you know what exactly has been changed and sure about it,
310 please update `EXPECTED_TYPE_INFO_HASH` constant in this test
311 to the new value to fix the assertion.
312
313 Expected hash: {EXPECTED_TYPE_INFO_HASH}
314 Found hash: {type_info_hash}
315 "
316 )
317 );
318 }
319 }
320}