fuel-core 0.48.0

Fuel client library is aggregation of all fuels service. It contains the all business logic of the fuel protocol.
Documentation
use crate::{
    database::{
        GenesisDatabase,
        database_description::off_chain::OffChain,
    },
    fuel_core_graphql_api::storage::messages::SpentMessages,
    graphql_api::{
        storage::{
            blocks::FuelBlockIdsToHeights,
            coins::OwnedCoins,
            contracts::ContractsInfo,
            messages::OwnedMessageIds,
            old::{
                OldFuelBlockConsensus,
                OldFuelBlocks,
                OldTransactions,
            },
            transactions::{
                OwnedTransactions,
                TransactionStatuses,
            },
        },
        worker_service,
    },
};
use fuel_core_chain_config::TableEntry;
use fuel_core_storage::{
    StorageAsMut,
    tables::{
        Coins,
        FuelBlocks,
        Messages,
        SealedBlockConsensus,
        Transactions,
    },
    transactional::StorageTransaction,
};
use fuel_core_types::services::executor::Event;
use std::borrow::Cow;

use super::{
    Handler,
    import_task::ImportTable,
};

fn balances_indexation_enabled() -> bool {
    use std::sync::OnceLock;

    static BALANCES_INDEXATION_ENABLED: OnceLock<bool> = OnceLock::new();

    *BALANCES_INDEXATION_ENABLED.get_or_init(|| {
        // During re-genesis process the metadata never exist.
        let metadata = None;
        let indexation_availability =
            crate::database::database_description::indexation_availability::<OffChain>(
                metadata,
            );
        indexation_availability
            .contains(&crate::database::database_description::IndexationKind::Balances)
    })
}

fn coins_to_spend_indexation_enabled() -> bool {
    use std::sync::OnceLock;

    static COINS_TO_SPEND_INDEXATION_ENABLED: OnceLock<bool> = OnceLock::new();

    *COINS_TO_SPEND_INDEXATION_ENABLED.get_or_init(|| {
        // During re-genesis process the metadata never exist.
        let metadata = None;
        let indexation_availability =
            crate::database::database_description::indexation_availability::<OffChain>(
                metadata,
            );
        indexation_availability.contains(
            &crate::database::database_description::IndexationKind::CoinsToSpend,
        )
    })
}

impl ImportTable for Handler<TransactionStatuses, TransactionStatuses> {
    type TableInSnapshot = TransactionStatuses;
    type TableBeingWritten = TransactionStatuses;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for tx_status in group {
            tx.storage::<Self::TableInSnapshot>()
                .insert(&tx_status.key, &tx_status.value)?;
        }
        Ok(())
    }
}

impl ImportTable for Handler<FuelBlockIdsToHeights, FuelBlockIdsToHeights> {
    type TableInSnapshot = FuelBlockIdsToHeights;
    type TableBeingWritten = FuelBlockIdsToHeights;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for entry in group {
            tx.storage::<Self::TableInSnapshot>()
                .insert(&entry.key, &entry.value)?;
        }
        Ok(())
    }
}

impl ImportTable for Handler<OwnedTransactions, OwnedTransactions> {
    type TableInSnapshot = OwnedTransactions;
    type TableBeingWritten = OwnedTransactions;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for entry in group {
            tx.storage::<OwnedTransactions>()
                .insert(&entry.key, &entry.value)?;
        }
        Ok(())
    }
}

impl ImportTable for Handler<OwnedMessageIds, Messages> {
    type TableInSnapshot = Messages;
    type TableBeingWritten = OwnedMessageIds;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let events = group
            .into_iter()
            .map(|TableEntry { value, .. }| Cow::Owned(Event::MessageImported(value)));
        worker_service::process_executor_events(
            events,
            tx,
            balances_indexation_enabled(),
            coins_to_spend_indexation_enabled(),
            &self.base_asset_id,
        )?;
        Ok(())
    }
}

impl ImportTable for Handler<OwnedCoins, Coins> {
    type TableInSnapshot = Coins;
    type TableBeingWritten = OwnedCoins;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let events = group.into_iter().map(|TableEntry { value, key }| {
            Cow::Owned(Event::CoinCreated(value.uncompress(key)))
        });
        worker_service::process_executor_events(
            events,
            tx,
            balances_indexation_enabled(),
            coins_to_spend_indexation_enabled(),
            &self.base_asset_id,
        )?;
        Ok(())
    }
}

impl ImportTable for Handler<ContractsInfo, ContractsInfo> {
    type TableInSnapshot = ContractsInfo;
    type TableBeingWritten = ContractsInfo;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for entry in group {
            tx.storage::<ContractsInfo>()
                .insert(&entry.key, &entry.value)?;
        }
        Ok(())
    }
}

impl ImportTable for Handler<ContractsInfo, Transactions> {
    type TableInSnapshot = Transactions;
    type TableBeingWritten = ContractsInfo;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let transactions = group.iter().map(|TableEntry { value, .. }| value);
        worker_service::process_transactions(transactions, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<ContractsInfo, OldTransactions> {
    type TableInSnapshot = OldTransactions;
    type TableBeingWritten = ContractsInfo;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let transactions = group.iter().map(|TableEntry { value, .. }| value);
        worker_service::process_transactions(transactions, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<OldFuelBlocks, FuelBlocks> {
    type TableInSnapshot = FuelBlocks;
    type TableBeingWritten = OldFuelBlocks;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let blocks = group
            .iter()
            .map(|TableEntry { key, value, .. }| (key, value));
        worker_service::copy_to_old_blocks(blocks, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<OldFuelBlocks, OldFuelBlocks> {
    type TableInSnapshot = OldFuelBlocks;
    type TableBeingWritten = OldFuelBlocks;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let blocks = group
            .iter()
            .map(|TableEntry { key, value, .. }| (key, value));
        worker_service::copy_to_old_blocks(blocks, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<OldFuelBlockConsensus, SealedBlockConsensus> {
    type TableInSnapshot = SealedBlockConsensus;
    type TableBeingWritten = OldFuelBlockConsensus;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let blocks = group
            .iter()
            .map(|TableEntry { key, value, .. }| (key, value));
        worker_service::copy_to_old_block_consensus(blocks, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<OldFuelBlockConsensus, OldFuelBlockConsensus> {
    type TableInSnapshot = OldFuelBlockConsensus;
    type TableBeingWritten = OldFuelBlockConsensus;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let blocks = group
            .iter()
            .map(|TableEntry { key, value, .. }| (key, value));
        worker_service::copy_to_old_block_consensus(blocks, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<OldTransactions, Transactions> {
    type TableInSnapshot = Transactions;
    type TableBeingWritten = OldTransactions;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let transactions = group
            .iter()
            .map(|TableEntry { key, value, .. }| (key, value));
        worker_service::copy_to_old_transactions(transactions, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<OldTransactions, OldTransactions> {
    type TableInSnapshot = OldTransactions;
    type TableBeingWritten = OldTransactions;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        let transactions = group
            .iter()
            .map(|TableEntry { key, value, .. }| (key, value));
        worker_service::copy_to_old_transactions(transactions, tx)?;
        Ok(())
    }
}

impl ImportTable for Handler<SpentMessages, SpentMessages> {
    type TableInSnapshot = SpentMessages;
    type TableBeingWritten = SpentMessages;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for entry in group {
            tx.storage_as_mut::<SpentMessages>()
                .insert(&entry.key, &entry.value)?;
        }
        Ok(())
    }
}

impl ImportTable for Handler<FuelBlockIdsToHeights, FuelBlocks> {
    type TableInSnapshot = FuelBlocks;
    type TableBeingWritten = FuelBlockIdsToHeights;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for entry in group {
            tx.storage_as_mut::<FuelBlockIdsToHeights>()
                .insert(&entry.value.id(), &entry.key)?;
        }
        Ok(())
    }
}

impl ImportTable for Handler<FuelBlockIdsToHeights, OldFuelBlocks> {
    type TableInSnapshot = OldFuelBlocks;
    type TableBeingWritten = FuelBlockIdsToHeights;
    type DbDesc = OffChain;

    fn process(
        &mut self,
        group: Vec<TableEntry<Self::TableInSnapshot>>,
        tx: &mut StorageTransaction<&mut GenesisDatabase<Self::DbDesc>>,
    ) -> anyhow::Result<()> {
        for entry in group {
            tx.storage_as_mut::<FuelBlockIdsToHeights>()
                .insert(&entry.value.id(), &entry.key)?;
        }
        Ok(())
    }
}