fuel_core/database/
genesis_progress.rs

1use crate::graphql_api::storage::Column as OffChainColumn;
2
3use super::{
4    GenesisDatabase,
5    database_description::{
6        DatabaseDescription,
7        off_chain::OffChain,
8        on_chain::OnChain,
9    },
10};
11use fuel_core_chain_config::GenesisCommitment;
12use fuel_core_executor::refs::ContractRef;
13use fuel_core_storage::{
14    Error as StorageError,
15    Mappable,
16    MerkleRoot,
17    Result,
18    StorageAsMut,
19    StorageInspect,
20    StorageMutate,
21    blueprint::plain::Plain,
22    codec::postcard::Postcard,
23    column::Column,
24    iter::IteratorOverTable,
25    structured_storage::TableWithBlueprint,
26    tables::{
27        Coins,
28        ContractsLatestUtxo,
29        Messages,
30        ProcessedTransactions,
31    },
32};
33use fuel_core_types::fuel_merkle::binary::root_calculator::MerkleRootCalculator;
34
35pub struct GenesisMetadata<Description>(core::marker::PhantomData<Description>);
36
37impl<Description> Mappable for GenesisMetadata<Description> {
38    type Key = str;
39    type OwnedKey = String;
40    type Value = Self::OwnedValue;
41    type OwnedValue = usize;
42}
43
44impl TableWithBlueprint for GenesisMetadata<OnChain> {
45    type Blueprint = Plain<Postcard, Postcard>;
46    type Column = <OnChain as DatabaseDescription>::Column;
47    fn column() -> Self::Column {
48        Column::GenesisMetadata
49    }
50}
51
52impl TableWithBlueprint for GenesisMetadata<OffChain> {
53    type Blueprint = Plain<Postcard, Postcard>;
54    type Column = <OffChain as DatabaseDescription>::Column;
55    fn column() -> Self::Column {
56        OffChainColumn::GenesisMetadata
57    }
58}
59
60pub trait GenesisProgressInspect<Description> {
61    fn genesis_progress(&self, key: &str) -> Option<usize>;
62}
63
64pub trait GenesisProgressMutate<Description> {
65    fn update_genesis_progress(
66        &mut self,
67        key: &str,
68        processed_group: usize,
69    ) -> Result<()>;
70}
71
72impl<S, DbDesc> GenesisProgressInspect<DbDesc> for S
73where
74    S: StorageInspect<GenesisMetadata<DbDesc>, Error = StorageError>,
75    DbDesc: DatabaseDescription,
76{
77    fn genesis_progress(
78        &self,
79        key: &<GenesisMetadata<DbDesc> as Mappable>::Key,
80    ) -> Option<usize> {
81        Some(
82            StorageInspect::<GenesisMetadata<DbDesc>>::get(self, key)
83                .ok()??
84                .into_owned(),
85        )
86    }
87}
88
89impl<S, DbDesc> GenesisProgressMutate<DbDesc> for S
90where
91    S: StorageMutate<GenesisMetadata<DbDesc>, Error = StorageError>,
92{
93    fn update_genesis_progress(
94        &mut self,
95        key: &<GenesisMetadata<DbDesc> as Mappable>::Key,
96        processed_group: usize,
97    ) -> Result<()> {
98        self.storage_as_mut::<GenesisMetadata<DbDesc>>()
99            .insert(key, &processed_group)?;
100
101        Ok(())
102    }
103}
104
105impl GenesisDatabase {
106    pub fn genesis_coins_root(&self) -> Result<MerkleRoot> {
107        let coins = self.iter_all::<Coins>(None);
108
109        let mut root_calculator = MerkleRootCalculator::new();
110        for coin in coins {
111            let (utxo_id, coin) = coin?;
112            root_calculator.push(coin.uncompress(utxo_id).root()?.as_slice());
113        }
114
115        Ok(root_calculator.root())
116    }
117
118    pub fn genesis_messages_root(&self) -> Result<MerkleRoot> {
119        let messages = self.iter_all::<Messages>(None);
120
121        let mut root_calculator = MerkleRootCalculator::new();
122        for message in messages {
123            let (_, message) = message?;
124            root_calculator.push(message.root()?.as_slice());
125        }
126
127        Ok(root_calculator.root())
128    }
129
130    pub fn genesis_contracts_root(&self) -> Result<MerkleRoot> {
131        let contracts = self.iter_all::<ContractsLatestUtxo>(None);
132
133        let mut root_calculator = MerkleRootCalculator::new();
134        for contract in contracts {
135            let (contract_id, _) = contract?;
136            let root = ContractRef::new(self, contract_id).root()?;
137            root_calculator.push(root.as_slice());
138        }
139
140        Ok(root_calculator.root())
141    }
142
143    pub fn processed_transactions_root(&self) -> Result<MerkleRoot> {
144        let txs = self.iter_all::<ProcessedTransactions>(None);
145
146        let mut root_calculator = MerkleRootCalculator::new();
147        for tx in txs {
148            let (tx_id, _) = tx?;
149            root_calculator.push(tx_id.as_slice());
150        }
151
152        Ok(root_calculator.root())
153    }
154}