diff --git a/CHANGELOG.md b/CHANGELOG.md index 93faadb8b92..a70b680b46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Description of the upcoming release here. ### Fixed +- [#1802](https://github.com/FuelLabs/fuel-core/pull/1802): Fixed a runtime panic that occurred when restarting a node. The panic was caused by an invalid database commit while loading an existing off-chain database. The invalid commit is removed in this PR. - [#1803](https://github.com/FuelLabs/fuel-core/pull/1803): Produce block when da height haven't changed. - [#1795](https://github.com/FuelLabs/fuel-core/pull/1795): Fixed the building of the `fuel-core-wasm-executor` to work outside of the `fuel-core` context. The change uses the path to the manifest file of the `fuel-core-upgradable-executor` to build the `fuel-core-wasm-executor` instead of relying on the workspace. diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 53662e3d2c3..453e2835ae4 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -263,6 +263,9 @@ pub mod worker { /// Returns the total count after the update. fn increase_tx_count(&mut self, new_txs_count: u64) -> StorageResult; + /// Gets the total number of transactions on the chain from metadata. + fn get_tx_count(&self) -> StorageResult; + /// Commits the underlying changes into the database. fn commit(self) -> StorageResult<()>; } diff --git a/crates/fuel-core/src/graphql_api/storage.rs b/crates/fuel-core/src/graphql_api/storage.rs index 401fbfb4a72..887f0b385de 100644 --- a/crates/fuel-core/src/graphql_api/storage.rs +++ b/crates/fuel-core/src/graphql_api/storage.rs @@ -23,6 +23,7 @@ use fuel_core_storage::{ Error as StorageError, Result as StorageResult, StorageAsMut, + StorageAsRef, StorageMutate, }; use fuel_core_types::{ @@ -42,6 +43,10 @@ pub mod messages; pub mod statistic; pub mod transactions; +/// Tracks the total number of transactions written to the chain +/// It's useful for analyzing TPS or other metrics. +const TX_COUNT: &str = "total_tx_count"; + /// GraphQL database tables column ids to the corresponding [`fuel_core_storage::Mappable`] table. #[repr(u32)] #[derive( @@ -125,22 +130,23 @@ where } fn increase_tx_count(&mut self, new_txs_count: u64) -> StorageResult { - /// Tracks the total number of transactions written to the chain - /// It's useful for analyzing TPS or other metrics. - const TX_COUNT: &str = "total_tx_count"; - // TODO: how should tx count be initialized after regenesis? - let current_tx_count: u64 = self - .storage::>() - .get(TX_COUNT)? - .unwrap_or_default() - .into_owned(); + let current_tx_count: u64 = self.get_tx_count()?; // Using saturating_add because this value doesn't significantly impact the correctness of execution. let new_tx_count = current_tx_count.saturating_add(new_txs_count); <_ as StorageMutate>>::insert(self, TX_COUNT, &new_tx_count)?; Ok(new_tx_count) } + fn get_tx_count(&self) -> StorageResult { + let tx_count = self + .storage::>() + .get(TX_COUNT)? + .unwrap_or_default() + .into_owned(); + Ok(tx_count) + } + fn commit(self) -> StorageResult<()> { self.commit()?; Ok(()) diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index 4fdc750197d..320aa2c0530 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -323,10 +323,11 @@ where _: &StateWatcher, _: Self::TaskParams, ) -> anyhow::Result { - let mut db_tx = self.database.transaction(); - let total_tx_count = db_tx.increase_tx_count(0).unwrap_or_default(); - db_tx.commit()?; - graphql_metrics().total_txs_count.set(total_tx_count as i64); + { + let db_tx = self.database.transaction(); + let total_tx_count = db_tx.get_tx_count().unwrap_or_default(); + graphql_metrics().total_txs_count.set(total_tx_count as i64); + } // TODO: It is possible that the node was shut down before we processed all imported blocks. // It could lead to some missed blocks and the database's inconsistent state. diff --git a/tests/tests/health.rs b/tests/tests/health.rs index ce795f9680d..e6af747fd73 100644 --- a/tests/tests/health.rs +++ b/tests/tests/health.rs @@ -1,9 +1,12 @@ use fuel_core::{ + combined_database::CombinedDatabase, database::Database, service::{ Config, FuelService, + ServiceTrait, }, + types::fuel_tx::Transaction, }; use fuel_core_client::client::FuelClient; @@ -26,7 +29,6 @@ async fn can_restart_node() { // start node once { - use fuel_core::service::ServiceTrait; let database = Database::open_rocksdb(tmp_dir.path(), None).unwrap(); let first_startup = FuelService::from_database(database, Config::local_node()) .await @@ -41,3 +43,39 @@ async fn can_restart_node() { .unwrap(); } } + +#[tokio::test] +async fn can_restart_node_with_transactions() { + let capacity = 1024 * 1024; + let tmp_dir = tempfile::TempDir::new().unwrap(); + + { + // Given + let database = CombinedDatabase::open(tmp_dir.path(), capacity).unwrap(); + let service = FuelService::from_combined_database(database, Config::local_node()) + .await + .unwrap(); + let client = FuelClient::from(service.bound_address); + client.health().await.unwrap(); + + for _ in 0..5 { + let tx = Transaction::default_test_tx(); + client.submit_and_await_commit(&tx).await.unwrap(); + } + + service.stop_and_await().await.unwrap(); + } + + { + // When + let database = CombinedDatabase::open(tmp_dir.path(), capacity).unwrap(); + let service = FuelService::from_combined_database(database, Config::local_node()) + .await + .unwrap(); + let client = FuelClient::from(service.bound_address); + + // Then + client.health().await.unwrap(); + service.stop_and_await().await.unwrap(); + } +}