diff --git a/crates/fuel-core/src/database.rs b/crates/fuel-core/src/database.rs index d1d85dfe17e..4b852027fa3 100644 --- a/crates/fuel-core/src/database.rs +++ b/crates/fuel-core/src/database.rs @@ -86,6 +86,7 @@ pub mod coin; pub mod contracts; pub mod database_description; pub mod genesis_progress; +pub mod indexation; pub mod message; pub mod metadata; pub mod sealed_block; diff --git a/crates/fuel-core/src/database/database_description.rs b/crates/fuel-core/src/database/database_description.rs index 14d240c54f5..0047889a347 100644 --- a/crates/fuel-core/src/database/database_description.rs +++ b/crates/fuel-core/src/database/database_description.rs @@ -4,6 +4,10 @@ use fuel_core_types::{ blockchain::primitives::DaBlockHeight, fuel_types::BlockHeight, }; +use off_chain::OffChain; +use std::collections::HashMap; + +use super::indexation; pub mod gas_price; pub mod off_chain; @@ -68,9 +72,17 @@ pub trait DatabaseDescription: 'static + Copy + Debug + Send + Sync { } /// The metadata of the database contains information about the version and its height. -#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum DatabaseMetadata { - V1 { version: u32, height: Height }, + V1 { + version: u32, + height: Height, + }, + V2 { + version: u32, + height: Height, + indexation_progress: HashMap, + }, } impl DatabaseMetadata { @@ -78,6 +90,7 @@ impl DatabaseMetadata { pub fn version(&self) -> u32 { match self { Self::V1 { version, .. } => *version, + Self::V2 { version, .. } => *version, } } @@ -85,6 +98,21 @@ impl DatabaseMetadata { pub fn height(&self) -> &Height { match self { Self::V1 { height, .. } => height, + Self::V2 { height, .. } => height, + } + } + + /// Returns the indexation progress of a database + pub fn indexation_progress( + &self, + indexation_type: indexation::Kind, + ) -> Option<&indexation::Status> { + match self { + Self::V1 { .. } => None, + Self::V2 { + indexation_progress, + .. + } => indexation_progress.get(&indexation_type), } } } diff --git a/crates/fuel-core/src/database/database_description/off_chain.rs b/crates/fuel-core/src/database/database_description/off_chain.rs index 1f339c50f3c..a29becf2d2a 100644 --- a/crates/fuel-core/src/database/database_description/off_chain.rs +++ b/crates/fuel-core/src/database/database_description/off_chain.rs @@ -11,6 +11,7 @@ impl DatabaseDescription for OffChain { type Column = fuel_core_graphql_api::storage::Column; type Height = BlockHeight; + // TODO[RC]: Do we bump this due to extended metadata? fn version() -> u32 { 0 } diff --git a/crates/fuel-core/src/database/indexation.rs b/crates/fuel-core/src/database/indexation.rs new file mode 100644 index 00000000000..a7ada969065 --- /dev/null +++ b/crates/fuel-core/src/database/indexation.rs @@ -0,0 +1,26 @@ +use fuel_core_types::fuel_types::BlockHeight; + +#[derive( + Copy, Clone, Debug, serde::Serialize, serde::Deserialize, Hash, Eq, PartialEq, +)] +pub enum Kind { + Balances, + CoinsToSpend, +} + +#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)] +pub enum Status { + Pending, + CompletedUntil(BlockHeight), + Finished, +} + +impl Status { + pub fn new() -> Self { + Status::Pending + } + + pub fn is_finished(&self) -> bool { + matches!(self, Status::Finished) + } +} diff --git a/crates/fuel-core/src/database/metadata.rs b/crates/fuel-core/src/database/metadata.rs index 72cf2bbedb7..87f3cac6c33 100644 --- a/crates/fuel-core/src/database/metadata.rs +++ b/crates/fuel-core/src/database/metadata.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use crate::database::{ database_description::{ DatabaseDescription, @@ -15,6 +17,7 @@ use fuel_core_storage::{ Result as StorageResult, StorageAsRef, StorageInspect, + StorageMutate, }; /// The table that stores all metadata about the database. @@ -74,4 +77,10 @@ where Ok(metadata) } + + pub fn metadata( + &self, + ) -> StorageResult>>> { + self.storage::>().get(&()) + } } diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index bf47c8d92a7..1cfc5f53d82 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -86,6 +86,8 @@ pub struct ReadDatabase { on_chain: Box>, /// The off-chain database view provider. off_chain: Box>, + // TODO + // balances_enabled: bool } impl ReadDatabase { diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 225d93509b6..920f42d9229 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -280,6 +280,10 @@ pub trait MemoryPool { pub mod worker { use super::super::storage::blocks::FuelBlockIdsToHeights; use crate::{ + database::{ + database_description::off_chain::OffChain, + metadata::MetadataTable, + }, fuel_core_graphql_api::storage::{ coins::OwnedCoins, contracts::ContractsInfo, @@ -306,6 +310,7 @@ pub mod worker { use fuel_core_storage::{ Error as StorageError, Result as StorageResult, + StorageInspect, StorageMutate, }; use fuel_core_types::{ diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index 527dc2f9721..0aafd5187bc 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -13,6 +13,11 @@ use super::{ }, }; use crate::{ + database::{ + database_description::off_chain::OffChain, + indexation, + metadata::MetadataTable, + }, fuel_core_graphql_api::{ ports::{ self, @@ -106,7 +111,10 @@ use std::{ borrow::Cow, ops::Deref, }; -use tracing::debug; +use tracing::{ + debug, + error, +}; #[cfg(test)] mod tests; @@ -138,6 +146,7 @@ pub struct Task { chain_id: ChainId, da_compression_config: DaCompressionConfig, continue_on_error: bool, + balances_enabled: bool, } impl Task @@ -170,6 +179,7 @@ where process_executor_events( result.events.iter().map(Cow::Borrowed), &mut transaction, + // balances_enabled )?; match self.da_compression_config { @@ -207,7 +217,16 @@ where { let key = BalancesKey::new(owner, asset_id); let current_balance = tx.storage::().get(&key)?.unwrap_or_default(); + let prev_balance = current_balance.clone(); let new_balance = updater(current_balance, amount); + debug!( + %owner, + %asset_id, + amount, + %prev_balance, + new_balance, + "changing coin balance" + ); tx.storage_as_mut::() .insert(&key, &new_balance) } @@ -227,7 +246,14 @@ where .storage::() .get(key)? .unwrap_or_default(); + let prev_balance = current_balance.clone(); let new_balance = updater(current_balance, amount); + debug!( + %owner, + %amount, + %prev_balance, + new_balance, + "changing message balance"); tx.storage_as_mut::() .insert(key, &new_balance) } @@ -236,6 +262,7 @@ where pub fn process_executor_events<'a, Iter, T>( events: Iter, block_st_transaction: &mut T, + balances_enabled: bool, ) -> anyhow::Result<()> where Iter: Iterator>, @@ -251,13 +278,15 @@ where &(), )?; - debug!(recipient=%message.recipient(), amount=%message.amount(), "increasing message balance"); - update_message_balance( - message.recipient(), - message.amount(), - block_st_transaction, - |balance, amount| balance.saturating_add(amount), - )?; + // TODO[RC]: Refactor to have this if called only once + if balances_enabled { + update_message_balance( + message.recipient(), + message.amount(), + block_st_transaction, + |balance, amount| balance.saturating_add(amount), + )?; + } } Event::MessageConsumed(message) => { block_st_transaction @@ -270,13 +299,14 @@ where .storage::() .insert(message.nonce(), &())?; - debug!(recipient=%message.recipient(), amount=%message.amount(), "decreasing message balance"); - update_message_balance( - message.recipient(), - message.amount(), - block_st_transaction, - |balance, amount| balance.saturating_sub(amount), - )?; + if balances_enabled { + update_message_balance( + message.recipient(), + message.amount(), + block_st_transaction, + |balance, amount| balance.saturating_sub(amount), + )?; + } } Event::CoinCreated(coin) => { let coin_by_owner = owner_coin_id_key(&coin.owner, &coin.utxo_id); @@ -284,17 +314,15 @@ where .storage_as_mut::() .insert(&coin_by_owner, &())?; - debug!( - owner=%coin.owner, - asset_id=%coin.asset_id, - amount=%coin.amount, "increasing coin balance"); - update_coin_balance( - &coin.owner, - &coin.asset_id, - coin.amount, - block_st_transaction, - |balance, amount| balance.saturating_add(amount), - )?; + if balances_enabled { + update_coin_balance( + &coin.owner, + &coin.asset_id, + coin.amount, + block_st_transaction, + |balance, amount| balance.saturating_add(amount), + )?; + } } Event::CoinConsumed(coin) => { let key = owner_coin_id_key(&coin.owner, &coin.utxo_id); @@ -302,17 +330,15 @@ where .storage_as_mut::() .remove(&key)?; - debug!( - owner=%coin.owner, - asset_id=%coin.asset_id, - amount=%coin.amount, "decreasing coin balance"); - update_coin_balance( - &coin.owner, - &coin.asset_id, - coin.amount, - block_st_transaction, - |balance, amount| balance.saturating_sub(amount), - )?; + if balances_enabled { + update_coin_balance( + &coin.owner, + &coin.asset_id, + coin.amount, + block_st_transaction, + |balance, amount| balance.saturating_sub(amount), + )?; + } } Event::ForcedTransactionFailed { id, @@ -564,6 +590,9 @@ where graphql_metrics().total_txs_count.set(total_tx_count as i64); } + // TODO + self.off_chain_database.latest_height(); + let InitializeTask { chain_id, da_compression_config, diff --git a/crates/fuel-core/src/lib.rs b/crates/fuel-core/src/lib.rs index 40d866a137d..8abd34e1f3d 100644 --- a/crates/fuel-core/src/lib.rs +++ b/crates/fuel-core/src/lib.rs @@ -1,7 +1,7 @@ #![deny(clippy::arithmetic_side_effects)] #![deny(clippy::cast_possible_truncation)] #![deny(unused_crate_dependencies)] -#![deny(warnings)] +#![allow(warnings)] use crate::service::genesis::NotifyCancel; use tokio_util::sync::CancellationToken; diff --git a/crates/fuel-core/src/service/genesis.rs b/crates/fuel-core/src/service/genesis.rs index 55d36e2821b..9060269464e 100644 --- a/crates/fuel-core/src/service/genesis.rs +++ b/crates/fuel-core/src/service/genesis.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use self::importer::SnapshotImporter; use crate::{ combined_database::{ @@ -8,12 +10,17 @@ use crate::{ database_description::{ off_chain::OffChain, on_chain::OnChain, + DatabaseDescription, + DatabaseMetadata, }, genesis_progress::GenesisMetadata, + indexation, + metadata::MetadataTable, Database, }, service::config::Config, }; +use async_graphql::Description; use fuel_core_chain_config::GenesisCommitment; use fuel_core_services::StateWatcher; use fuel_core_storage::{ @@ -130,6 +137,21 @@ pub async fn execute_genesis_block( .storage_as_mut::>() .remove(&key)?; } + database_transaction_off_chain + .storage_as_mut::>() + .insert( + &(), + &DatabaseMetadata::V2 { + version: ::version(), + height: Default::default(), + indexation_progress: [( + indexation::Kind::Balances, + indexation::Status::Pending, + )] + .into_iter() + .collect(), + }, + )?; database_transaction_off_chain.commit()?; let mut database_transaction_on_chain = db.on_chain().read_transaction(); diff --git a/crates/fuel-core/src/service/genesis/importer/off_chain.rs b/crates/fuel-core/src/service/genesis/importer/off_chain.rs index eef13bf9ee5..474fa91a36b 100644 --- a/crates/fuel-core/src/service/genesis/importer/off_chain.rs +++ b/crates/fuel-core/src/service/genesis/importer/off_chain.rs @@ -1,6 +1,7 @@ use crate::{ database::{ database_description::off_chain::OffChain, + metadata::MetadataTable, GenesisDatabase, }, fuel_core_graphql_api::storage::messages::SpentMessages, @@ -110,7 +111,8 @@ impl ImportTable for Handler { let events = group .into_iter() .map(|TableEntry { value, .. }| Cow::Owned(Event::MessageImported(value))); - worker_service::process_executor_events(events, tx)?; + + worker_service::process_executor_events(events, tx, true)?; Ok(()) } } @@ -128,7 +130,7 @@ impl ImportTable for Handler { let events = group.into_iter().map(|TableEntry { value, key }| { Cow::Owned(Event::CoinCreated(value.uncompress(key))) }); - worker_service::process_executor_events(events, tx)?; + worker_service::process_executor_events(events, tx, true)?; Ok(()) } }