Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use indexation cache to satisfy "coins to spend" queries #2463

Draft
wants to merge 13 commits into
base: rafal_2391_coins_to_spend_cache
Choose a base branch
from
Draft
13 changes: 1 addition & 12 deletions crates/fuel-core/src/coins_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ use fuel_core_types::{
};
use futures::TryStreamExt;
use rand::prelude::*;
use std::{
cmp::Reverse,
collections::HashSet,
};
use std::cmp::Reverse;
use thiserror::Error;

#[derive(Debug, Error)]
Expand Down Expand Up @@ -66,14 +63,6 @@ impl SpendQuery {
exclude_vec: Option<Vec<CoinId>>,
base_asset_id: AssetId,
) -> Result<Self, CoinsQueryError> {
let mut duplicate_checker = HashSet::with_capacity(query_per_asset.len());

for query in query_per_asset {
if !duplicate_checker.insert(query.id) {
return Err(CoinsQueryError::DuplicateAssets(query.id));
}
}

let exclude = exclude_vec.map_or_else(Default::default, Exclude::new);

Ok(Self {
Expand Down
4 changes: 2 additions & 2 deletions crates/fuel-core/src/graphql_api/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ pub struct ReadDatabase {
/// The flag that indicates whether the Balances indexation is enabled.
balances_indexation_enabled: bool,
/// The flag that indicates whether the CoinsToSpend indexation is enabled.
#[allow(dead_code)]
// TODO[RC]: The actual usage of the coins to spend index will be delivered in a follow-up PR.
coins_to_spend_indexation_enabled: bool,
}

Expand Down Expand Up @@ -135,6 +133,7 @@ impl ReadDatabase {
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,
})
}

Expand All @@ -151,6 +150,7 @@ pub struct ReadView {
pub(crate) on_chain: OnChainView,
pub(crate) off_chain: OffChainView,
pub(crate) balances_indexation_enabled: bool,
pub(crate) coins_to_spend_indexation_enabled: bool,
}

impl ReadView {
Expand Down
22 changes: 14 additions & 8 deletions crates/fuel-core/src/graphql_api/indexation/coins_to_spend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,25 @@ pub(crate) const RETRYABLE_BYTE: [u8; 1] = [0x00];
// Indicates that a message is non-retryable (also, all coins use this byte).
pub(crate) const NON_RETRYABLE_BYTE: [u8; 1] = [0x01];

// For key disambiguation purposes, the coins use UtxoId as a key suffix (34 bytes).
// Messages do not have UtxoId, hence we use Nonce for differentiation.
// Nonce is 32 bytes, so we need to pad it with 2 bytes to make it 34 bytes.
// We need equal length keys to maintain the correct, lexicographical order of the keys.
pub(crate) const MESSAGE_PADDING_BYTES: [u8; 2] = [0xFF, 0xFF];

#[repr(u8)]
#[derive(Clone)]
pub(crate) enum IndexedCoinType {
#[derive(Debug, Clone)]
pub enum IndexedCoinType {
Coin,
Message,
}

impl TryFrom<u8> for IndexedCoinType {
type Error = IndexationError;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(IndexedCoinType::Coin),
1 => Ok(IndexedCoinType::Message),
_ => todo!(), // Err(IndexationError::InvalidIndexedCoinType(value)),
}
}
}

fn add_coin<T>(block_st_transaction: &mut T, coin: &Coin) -> Result<(), IndexationError>
where
T: OffChainDatabaseTransaction,
Expand Down
14 changes: 10 additions & 4 deletions crates/fuel-core/src/graphql_api/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ use fuel_core_types::{
};
use std::sync::Arc;

use super::storage::balances::TotalBalanceAmount;
use crate::schema::coins::ExcludeInputBytes;

use super::{
indexation::coins_to_spend::IndexedCoinType,
storage::balances::TotalBalanceAmount,
};

pub trait OffChainDatabase: Send + Sync {
fn block_height(&self, block_id: &BlockId) -> StorageResult<BlockHeight>;
Expand Down Expand Up @@ -112,9 +117,10 @@ pub trait OffChainDatabase: Send + Sync {
&self,
owner: &Address,
asset_id: &AssetId,
max: u16,
// TODO[RC]: Also support message ids here - these are different than UtxoId. This will be taken care of in a follow-up PR.
) -> StorageResult<Vec<UtxoId>>;
target_amount: u64,
max_coins: u32,
excluded_ids: &ExcludeInputBytes,
) -> StorageResult<Vec<(Vec<u8>, IndexedCoinType)>>; // TODO[RC]: Named return type

fn contract_salt(&self, contract_id: &ContractId) -> StorageResult<Salt>;

Expand Down
Loading
Loading