fuel_core/database/
metadata.rs

1use super::database_description::{
2    IndexationKind,
3    indexation_availability,
4};
5use crate::database::{
6    Database,
7    Error as DatabaseError,
8    database_description::{
9        DatabaseDescription,
10        DatabaseMetadata,
11    },
12};
13use fuel_core_storage::{
14    Error as StorageError,
15    Mappable,
16    Result as StorageResult,
17    StorageAsRef,
18    StorageInspect,
19    blueprint::plain::Plain,
20    codec::postcard::Postcard,
21    structured_storage::TableWithBlueprint,
22};
23
24/// The table that stores all metadata about the database.
25pub struct MetadataTable<Description>(core::marker::PhantomData<Description>);
26
27impl<Description> Mappable for MetadataTable<Description>
28where
29    Description: DatabaseDescription,
30{
31    type Key = ();
32    type OwnedKey = ();
33    type Value = DatabaseMetadata<Description::Height>;
34    type OwnedValue = Self::Value;
35}
36
37impl<Description> TableWithBlueprint for MetadataTable<Description>
38where
39    Description: DatabaseDescription,
40{
41    type Blueprint = Plain<Postcard, Postcard>;
42    type Column = Description::Column;
43
44    fn column() -> Self::Column {
45        Description::metadata_column()
46    }
47}
48
49impl<Description, Stage> Database<Description, Stage>
50where
51    Description: DatabaseDescription,
52    Self: StorageInspect<MetadataTable<Description>, Error = StorageError>,
53{
54    /// Ensures the version is correct.
55    pub fn check_version(&self) -> StorageResult<()> {
56        let Some(metadata) = self.storage::<MetadataTable<Description>>().get(&())?
57        else {
58            return Ok(());
59        };
60
61        if metadata.version() != Description::version() {
62            return Err(DatabaseError::InvalidDatabaseVersion {
63                found: metadata.version(),
64                expected: Description::version(),
65            }
66            .into())
67        }
68
69        Ok(())
70    }
71
72    pub fn latest_height_from_metadata(
73        &self,
74    ) -> StorageResult<Option<Description::Height>> {
75        let metadata = self.storage::<MetadataTable<Description>>().get(&())?;
76
77        let metadata = metadata.map(|metadata| *metadata.height());
78
79        Ok(metadata)
80    }
81
82    pub fn indexation_available(&self, kind: IndexationKind) -> StorageResult<bool> {
83        let metadata = self
84            .storage::<MetadataTable<Description>>()
85            .get(&())?
86            .map(|metadata| metadata.into_owned());
87
88        let indexation_availability = indexation_availability::<Description>(metadata);
89        Ok(indexation_availability.contains(&kind))
90    }
91}