Skip to content

Commit

Permalink
Expose indexation status in NodeInfo endpoint (#2595)
Browse files Browse the repository at this point in the history
Closes #2576

## Description
This PR extends the `nodeInfo` GraphQL endpoint by adding the
`indexation` field which allows to check whether a given indexation is
enabled. Example response:

```json
{
  "data": {
    "nodeInfo": {
      "utxoValidation": false,
      "indexation": {
        "balances": true,
        "coinsToSpend": false,
        "assetMetadata": false
      }
    }
  }
}
```

### Before requesting review
- [X] I have reviewed the code myself

### After merging, notify other teams
- [X] [Rust SDK](https://github.com/FuelLabs/fuels-rs/)

---------

Co-authored-by: AurelienFT <[email protected]>
Co-authored-by: Mitchell Turner <[email protected]>
Co-authored-by: AurelienFT <[email protected]>
Co-authored-by: AurelienFT <[email protected]>
  • Loading branch information
5 people authored Jan 22, 2025
1 parent eafb4a6 commit 1ef9d9c
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added
- [2551](https://github.com/FuelLabs/fuel-core/pull/2551): Enhanced the DA compressed block header to include block id.
- [2595](https://github.com/FuelLabs/fuel-core/pull/2595): Added `indexation` field to the `nodeInfo` GraphQL endpoint to allow checking if a specific indexation is enabled.

### Changed
- [2603](https://github.com/FuelLabs/fuel-core/pull/2603): Sets the latest recorded height on initialization, not just when DA costs are received
Expand Down
16 changes: 16 additions & 0 deletions crates/client/assets/schema.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,21 @@ type HeavyOperation {
scalar HexString


type IndexationFlags {
"""
Is balances indexation enabled
"""
balances: Boolean!
"""
Is coins to spend indexation enabled
"""
coinsToSpend: Boolean!
"""
Is asset metadata indexation enabled
"""
assetMetadata: Boolean!
}

union Input = InputCoin | InputContract | InputMessage

type InputCoin {
Expand Down Expand Up @@ -764,6 +779,7 @@ type NodeInfo {
maxSize: U64!
maxDepth: U64!
nodeVersion: String!
indexation: IndexationFlags!
txPoolStats: TxPoolStats!
peers: [PeerInfo!]!
}
Expand Down
9 changes: 9 additions & 0 deletions crates/client/src/client/schema/node_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct NodeInfo {
pub max_size: U64,
pub max_depth: U64,
pub node_version: String,
pub indexation: IndexationFlags,
pub tx_pool_stats: TxPoolStats,
}

Expand Down Expand Up @@ -88,6 +89,14 @@ pub struct TxPoolStats {
pub total_size: U64,
}

#[derive(cynic::QueryFragment, Clone, Debug, PartialEq, Eq)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct IndexationFlags {
pub balances: bool,
pub coins_to_spend: bool,
pub asset_metadata: bool,
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ query QueryNodeInfo {
maxSize
maxDepth
nodeVersion
indexation {
balances
coinsToSpend
assetMetadata
}
txPoolStats {
txCount
totalGas
Expand Down
7 changes: 6 additions & 1 deletion crates/client/src/client/types/node_info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::client::schema::{
self,
node_info::TxPoolStats,
node_info::{
IndexationFlags,
TxPoolStats,
},
};

#[derive(Clone, Debug, PartialEq, Eq)]
Expand All @@ -12,6 +15,7 @@ pub struct NodeInfo {
pub max_size: u64,
pub max_depth: u64,
pub node_version: String,
pub indexation: IndexationFlags,
pub tx_pool_stats: TxPoolStats,
}

Expand All @@ -27,6 +31,7 @@ impl From<schema::node_info::NodeInfo> for NodeInfo {
max_size: value.max_size.into(),
max_depth: value.max_depth.into(),
node_version: value.node_version,
indexation: value.indexation,
tx_pool_stats: value.tx_pool_stats,
}
}
Expand Down
106 changes: 80 additions & 26 deletions crates/fuel-core/src/graphql_api/database.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::fuel_core_graphql_api::{
database::arc_wrapper::ArcWrapper,
ports::{
OffChainDatabase,
OnChainDatabase,
use crate::{
database::database_description::IndexationKind,
fuel_core_graphql_api::{
database::arc_wrapper::ArcWrapper,
ports::{
OffChainDatabase,
OnChainDatabase,
},
},
};
use fuel_core_services::yield_stream::StreamYieldExt;
Expand Down Expand Up @@ -67,6 +70,7 @@ use std::{
borrow::Cow,
sync::Arc,
};
use strum::IntoEnumIterator;

use super::ports::worker;

Expand All @@ -88,12 +92,31 @@ pub struct ReadDatabase {
on_chain: Box<dyn AtomicView<LatestView = OnChainView>>,
/// The off-chain database view provider.
off_chain: Box<dyn AtomicView<LatestView = OffChainView>>,
/// The flag that indicates whether the Balances indexation is enabled.
balances_indexation_enabled: bool,
/// The flag that indicates whether the CoinsToSpend indexation is enabled.
coins_to_spend_indexation_enabled: bool,
/// The flag that indicates whether the AssetMetadata indexation is enabled.
asset_metadata_indexation_enabled: bool,
/// The flag indicating which indexation is enabled.
indexation_flags: IndexationFlags,
}

#[derive(Clone)]
pub struct IndexationFlags(u8);

impl IndexationFlags {
pub fn new() -> Self {
Self(0)
}

pub fn contains(&self, kind: &IndexationKind) -> bool {
self.0 & (1 << *kind as u8) != 0
}

pub fn insert(&mut self, kind: IndexationKind) {
self.0 |= 1 << kind as u8;
}
}

impl Default for IndexationFlags {
fn default() -> Self {
Self::new()
}
}

impl ReadDatabase {
Expand All @@ -110,20 +133,32 @@ impl ReadDatabase {
OnChain::LatestView: OnChainDatabase,
OffChain::LatestView: OffChainDatabase,
{
let balances_indexation_enabled = off_chain.balances_indexation_enabled()?;
let coins_to_spend_indexation_enabled =
off_chain.coins_to_spend_indexation_enabled()?;
let asset_metadata_indexation_enabled =
off_chain.asset_metadata_indexation_enabled()?;

let mut indexation_flags = IndexationFlags::new();
for kind in IndexationKind::iter() {
match kind {
IndexationKind::Balances => {
if off_chain.balances_indexation_enabled()? {
indexation_flags.insert(kind);
}
}
IndexationKind::CoinsToSpend => {
if off_chain.coins_to_spend_indexation_enabled()? {
indexation_flags.insert(kind);
}
}
IndexationKind::AssetMetadata => {
if off_chain.asset_metadata_indexation_enabled()? {
indexation_flags.insert(kind);
}
}
}
}
Ok(Self {
batch_size,
genesis_height,
on_chain: Box::new(ArcWrapper::new(on_chain)),
off_chain: Box::new(ArcWrapper::new(off_chain)),
balances_indexation_enabled,
coins_to_spend_indexation_enabled,
asset_metadata_indexation_enabled,
indexation_flags,
})
}

Expand All @@ -137,9 +172,7 @@ impl ReadDatabase {
genesis_height: self.genesis_height,
on_chain: self.on_chain.latest_view()?,
off_chain: self.off_chain.latest_view()?,
balances_indexation_enabled: self.balances_indexation_enabled,
coins_to_spend_indexation_enabled: self.coins_to_spend_indexation_enabled,
asset_metadata_indexation_enabled: self.asset_metadata_indexation_enabled,
indexation_flags: self.indexation_flags.clone(),
})
}

Expand All @@ -155,9 +188,7 @@ pub struct ReadView {
pub(crate) genesis_height: BlockHeight,
pub(crate) on_chain: OnChainView,
pub(crate) off_chain: OffChainView,
pub(crate) balances_indexation_enabled: bool,
pub(crate) coins_to_spend_indexation_enabled: bool,
pub(crate) asset_metadata_indexation_enabled: bool,
pub(crate) indexation_flags: IndexationFlags,
}

impl ReadView {
Expand Down Expand Up @@ -408,3 +439,26 @@ impl ReadView {
self.off_chain.message_is_spent(nonce)
}
}

#[test]
fn test_indexation_flags() {
let mut indexation = IndexationFlags::new();
assert!(!indexation.contains(&IndexationKind::Balances));
assert!(!indexation.contains(&IndexationKind::CoinsToSpend));
assert!(!indexation.contains(&IndexationKind::AssetMetadata));

indexation.insert(IndexationKind::Balances);
assert!(indexation.contains(&IndexationKind::Balances));
assert!(!indexation.contains(&IndexationKind::CoinsToSpend));
assert!(!indexation.contains(&IndexationKind::AssetMetadata));

indexation.insert(IndexationKind::CoinsToSpend);
assert!(indexation.contains(&IndexationKind::Balances));
assert!(indexation.contains(&IndexationKind::CoinsToSpend));
assert!(!indexation.contains(&IndexationKind::AssetMetadata));

indexation.insert(IndexationKind::AssetMetadata);
assert!(indexation.contains(&IndexationKind::Balances));
assert!(indexation.contains(&IndexationKind::CoinsToSpend));
assert!(indexation.contains(&IndexationKind::AssetMetadata));
}
6 changes: 5 additions & 1 deletion crates/fuel-core/src/query/assets.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
database::database_description::IndexationKind,
fuel_core_graphql_api::database::ReadView,
graphql_api::storage::assets::AssetDetails,
};
Expand All @@ -10,7 +11,10 @@ use fuel_core_types::fuel_tx::AssetId;

impl ReadView {
pub fn get_asset_details(&self, id: &AssetId) -> StorageResult<AssetDetails> {
if self.asset_metadata_indexation_enabled {
if self
.indexation_flags
.contains(&IndexationKind::AssetMetadata)
{
Ok(self
.off_chain
.asset_info(id)?
Expand Down
5 changes: 3 additions & 2 deletions crates/fuel-core/src/query/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
};

use crate::{
database::database_description::IndexationKind,
fuel_core_graphql_api::database::ReadView,
graphql_api::storage::balances::TotalBalanceAmount,
};
Expand Down Expand Up @@ -41,7 +42,7 @@ impl ReadView {
asset_id: AssetId,
base_asset_id: AssetId,
) -> StorageResult<AddressBalance> {
let amount = if self.balances_indexation_enabled {
let amount = if self.indexation_flags.contains(&IndexationKind::Balances) {
self.off_chain.balance(&owner, &asset_id, &base_asset_id)?
} else {
AssetQuery::new(
Expand Down Expand Up @@ -73,7 +74,7 @@ impl ReadView {
direction: IterDirection,
base_asset_id: &'a AssetId,
) -> impl Stream<Item = StorageResult<AddressBalance>> + 'a {
if self.balances_indexation_enabled {
if self.indexation_flags.contains(&IndexationKind::Balances) {
futures::future::Either::Left(self.balances_with_cache(
owner,
start,
Expand Down
5 changes: 4 additions & 1 deletion crates/fuel-core/src/schema/balance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
database::database_description::IndexationKind,
fuel_core_graphql_api::{
api_service::ConsensusProvider,
query_costs,
Expand Down Expand Up @@ -111,7 +112,9 @@ impl BalanceQuery {
) -> async_graphql::Result<Connection<AssetId, Balance, EmptyFields, EmptyFields>>
{
let query = ctx.read_view()?;
if !query.balances_indexation_enabled && (before.is_some() || after.is_some()) {
if !query.indexation_flags.contains(&IndexationKind::Balances)
&& (before.is_some() || after.is_some())
{
return Err(anyhow!(
"Can not use pagination when balances indexation is not available"
)
Expand Down
5 changes: 4 additions & 1 deletion crates/fuel-core/src/schema/coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
ExcludedCoinIds,
SpendQuery,
},
database::database_description::IndexationKind,
fuel_core_graphql_api::{
query_costs,
storage::coins::CoinsToSpendIndexKey,
Expand Down Expand Up @@ -289,7 +290,9 @@ impl CoinQuery {
query_per_asset.truncate(max_input as usize);

let read_view = ctx.read_view()?;
let indexation_available = read_view.coins_to_spend_indexation_enabled;
let indexation_available = read_view
.indexation_flags
.contains(&IndexationKind::CoinsToSpend);
if indexation_available {
coins_to_spend_with_cache(
owner,
Expand Down
Loading

0 comments on commit 1ef9d9c

Please sign in to comment.