From 8f21da69f67148cd974194de05b4c61a8a7fbfe4 Mon Sep 17 00:00:00 2001 From: AurelienFT <32803821+AurelienFT@users.noreply.github.com> Date: Tue, 14 Jan 2025 23:40:38 +0100 Subject: [PATCH 01/13] Add current pool gas to the node info endpoint (#2550) / Add the information of the statistics of the pool on `node_info` endpoint. Useful for trying to predicting tx block inclusion in some cases - [x] Breaking changes are clearly marked as such in the PR description and changelog - [x] New behavior is reflected in tests - [x] [The specification](https://github.com/FuelLabs/fuel-specs/) matches the implemented behavior (link update PR if changes are needed) - [x] I have reviewed the code myself - [x] I have created follow-up issues caused by this PR and linked them here [Add or remove entries as needed] - [ ] [Rust SDK](https://github.com/FuelLabs/fuels-rs/) - [ ] [Sway compiler](https://github.com/FuelLabs/sway/) - [ ] [Platform documentation](https://github.com/FuelLabs/devrel-requests/issues/new?assignees=&labels=new+request&projects=&template=NEW-REQUEST.yml&title=%5BRequest%5D%3A+) (for out-of-organization contributors, the person merging the PR will do this) - [ ] Someone else? --------- Co-authored-by: Green Baneling --- crates/client/assets/schema.sdl | 20 +++++++ crates/client/src/client/schema/node_info.rs | 11 ++++ ...fo__tests__node_info_query_gql_output.snap | 8 +++ crates/client/src/client/types/node_info.rs | 11 +++- crates/fuel-core/src/graphql_api.rs | 2 + crates/fuel-core/src/graphql_api/ports.rs | 7 ++- crates/fuel-core/src/schema/node_info.rs | 50 ++++++++++++++++-- .../src/service/adapters/graphql_api.rs | 9 +++- crates/fuel-core/src/service/sub_services.rs | 2 + crates/services/txpool_v2/src/lib.rs | 1 + crates/services/txpool_v2/src/pool.rs | 38 +++++++++++++- crates/services/txpool_v2/src/service.rs | 9 +++- crates/services/txpool_v2/src/shared_state.rs | 6 +++ .../services/txpool_v2/src/tests/universe.rs | 52 ++++++++++++++++++- tests/tests/node_info.rs | 36 +++++++++++++ 15 files changed, 252 insertions(+), 10 deletions(-) diff --git a/crates/client/assets/schema.sdl b/crates/client/assets/schema.sdl index b9048362caa..28602d67594 100644 --- a/crates/client/assets/schema.sdl +++ b/crates/client/assets/schema.sdl @@ -751,8 +751,11 @@ type NodeInfo { utxoValidation: Boolean! vmBacktrace: Boolean! maxTx: U64! + maxGas: U64! + maxSize: U64! maxDepth: U64! nodeVersion: String! + txPoolStats: TxPoolStats! peers: [PeerInfo!]! } @@ -1259,6 +1262,23 @@ enum TxParametersVersion { scalar TxPointer +type TxPoolStats { + """ + The number of transactions in the pool + """ + txCount: U64! + """ + The total size of the transactions in the pool + """ + totalSize: U64! + """ + The total gas of the transactions in the pool + """ + totalGas: U64! +} + +scalar U128 + scalar U16 scalar U32 diff --git a/crates/client/src/client/schema/node_info.rs b/crates/client/src/client/schema/node_info.rs index 8eb6c9212ab..1a3e7b5d859 100644 --- a/crates/client/src/client/schema/node_info.rs +++ b/crates/client/src/client/schema/node_info.rs @@ -23,8 +23,11 @@ pub struct NodeInfo { pub utxo_validation: bool, pub vm_backtrace: bool, pub max_tx: U64, + pub max_gas: U64, + pub max_size: U64, pub max_depth: U64, pub node_version: String, + pub tx_pool_stats: TxPoolStats, } #[derive(cynic::QueryFragment, Clone, Debug)] @@ -77,6 +80,14 @@ impl From for fuel_core_types::services::p2p::PeerInfo { } } +#[derive(cynic::QueryFragment, Clone, Debug, PartialEq, Eq)] +#[cynic(schema_path = "./assets/schema.sdl")] +pub struct TxPoolStats { + pub tx_count: U64, + pub total_gas: U64, + pub total_size: U64, +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/client/src/client/schema/snapshots/fuel_core_client__client__schema__node_info__tests__node_info_query_gql_output.snap b/crates/client/src/client/schema/snapshots/fuel_core_client__client__schema__node_info__tests__node_info_query_gql_output.snap index 1d538f92ad0..cf5d0ea1920 100644 --- a/crates/client/src/client/schema/snapshots/fuel_core_client__client__schema__node_info__tests__node_info_query_gql_output.snap +++ b/crates/client/src/client/schema/snapshots/fuel_core_client__client__schema__node_info__tests__node_info_query_gql_output.snap @@ -1,14 +1,22 @@ --- source: crates/client/src/client/schema/node_info.rs expression: operation.query +snapshot_kind: text --- query { nodeInfo { utxoValidation vmBacktrace maxTx + maxGas + maxSize maxDepth nodeVersion + txPoolStats { + txCount + totalGas + totalSize + } } } diff --git a/crates/client/src/client/types/node_info.rs b/crates/client/src/client/types/node_info.rs index b4e8c306c9b..dce6a6a1174 100644 --- a/crates/client/src/client/types/node_info.rs +++ b/crates/client/src/client/types/node_info.rs @@ -1,12 +1,18 @@ -use crate::client::schema; +use crate::client::schema::{ + self, + node_info::TxPoolStats, +}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct NodeInfo { pub utxo_validation: bool, pub vm_backtrace: bool, pub max_tx: u64, + pub max_gas: u64, + pub max_size: u64, pub max_depth: u64, pub node_version: String, + pub tx_pool_stats: TxPoolStats, } // GraphQL Translation @@ -17,8 +23,11 @@ impl From for NodeInfo { utxo_validation: value.utxo_validation, vm_backtrace: value.vm_backtrace, max_tx: value.max_tx.into(), + max_gas: value.max_gas.into(), + max_size: value.max_size.into(), max_depth: value.max_depth.into(), node_version: value.node_version, + tx_pool_stats: value.tx_pool_stats, } } } diff --git a/crates/fuel-core/src/graphql_api.rs b/crates/fuel-core/src/graphql_api.rs index 772bbc815ea..d73eb8d0260 100644 --- a/crates/fuel-core/src/graphql_api.rs +++ b/crates/fuel-core/src/graphql_api.rs @@ -25,6 +25,8 @@ pub struct Config { pub debug: bool, pub vm_backtrace: bool, pub max_tx: usize, + pub max_gas: u64, + pub max_size: usize, pub max_txpool_dependency_chain_length: usize, pub chain_name: String, } diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 077a48d1637..b1226366900 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -19,7 +19,10 @@ use fuel_core_storage::{ StorageInspect, StorageRead, }; -use fuel_core_txpool::TxStatusMessage; +use fuel_core_txpool::{ + TxPoolStats, + TxStatusMessage, +}; use fuel_core_types::{ blockchain::{ block::CompressedBlock, @@ -206,6 +209,8 @@ pub trait TxPoolPort: Send + Sync { &self, tx_id: TxId, ) -> anyhow::Result>; + + fn latest_pool_stats(&self) -> TxPoolStats; } #[async_trait] diff --git a/crates/fuel-core/src/schema/node_info.rs b/crates/fuel-core/src/schema/node_info.rs index 5805c76dc60..d02070b361b 100644 --- a/crates/fuel-core/src/schema/node_info.rs +++ b/crates/fuel-core/src/schema/node_info.rs @@ -2,9 +2,12 @@ use super::scalars::{ U32, U64, }; -use crate::fuel_core_graphql_api::{ - query_costs, - Config as GraphQLConfig, +use crate::{ + fuel_core_graphql_api::{ + query_costs, + Config as GraphQLConfig, + }, + graphql_api::api_service::TxPool, }; use async_graphql::{ Context, @@ -16,6 +19,8 @@ pub struct NodeInfo { utxo_validation: bool, vm_backtrace: bool, max_tx: U64, + max_gas: U64, + max_size: U64, max_depth: U64, node_version: String, } @@ -34,6 +39,14 @@ impl NodeInfo { self.max_tx } + async fn max_gas(&self) -> U64 { + self.max_gas + } + + async fn max_size(&self) -> U64 { + self.max_size + } + async fn max_depth(&self) -> U64 { self.max_depth } @@ -42,6 +55,15 @@ impl NodeInfo { self.node_version.to_owned() } + #[graphql(complexity = "query_costs().storage_read + child_complexity")] + async fn tx_pool_stats( + &self, + ctx: &Context<'_>, + ) -> async_graphql::Result { + let tx_pool = ctx.data_unchecked::(); + Ok(TxPoolStats(tx_pool.latest_pool_stats())) + } + #[graphql(complexity = "query_costs().get_peers + child_complexity")] async fn peers(&self, _ctx: &Context<'_>) -> async_graphql::Result> { #[cfg(feature = "p2p")] @@ -76,6 +98,8 @@ impl NodeQuery { utxo_validation: config.utxo_validation, vm_backtrace: config.vm_backtrace, max_tx: (config.max_tx as u64).into(), + max_gas: config.max_gas.into(), + max_size: (config.max_size as u64).into(), max_depth: (config.max_txpool_dependency_chain_length as u64).into(), node_version: VERSION.to_owned(), }) @@ -124,3 +148,23 @@ impl PeerInfo { self.0.app_score } } + +struct TxPoolStats(fuel_core_txpool::TxPoolStats); + +#[Object] +impl TxPoolStats { + /// The number of transactions in the pool + async fn tx_count(&self) -> U64 { + self.0.tx_count.into() + } + + /// The total size of the transactions in the pool + async fn total_size(&self) -> U64 { + self.0.total_size.into() + } + + /// The total gas of the transactions in the pool + async fn total_gas(&self) -> U64 { + self.0.total_gas.into() + } +} diff --git a/crates/fuel-core/src/service/adapters/graphql_api.rs b/crates/fuel-core/src/service/adapters/graphql_api.rs index ff96e484ed9..daeea9c786a 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api.rs @@ -29,7 +29,10 @@ use crate::{ use async_trait::async_trait; use fuel_core_services::stream::BoxStream; use fuel_core_storage::Result as StorageResult; -use fuel_core_txpool::TxStatusMessage; +use fuel_core_txpool::{ + TxPoolStats, + TxStatusMessage, +}; use fuel_core_types::{ blockchain::header::ConsensusParametersVersion, entities::relayer::message::MerkleProof, @@ -96,6 +99,10 @@ impl TxPoolPort for TxPoolAdapter { ) -> anyhow::Result> { self.service.tx_update_subscribe(id) } + + fn latest_pool_stats(&self) -> TxPoolStats { + self.service.latest_stats() + } } impl DatabaseMessageProof for OnChainIterableKeyValueView { diff --git a/crates/fuel-core/src/service/sub_services.rs b/crates/fuel-core/src/service/sub_services.rs index d733204af61..86c25573133 100644 --- a/crates/fuel-core/src/service/sub_services.rs +++ b/crates/fuel-core/src/service/sub_services.rs @@ -303,6 +303,8 @@ pub fn init_sub_services( debug: config.debug, vm_backtrace: config.vm.backtrace, max_tx: config.txpool.pool_limits.max_txs, + max_gas: config.txpool.pool_limits.max_gas, + max_size: config.txpool.pool_limits.max_bytes_size, max_txpool_dependency_chain_length: config.txpool.max_txs_chain_count, chain_name, }; diff --git a/crates/services/txpool_v2/src/lib.rs b/crates/services/txpool_v2/src/lib.rs index d2530e00038..8b63eed4220 100644 --- a/crates/services/txpool_v2/src/lib.rs +++ b/crates/services/txpool_v2/src/lib.rs @@ -25,6 +25,7 @@ mod tests; fuel_core_trace::enable_tracing!(); use fuel_core_types::fuel_asm::Word; +pub use pool::TxPoolStats; pub use selection_algorithms::Constraints; pub use service::{ new_service, diff --git a/crates/services/txpool_v2/src/pool.rs b/crates/services/txpool_v2/src/pool.rs index e4a44afd7d1..5b0891032bc 100644 --- a/crates/services/txpool_v2/src/pool.rs +++ b/crates/services/txpool_v2/src/pool.rs @@ -42,6 +42,16 @@ use crate::{ }, }; +#[cfg(test)] +use std::collections::HashSet; + +#[derive(Debug, Clone, Copy, Default)] +pub struct TxPoolStats { + pub tx_count: u64, + pub total_size: u64, + pub total_gas: u64, +} + /// The pool is the main component of the txpool service. It is responsible for storing transactions /// and allowing the selection of transactions for inclusion in a block. pub struct Pool { @@ -59,6 +69,8 @@ pub struct Pool { pub(crate) current_gas: u64, /// Current pool size in bytes. pub(crate) current_bytes_size: usize, + /// The current pool gas. + pub(crate) pool_stats_sender: tokio::sync::watch::Sender, } impl Pool { @@ -68,6 +80,7 @@ impl Pool { collision_manager: CM, selection_algorithm: SA, config: Config, + pool_stats_sender: tokio::sync::watch::Sender, ) -> Self { Pool { storage, @@ -77,6 +90,7 @@ impl Pool { tx_id_to_storage_id: HashMap::new(), current_gas: 0, current_bytes_size: 0, + pool_stats_sender, } } @@ -157,10 +171,18 @@ where .into_iter() .map(|data| data.transaction) .collect::>(); - + self.update_stats(); Ok(removed_transactions) } + fn update_stats(&self) { + let _ = self.pool_stats_sender.send(TxPoolStats { + tx_count: self.tx_count() as u64, + total_size: self.current_bytes_size as u64, + total_gas: self.current_gas, + }); + } + /// Check if a transaction can be inserted into the pool. pub fn can_insert_transaction( &self, @@ -244,7 +266,11 @@ where storage_entry.transaction }) - .collect::>() + .collect::>(); + + self.update_stats(); + + txs } pub fn find_one(&self, tx_id: &TxId) -> Option<&StorageData> { @@ -292,6 +318,8 @@ where self.update_components_and_caches_on_removal(iter::once(&transaction)); } } + + self.update_stats(); } /// Check if the pool has enough space to store a transaction. @@ -443,6 +471,9 @@ where .extend(removed.into_iter().map(|data| data.transaction)); } } + + self.update_stats(); + removed_transactions } @@ -456,6 +487,9 @@ where self.update_components_and_caches_on_removal(removed.iter()); txs_removed.extend(removed.into_iter().map(|data| data.transaction)); } + + self.update_stats(); + txs_removed } diff --git a/crates/services/txpool_v2/src/service.rs b/crates/services/txpool_v2/src/service.rs index f2926495d66..5703d13cab7 100644 --- a/crates/services/txpool_v2/src/service.rs +++ b/crates/services/txpool_v2/src/service.rs @@ -1,4 +1,7 @@ -use crate as fuel_core_txpool; +use crate::{ + self as fuel_core_txpool, + pool::TxPoolStats, +}; use fuel_core_services::{ AsyncProcessor, @@ -696,6 +699,8 @@ where mpsc::channel(1); let (read_pool_requests_sender, read_pool_requests_receiver) = mpsc::channel(config.service_channel_limits.max_pending_read_pool_requests); + let (pool_stats_sender, pool_stats_receiver) = + tokio::sync::watch::channel(TxPoolStats::default()); let tx_status_sender = TxStatusChange::new( config.max_tx_update_subscriptions, // The connection should be closed automatically after the `SqueezedOut` event. @@ -712,6 +717,7 @@ where select_transactions_requests_sender, read_pool_requests_sender, new_txs_notifier, + latest_stats: pool_stats_receiver, }; let subscriptions = Subscriptions { @@ -759,6 +765,7 @@ where BasicCollisionManager::new(), RatioTipGasSelection::new(), config, + pool_stats_sender, ); Service::new(Task { diff --git a/crates/services/txpool_v2/src/shared_state.rs b/crates/services/txpool_v2/src/shared_state.rs index a7dbaaf0df1..b57325e39e0 100644 --- a/crates/services/txpool_v2/src/shared_state.rs +++ b/crates/services/txpool_v2/src/shared_state.rs @@ -20,6 +20,7 @@ use tokio::sync::{ use crate::{ error::Error, + pool::TxPoolStats, service::{ BorrowTxPoolRequest, ReadPoolRequest, @@ -54,6 +55,7 @@ pub struct SharedState { pub(crate) read_pool_requests_sender: mpsc::Sender, pub(crate) tx_status_sender: TxStatusChange, pub(crate) new_txs_notifier: tokio::sync::watch::Sender<()>, + pub(crate) latest_stats: tokio::sync::watch::Receiver, } impl SharedState { @@ -178,4 +180,8 @@ impl SharedState { .write_pool_requests_sender .try_send(WritePoolRequest::RemoveCoinDependents { transactions }); } + + pub fn latest_stats(&self) -> TxPoolStats { + *self.latest_stats.borrow() + } } diff --git a/crates/services/txpool_v2/src/tests/universe.rs b/crates/services/txpool_v2/src/tests/universe.rs index 0703aaebe48..236921bf6ed 100644 --- a/crates/services/txpool_v2/src/tests/universe.rs +++ b/crates/services/txpool_v2/src/tests/universe.rs @@ -58,7 +58,10 @@ use crate::{ config::Config, error::Error, new_service, - pool::Pool, + pool::{ + Pool, + TxPoolStats, + }, selection_algorithms::ratio_tip_gas::RatioTipGasSelection, service::{ memory::MemoryPool, @@ -96,6 +99,7 @@ pub struct TestPoolUniverse { rng: StdRng, pub config: Config, pool: Option>, + stats_receiver: Option>, } impl Default for TestPoolUniverse { @@ -105,6 +109,7 @@ impl Default for TestPoolUniverse { rng: StdRng::seed_from_u64(0), config: Default::default(), pool: None, + stats_receiver: None, } } } @@ -118,6 +123,14 @@ impl TestPoolUniverse { &self.mock_db } + pub fn latest_stats(&self) -> TxPoolStats { + if let Some(receiver) = &self.stats_receiver { + *receiver.borrow() + } else { + TxPoolStats::default() + } + } + pub fn config(self, config: Config) -> Self { if self.pool.is_some() { panic!("Pool already built"); @@ -126,6 +139,7 @@ impl TestPoolUniverse { } pub fn build_pool(&mut self) { + let (tx, rx) = tokio::sync::watch::channel(TxPoolStats::default()); let pool = Arc::new(RwLock::new(Pool::new( GraphStorage::new(GraphConfig { max_txs_chain_count: self.config.max_txs_chain_count, @@ -133,7 +147,9 @@ impl TestPoolUniverse { BasicCollisionManager::new(), RatioTipGasSelection::new(), self.config.clone(), + tx, ))); + self.stats_receiver = Some(rx); self.pool = Some(pool.clone()); } @@ -293,6 +309,40 @@ impl TestPoolUniverse { } } + pub fn assert_pool_integrity(&self, expected_txs: &[ArcPoolTx]) { + let stats = self.latest_stats(); + assert_eq!(stats.tx_count, expected_txs.len() as u64); + let mut total_gas: u64 = 0; + let mut total_size: u64 = 0; + for tx in expected_txs { + total_gas = total_gas.checked_add(tx.max_gas()).unwrap(); + total_size = total_gas + .checked_add(tx.metered_bytes_size() as u64) + .unwrap(); + } + assert_eq!(stats.total_gas, total_gas); + assert_eq!(stats.total_size, total_size); + let pool = self.pool.as_ref().unwrap(); + let pool = pool.read(); + let storage_ids_dependencies = pool.storage.assert_integrity(expected_txs); + let txs_without_dependencies = expected_txs + .iter() + .zip(storage_ids_dependencies) + .filter_map(|(tx, (_, has_dependencies))| { + if !has_dependencies { + Some(tx.clone()) + } else { + None + } + }) + .collect::>(); + pool.selection_algorithm + .assert_integrity(&txs_without_dependencies); + pool.collision_manager.assert_integrity(expected_txs); + let txs: HashSet = expected_txs.iter().map(|tx| tx.id()).collect(); + pool.assert_integrity(txs); + } + pub fn get_pool(&self) -> Shared { self.pool.clone().unwrap() } diff --git a/tests/tests/node_info.rs b/tests/tests/node_info.rs index 0e3e2339a3d..fc67759d1e5 100644 --- a/tests/tests/node_info.rs +++ b/tests/tests/node_info.rs @@ -1,3 +1,5 @@ +#![allow(non_snake_case)] + use fuel_core::service::{ Config, FuelService, @@ -6,6 +8,8 @@ use fuel_core_client::client::{ types::NodeInfo, FuelClient, }; +use fuel_core_poa::Trigger; +use fuel_core_types::fuel_tx::Transaction; #[tokio::test] async fn node_info() { @@ -27,6 +31,38 @@ async fn node_info() { assert_eq!(max_tx, node_config.txpool.pool_limits.max_txs as u64); } +#[tokio::test] +async fn tx_pool_stats__should_be_updated_when_transaction_is_submitted() { + // Given + let mut node_config = Config::local_node(); + node_config.block_production = Trigger::Never; + + let srv = FuelService::new_node(node_config.clone()).await.unwrap(); + let client = FuelClient::from(srv.bound_address); + + // When + let NodeInfo { + tx_pool_stats: initial_tx_pool_stats, + .. + } = client.node_info().await.unwrap(); + + let tx = Transaction::default_test_tx(); + client.submit(&tx).await.unwrap(); + + let NodeInfo { + tx_pool_stats: updated_tx_pool_stats, + .. + } = client.node_info().await.unwrap(); + + // Then + assert_eq!(initial_tx_pool_stats.tx_count.0, 0); + assert_eq!(initial_tx_pool_stats.total_gas.0, 0); + assert_eq!(initial_tx_pool_stats.total_size.0, 0); + assert_eq!(updated_tx_pool_stats.tx_count.0, 1); + assert_eq!(updated_tx_pool_stats.total_gas.0, 4330); + assert_eq!(updated_tx_pool_stats.total_size.0, 344); +} + #[cfg(feature = "p2p")] #[tokio::test(flavor = "multi_thread")] async fn test_peer_info() { From b75218be020050fcc7a2894aacb96fc9c5918364 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 14:13:35 +0100 Subject: [PATCH 02/13] Fix compilation --- crates/services/txpool_v2/src/pool.rs | 9 ++-- .../services/txpool_v2/src/tests/universe.rs | 42 ------------------- 2 files changed, 3 insertions(+), 48 deletions(-) diff --git a/crates/services/txpool_v2/src/pool.rs b/crates/services/txpool_v2/src/pool.rs index 5b0891032bc..dafe680e09d 100644 --- a/crates/services/txpool_v2/src/pool.rs +++ b/crates/services/txpool_v2/src/pool.rs @@ -42,9 +42,6 @@ use crate::{ }, }; -#[cfg(test)] -use std::collections::HashSet; - #[derive(Debug, Clone, Copy, Default)] pub struct TxPoolStats { pub tx_count: u64, @@ -177,7 +174,7 @@ where fn update_stats(&self) { let _ = self.pool_stats_sender.send(TxPoolStats { - tx_count: self.tx_count() as u64, + tx_count: self.tx_id_to_storage_id.len() as u64, total_size: self.current_bytes_size as u64, total_gas: self.current_gas, }); @@ -258,7 +255,8 @@ where &mut self, constraints: Constraints, ) -> Vec { - self.selection_algorithm + let txs = self + .selection_algorithm .gather_best_txs(constraints, &mut self.storage) .into_iter() .map(|storage_entry| { @@ -269,7 +267,6 @@ where .collect::>(); self.update_stats(); - txs } diff --git a/crates/services/txpool_v2/src/tests/universe.rs b/crates/services/txpool_v2/src/tests/universe.rs index 236921bf6ed..9290dffeb54 100644 --- a/crates/services/txpool_v2/src/tests/universe.rs +++ b/crates/services/txpool_v2/src/tests/universe.rs @@ -123,14 +123,6 @@ impl TestPoolUniverse { &self.mock_db } - pub fn latest_stats(&self) -> TxPoolStats { - if let Some(receiver) = &self.stats_receiver { - *receiver.borrow() - } else { - TxPoolStats::default() - } - } - pub fn config(self, config: Config) -> Self { if self.pool.is_some() { panic!("Pool already built"); @@ -309,40 +301,6 @@ impl TestPoolUniverse { } } - pub fn assert_pool_integrity(&self, expected_txs: &[ArcPoolTx]) { - let stats = self.latest_stats(); - assert_eq!(stats.tx_count, expected_txs.len() as u64); - let mut total_gas: u64 = 0; - let mut total_size: u64 = 0; - for tx in expected_txs { - total_gas = total_gas.checked_add(tx.max_gas()).unwrap(); - total_size = total_gas - .checked_add(tx.metered_bytes_size() as u64) - .unwrap(); - } - assert_eq!(stats.total_gas, total_gas); - assert_eq!(stats.total_size, total_size); - let pool = self.pool.as_ref().unwrap(); - let pool = pool.read(); - let storage_ids_dependencies = pool.storage.assert_integrity(expected_txs); - let txs_without_dependencies = expected_txs - .iter() - .zip(storage_ids_dependencies) - .filter_map(|(tx, (_, has_dependencies))| { - if !has_dependencies { - Some(tx.clone()) - } else { - None - } - }) - .collect::>(); - pool.selection_algorithm - .assert_integrity(&txs_without_dependencies); - pool.collision_manager.assert_integrity(expected_txs); - let txs: HashSet = expected_txs.iter().map(|tx| tx.id()).collect(); - pool.assert_integrity(txs); - } - pub fn get_pool(&self) -> Shared { self.pool.clone().unwrap() } From bb43ec15d7561a54c1d3e7abb932bfc8cbbbc905 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 14:19:49 +0100 Subject: [PATCH 03/13] fix schema --- crates/client/assets/schema.sdl | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/client/assets/schema.sdl b/crates/client/assets/schema.sdl index 28602d67594..7ab3d16f810 100644 --- a/crates/client/assets/schema.sdl +++ b/crates/client/assets/schema.sdl @@ -1277,8 +1277,6 @@ type TxPoolStats { totalGas: U64! } -scalar U128 - scalar U16 scalar U32 From 2121036e90e9893bbc6c43b1e2e45d4d6655eaa5 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 14:29:43 +0100 Subject: [PATCH 04/13] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c96e6e35e..33c48ed134c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- [2573](https://github.com/FuelLabs/fuel-core/pull/2573): Add txpool stats to the `node_info` GraphQL endpoint + ## [Version 0.40.2] ### Fixed From beb1f9d9584000f96b98cba8d5a6e15bcbbb5a97 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 16:25:23 +0100 Subject: [PATCH 05/13] try to fix cargo audit --- .github/workflows/ci.yml | 2 +- .github/workflows/nightly-cargo-audit.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 943f36c810d..c4e2453f4df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -892,6 +892,6 @@ jobs: continue-on-error: true steps: - uses: actions/checkout@v4 - - uses: actions-rs/audit-check@v1 + - uses: rustsec/audit-check@v1.4.1 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly-cargo-audit.yml b/.github/workflows/nightly-cargo-audit.yml index 91d3f662f69..4c7e1d6c34b 100644 --- a/.github/workflows/nightly-cargo-audit.yml +++ b/.github/workflows/nightly-cargo-audit.yml @@ -9,6 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/audit-check@v1 + - uses: rustsec/audit-check@v1.4.1 with: token: ${{ secrets.GITHUB_TOKEN }} From e64a593d4741d1d94607ea20e0ee2b36eb2eb28f Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 16:28:56 +0100 Subject: [PATCH 06/13] try again audit --- .github/workflows/ci.yml | 2 +- .github/workflows/nightly-cargo-audit.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4e2453f4df..2df590436a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -892,6 +892,6 @@ jobs: continue-on-error: true steps: - uses: actions/checkout@v4 - - uses: rustsec/audit-check@v1.4.1 + - uses: rustsec/audit-check@v2.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly-cargo-audit.yml b/.github/workflows/nightly-cargo-audit.yml index 4c7e1d6c34b..52a14b2531b 100644 --- a/.github/workflows/nightly-cargo-audit.yml +++ b/.github/workflows/nightly-cargo-audit.yml @@ -9,6 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: rustsec/audit-check@v1.4.1 + - uses: rustsec/audit-check@v2.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} From 606960f18ee0d0c96b870e71313b9a19647f4951 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 16:33:21 +0100 Subject: [PATCH 07/13] try fix the audit again --- .github/workflows/ci.yml | 1 + .github/workflows/nightly-cargo-audit.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2df590436a5..ae660415e7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -892,6 +892,7 @@ jobs: continue-on-error: true steps: - uses: actions/checkout@v4 + - run: cargo install cargo-audit --locked - uses: rustsec/audit-check@v2.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly-cargo-audit.yml b/.github/workflows/nightly-cargo-audit.yml index 52a14b2531b..1809b35d603 100644 --- a/.github/workflows/nightly-cargo-audit.yml +++ b/.github/workflows/nightly-cargo-audit.yml @@ -9,6 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - run: cargo install cargo-audit --locked - uses: rustsec/audit-check@v2.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} From bfb3fd0391a6002ef7eae369290a566649a45af5 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 16:34:00 +0100 Subject: [PATCH 08/13] fix spelling --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33c48ed134c..6d43477a9fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -429,7 +429,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). The change has many minor improvements in different areas related to the state transition bytecode: - The state transition bytecode lies in its own file(`state_transition_bytecode.wasm`) along with the chain config file. The `ChainConfig` loads it automatically when `ChainConfig::load` is called and pushes it back when `ChainConfig::write` is called. - The `fuel-core` release bundle also contains the `fuel-core-wasm-executor.wasm` file of the corresponding executor version. - - The regenesis process now considers the last block produced by the previous network. When we create a (re)genesis block of a new network, it has the `height = last_block_of_old_netowkr + 1`. It continues the old network and doesn't overlap blocks(before, we had `old_block.height == new_genesis_block.hegiht`). + - The regenesis process now considers the last block produced by the previous network. When we create a (re)genesis block of a new network, it has the `height = last_block_of_old_netowkr + 1`. It continues the old network and doesn't overlap blocks(before, we had `old_block.height == new_genesis_block.height`). - Along with the new block height, the regenesis process also increases the state transition bytecode and consensus parameters versions. It guarantees that a new network doesn't use values from the previous network and allows us not to migrate `StateTransitionBytecodeVersions` and `ConsensusParametersVersions` tables. - Added a new CLI argument, `native-executor-version,` that allows overriding of the default version of the native executor. It can be useful for side rollups that have their own history of executor upgrades. - Replaced: From b15b25488d4c62f3a5bed60f5880753f8db5fdec Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 17:07:12 +0100 Subject: [PATCH 09/13] fix audit and try to fix backwaard compativility tests --- .cargo/audit.toml | 1 + .github/workflows/ci.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.cargo/audit.toml b/.cargo/audit.toml index db18bdc5a3c..a0081aca094 100644 --- a/.cargo/audit.toml +++ b/.cargo/audit.toml @@ -1,4 +1,5 @@ [advisories] ignore = [ "RUSTSEC-2024-0336" # https://github.com/FuelLabs/fuel-core/issues/1843 + "RUSTSEC-2024-0421" # https://github.com/FuelLabs/fuel-core/issues/2488 ] \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae660415e7a..5d9694a1fc2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: # for `fuel-core 0.26.0`(because of the bug with `--offline` # and `--locked` when we build `fuel-core-wasm-executor 0.26.0`). - command: check - args: --manifest-path version-compatibility/Cargo.toml --workspace && cargo test --manifest-path version-compatibility/Cargo.toml --workspace + args: --manifest-path version-compatibility/Cargo.toml --workspace --locked && cargo test --manifest-path version-compatibility/Cargo.toml --workspace --locked - command: build args: -p fuel-core-bin --no-default-features --features production From 1f9e5fd7f37be62069fa866eb342d44e34f443c4 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 17:20:01 +0100 Subject: [PATCH 10/13] try to pin async graphql versions --- .cargo/audit.toml | 2 +- version-compatibility/forkless-upgrade/Cargo.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.cargo/audit.toml b/.cargo/audit.toml index a0081aca094..83408501ca2 100644 --- a/.cargo/audit.toml +++ b/.cargo/audit.toml @@ -1,5 +1,5 @@ [advisories] ignore = [ - "RUSTSEC-2024-0336" # https://github.com/FuelLabs/fuel-core/issues/1843 + "RUSTSEC-2024-0336", # https://github.com/FuelLabs/fuel-core/issues/1843 "RUSTSEC-2024-0421" # https://github.com/FuelLabs/fuel-core/issues/2488 ] \ No newline at end of file diff --git a/version-compatibility/forkless-upgrade/Cargo.toml b/version-compatibility/forkless-upgrade/Cargo.toml index 0792f3c6fc7..204097000b5 100644 --- a/version-compatibility/forkless-upgrade/Cargo.toml +++ b/version-compatibility/forkless-upgrade/Cargo.toml @@ -14,6 +14,8 @@ hex = "0.4.3" rand = "0.8" tempfile = "3.4" tokio = { version = "1.37.0", features = ["rt-multi-thread"] } +async-graphql = "=7.0.11" +async-graphql-value = "=7.0.11" # Neutral deps fuel-core-trace = { path = "../../crates/trace" } From e4f300a5570783dba8c4c8f57b79f3cd8db19863 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 17:24:48 +0100 Subject: [PATCH 11/13] remove unwanted locked --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d9694a1fc2..ae660415e7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: # for `fuel-core 0.26.0`(because of the bug with `--offline` # and `--locked` when we build `fuel-core-wasm-executor 0.26.0`). - command: check - args: --manifest-path version-compatibility/Cargo.toml --workspace --locked && cargo test --manifest-path version-compatibility/Cargo.toml --workspace --locked + args: --manifest-path version-compatibility/Cargo.toml --workspace && cargo test --manifest-path version-compatibility/Cargo.toml --workspace - command: build args: -p fuel-core-bin --no-default-features --features production From ffc3b28cb612f2d86a7224fe4411353fd385f731 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 17:35:33 +0100 Subject: [PATCH 12/13] fix unused crates --- version-compatibility/forkless-upgrade/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/version-compatibility/forkless-upgrade/src/lib.rs b/version-compatibility/forkless-upgrade/src/lib.rs index ae7415e13d0..518b82799a1 100644 --- a/version-compatibility/forkless-upgrade/src/lib.rs +++ b/version-compatibility/forkless-upgrade/src/lib.rs @@ -1,6 +1,9 @@ #![deny(unused_crate_dependencies)] #![deny(warnings)] +use async_graphql as _; +use async_graphql_value as _; + #[cfg(test)] mod backward_compatibility; #[cfg(test)] From e91e6c677380349d6c37347251dfb632e85f9d86 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 15 Jan 2025 21:49:11 +0100 Subject: [PATCH 13/13] fix unused dependencies for compilation --- version-compatibility/forkless-upgrade/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/version-compatibility/forkless-upgrade/src/lib.rs b/version-compatibility/forkless-upgrade/src/lib.rs index 518b82799a1..377b35cf05f 100644 --- a/version-compatibility/forkless-upgrade/src/lib.rs +++ b/version-compatibility/forkless-upgrade/src/lib.rs @@ -1,7 +1,9 @@ #![deny(unused_crate_dependencies)] #![deny(warnings)] +#[cfg(test)] use async_graphql as _; +#[cfg(test)] use async_graphql_value as _; #[cfg(test)]