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

Optimize balance-related queries with a cache #2383

Merged
merged 123 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
4a70f52
Add basic balances functionality
rafal-ch Oct 14, 2024
7d472fb
Add support for querying all balances for user
rafal-ch Oct 14, 2024
4296fd4
Adding `balances_indexation_progress` to DB metadata
rafal-ch Oct 14, 2024
77d0f16
Attempt at migrating the metadata to store the indexation progress
rafal-ch Oct 15, 2024
525e6f9
Merge remote-tracking branch 'upstream/master' into 1965_balances
rafal-ch Oct 16, 2024
8eba5d7
Hack the `replace_forced()` and `commit_changes_forced` in
rafal-ch Oct 16, 2024
c083f45
Introduce `ForcedCommitDatabase`
rafal-ch Oct 16, 2024
6b76c37
Update dependencies
rafal-ch Oct 16, 2024
f246cd0
DB metadata can track multiple indexation progresses
rafal-ch Oct 17, 2024
7472db7
into_genesis() attemt
rafal-ch Oct 17, 2024
b4d2e0f
Add some TODOs with ideas for the future
rafal-ch Oct 17, 2024
d38fdb3
Use `double_key!` macro to define the balances key
rafal-ch Oct 17, 2024
292acab
Add `basic_storage_tests!` for Balances
rafal-ch Oct 17, 2024
651bcc8
Merge remote-tracking branch 'upstream/master' into 1965_balances
rafal-ch Oct 17, 2024
8342c8f
Balances DB stores separate information for coins and messages
rafal-ch Oct 17, 2024
9a9f120
Fix the recursive call
rafal-ch Oct 18, 2024
6aa9325
Init indexation progresses with 0 upon metadata migration
rafal-ch Oct 18, 2024
b153db4
Remove debug prints
rafal-ch Oct 18, 2024
512a8a3
Store incoming balance in the new Balances DB
rafal-ch Oct 18, 2024
adf9e2a
Read balance from the new Balances database
rafal-ch Oct 18, 2024
344ca90
Update coin balance, don't overwrite
rafal-ch Oct 18, 2024
f73dbed
Use more detailed `IndexationStatus`, not just block height
rafal-ch Oct 21, 2024
80da09b
Add processing of `MessageImported`
rafal-ch Oct 21, 2024
ad5216d
Simplify processing of coins and message amounts
rafal-ch Oct 21, 2024
c784e44
Extract `increase_balance()`
rafal-ch Oct 21, 2024
5762665
Store coin and message balances separately
rafal-ch Oct 21, 2024
5595985
Clean up column naming
rafal-ch Oct 21, 2024
38dd8d6
Add test for coin balances
rafal-ch Oct 21, 2024
530bcaf
Support both coins and messages in the new balance system
rafal-ch Oct 21, 2024
5604f30
Merge remote-tracking branch 'upstream/master' into 1965_balances
rafal-ch Oct 22, 2024
562c087
update comment
rafal-ch Oct 22, 2024
82f7a16
Remove the database migration hack
rafal-ch Oct 22, 2024
7d0b014
Remove code related to handling base asset id
rafal-ch Oct 22, 2024
1fe3bba
Clean-up of the balance update code
rafal-ch Oct 22, 2024
fe60c98
Remove unused tests
rafal-ch Oct 22, 2024
adef78e
Handle overflow in `balance` query
rafal-ch Oct 22, 2024
9409d52
Clippy and formatting
rafal-ch Oct 22, 2024
13b6db9
Update db tests after reverting changes to metadata
rafal-ch Oct 22, 2024
55f9025
Add comment
rafal-ch Oct 22, 2024
d215844
Add support for `balances()` (plural) query
rafal-ch Oct 22, 2024
53131a3
Handle error properly instead of using `expect()`
rafal-ch Oct 22, 2024
1e24aaa
Add support for `direction` in balances query
rafal-ch Oct 22, 2024
eeea199
Remove safety check from the `balance` query
rafal-ch Oct 22, 2024
e77f33b
Fix balance logging
rafal-ch Oct 22, 2024
c9b7e29
Include message balance in `balances()` query
rafal-ch Oct 22, 2024
076cb42
Revert "Fix balance logging"
rafal-ch Oct 22, 2024
f5e2a6d
Revert a couple of unintentional changes
rafal-ch Oct 22, 2024
d1c6fcc
Rename database `Balances` to `CoinBalances`
rafal-ch Oct 22, 2024
8cc0280
Update comments
rafal-ch Oct 22, 2024
ca32195
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Oct 22, 2024
f082291
Fix formatting
rafal-ch Oct 23, 2024
f598395
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Oct 24, 2024
8ce4550
Add comment about potential discount on the balances query cost
rafal-ch Oct 24, 2024
4e84ac3
Update DB metadata with balances info
rafal-ch Oct 28, 2024
9577f30
Support both 'new' and 'old' way of querying balances
rafal-ch Oct 28, 2024
a16ef36
Support both 'new' and 'old' way of querying balance
rafal-ch Oct 28, 2024
80fb852
Do not touch the onchain DB metadata
rafal-ch Oct 28, 2024
c94a484
Write balances cache information do off-chain db on genesis
rafal-ch Oct 28, 2024
ddf0571
Use balances cache in GraphQL api
rafal-ch Oct 28, 2024
9078b05
Clean-up error handling
rafal-ch Oct 28, 2024
3b6b8c6
Satisfy clippy and fmt
rafal-ch Oct 28, 2024
5162936
generic update function
rafal-ch Oct 28, 2024
f736ecb
Extract processing of balance updates
rafal-ch Oct 28, 2024
d880e0a
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Oct 28, 2024
6927f03
Use instead of for balances key
rafal-ch Oct 29, 2024
66e26d9
Revert the supporsed-to-be temporary change that disabled warnings
rafal-ch Oct 29, 2024
a87698a
Remove unused lifetime from `HasIndexation` trait
rafal-ch Oct 29, 2024
ddadd80
Simplify trait bounds for `HasIndexation` trait
rafal-ch Oct 29, 2024
ccadf41
Further simplify trait bounds for `HasIndexation` trait
rafal-ch Oct 29, 2024
91e8abc
Split and rename the `HasIndexation` trait
rafal-ch Oct 30, 2024
ab7808f
WIP - bail when unable to update balance due to overflow
rafal-ch Oct 31, 2024
90fa259
Prefer `core::fmt::Display` over `std::fmt::Display`
rafal-ch Oct 31, 2024
0b39319
Use named const instead of plain `true` in genesis importer for clarity
rafal-ch Oct 31, 2024
4d6e17a
Remove reduntant write to `DatabaseMetadata::V2`
rafal-ch Oct 31, 2024
8f3e817
Ensure all indexations are enabled at genesis
rafal-ch Oct 31, 2024
895d9da
Fix `produce_block__raises_gas_price` after balance overflow check wa…
rafal-ch Oct 31, 2024
de11071
Fix more integration tests to work with the balance overflow checks
rafal-ch Nov 1, 2024
71226d4
Fix typo
rafal-ch Nov 1, 2024
474e207
Fix BLOB integration tests to work with the balance overflow checks
rafal-ch Nov 1, 2024
ca6057d
Revert "Fix BLOB integration tests to work with the balance overflow …
rafal-ch Nov 2, 2024
4d43038
Revert "Fix more integration tests to work with the balance overflow …
rafal-ch Nov 2, 2024
e3d898d
Revert "Fix `produce_block__raises_gas_price` after balance overflow …
rafal-ch Nov 2, 2024
9848f64
Do not bail when balances cannot be updated, log the error instead
rafal-ch Nov 2, 2024
dae0af5
Total balance of assets is now represented as `u128`
rafal-ch Nov 6, 2024
facbd2e
Infer types in `process_balances_update()`
rafal-ch Nov 6, 2024
9b8e491
Simplify trait bounds in `update_balances()`
rafal-ch Nov 6, 2024
9ea9c02
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Nov 6, 2024
54087fc
Fix formatting
rafal-ch Nov 6, 2024
20081fa
Satisfy Clippy
rafal-ch Nov 6, 2024
8b9f4e8
Update tests
rafal-ch Nov 6, 2024
e819e23
Asset balance queries now return U128 instead of U64.
rafal-ch Nov 7, 2024
de16099
Log errors when balance cannot be calculated in the legacy calculatio…
rafal-ch Nov 8, 2024
4f307e3
Mention an balance overflow follow-up issue in the comments
rafal-ch Nov 11, 2024
66d5948
Remove the `TODO` comment
rafal-ch Nov 11, 2024
7023227
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Nov 15, 2024
9a07cd2
Prevent the metadata from being overwritten with incorrect version
rafal-ch Nov 15, 2024
af4a726
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Nov 19, 2024
35663ae
Move metadata tests to a dedicated module
rafal-ch Nov 19, 2024
179cf69
Keep the previous indexation availability when updating metadata
rafal-ch Nov 19, 2024
1d40056
Add tests for balance with (non)retryable messages
rafal-ch Nov 19, 2024
bf83346
Refactor the `balances()` off_chain function
rafal-ch Nov 19, 2024
4805aa2
Make balance updates less generic but more readable
rafal-ch Nov 19, 2024
be9fdda
Introduce `IndexationError`
rafal-ch Nov 19, 2024
623bb9f
Extract indexation to a separate module
rafal-ch Nov 19, 2024
18f37cc
Fix issue in `decrease_message_balance()`
rafal-ch Nov 19, 2024
b2fc999
Add UTs for the indexation module
rafal-ch Nov 20, 2024
b721103
Simplify implementation of balances indexation
rafal-ch Nov 20, 2024
bd16f6c
Satisfy Clippy
rafal-ch Nov 20, 2024
53631e7
Extract and reuse `BALANCES_INDEXATION_ENABLED` flag
rafal-ch Nov 21, 2024
a8b950b
Use saturating_add when calculatin balances (hard to overflow u128 wi…
rafal-ch Nov 21, 2024
2e6ade7
Use saturating_add when calculating balances (hard to overflow u128 w…
rafal-ch Nov 21, 2024
7a95506
Do not import `tracing` and remove some log messages
rafal-ch Nov 21, 2024
33f75af
Move the indexation initialization to combined databases
rafal-ch Nov 21, 2024
6b8f18e
Return balances via iterator, not collection
rafal-ch Nov 22, 2024
2408e56
Remove dbg print
rafal-ch Nov 22, 2024
67d17d5
Make the `balances()` implementation more readable
rafal-ch Nov 22, 2024
bb2537e
Update comment to mention follow-up issue
rafal-ch Nov 22, 2024
53bbc7b
Revert the stray change in `balance.rs`
rafal-ch Nov 22, 2024
cca1891
Add basic storage tests for `CoinBalances` and `MessageBalances`
rafal-ch Nov 22, 2024
c0cb68d
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Nov 26, 2024
370a196
Merge remote-tracking branch 'upstream/master' into 1965_balances_cache
rafal-ch Nov 28, 2024
be9b742
Small suggestions and simplification to the balances indexation PR (#…
xgreenx Nov 29, 2024
181811a
Merge branch 'master' into 1965_balances_cache
rafal-ch Nov 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

#### Breaking
- [2389](https://github.com/FuelLabs/fuel-core/pull/2258): Updated the `messageProof` GraphQL schema to return a non-nullable `MessageProof`.
- [2383](https://github.com/FuelLabs/fuel-core/pull/2383): Asset balance queries now return U128 instead of U64.
- [2154](https://github.com/FuelLabs/fuel-core/pull/2154): Transaction graphql endpoints use `TransactionType` instead of `fuel_tx::Transaction`.
- [2446](https://github.com/FuelLabs/fuel-core/pull/2446): Use graphiql instead of graphql-playground due to known vulnerability and stale development.
- [2379](https://github.com/FuelLabs/fuel-core/issues/2379): Change `kv_store::Value` to be `Arc<[u8]>` instead of `Arc<Vec<u8>>`.
Expand Down
2 changes: 1 addition & 1 deletion bin/e2e-test-client/src/test_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl Wallet {
}

/// returns the balance associated with a wallet
pub async fn balance(&self, asset_id: Option<AssetId>) -> anyhow::Result<u64> {
pub async fn balance(&self, asset_id: Option<AssetId>) -> anyhow::Result<u128> {
self.client
.balance(&self.address, Some(&asset_id.unwrap_or_default()))
.await
Expand Down
4 changes: 3 additions & 1 deletion crates/client/assets/schema.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ scalar AssetId

type Balance {
owner: Address!
amount: U64!
amount: U128!
assetId: AssetId!
}

Expand Down Expand Up @@ -1259,6 +1259,8 @@ enum TxParametersVersion {

scalar TxPointer

scalar U128

scalar U16

scalar U32
Expand Down
2 changes: 1 addition & 1 deletion crates/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,7 @@ impl FuelClient {
&self,
owner: &Address,
asset_id: Option<&AssetId>,
) -> io::Result<u64> {
) -> io::Result<u128> {
let owner: schema::Address = (*owner).into();
let asset_id: schema::AssetId = match asset_id {
Some(asset_id) => (*asset_id).into(),
Expand Down
4 changes: 2 additions & 2 deletions crates/client/src/client/schema/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::client::{
Address,
AssetId,
PageInfo,
U64,
U128,
},
PageDirection,
PaginationRequest,
Expand Down Expand Up @@ -99,7 +99,7 @@ pub struct BalanceEdge {
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct Balance {
pub owner: Address,
pub amount: U64,
pub amount: U128,
pub asset_id: AssetId,
}

Expand Down
1 change: 1 addition & 0 deletions crates/client/src/client/schema/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ macro_rules! number_scalar {
};
}

number_scalar!(U128, u128);
number_scalar!(U64, u64);
number_scalar!(U32, u32);
number_scalar!(U16, u16);
Expand Down
2 changes: 1 addition & 1 deletion crates/client/src/client/types/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::client::{
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Balance {
pub owner: Address,
pub amount: u64,
pub amount: u128,
pub asset_id: AssetId,
}

Expand Down
1 change: 1 addition & 0 deletions crates/fuel-core/src/coins_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ mod tests {
let on_chain = self.database.on_chain().clone();
let off_chain = self.database.off_chain().clone();
ServiceDatabase::new(100, 0u32.into(), on_chain, off_chain)
.expect("should create service database")
}
}

Expand Down
196 changes: 184 additions & 12 deletions crates/fuel-core/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ use fuel_core_types::{
};
use itertools::Itertools;
use std::{
borrow::Cow,
fmt::Debug,
sync::Arc,
};
Expand All @@ -66,7 +67,10 @@ pub use fuel_core_database::Error;
pub type Result<T> = core::result::Result<T, Error>;

// TODO: Extract `Database` and all belongs into `fuel-core-database`.
use crate::database::database_description::gas_price::GasPriceDatabase;
use crate::database::database_description::{
gas_price::GasPriceDatabase,
indexation_availability,
};
#[cfg(feature = "rocksdb")]
use crate::state::{
historical_rocksdb::{
Expand Down Expand Up @@ -482,15 +486,13 @@ where
ConflictPolicy::Overwrite,
changes,
);
let maybe_current_metadata = transaction
.storage_as_mut::<MetadataTable<Description>>()
.get(&())?;
let metadata = update_metadata::<Description>(maybe_current_metadata, new_height);
transaction
.storage_as_mut::<MetadataTable<Description>>()
.insert(
&(),
&DatabaseMetadata::V1 {
version: Description::version(),
height: new_height,
},
)?;
.insert(&(), &metadata)?;

transaction.into_changes()
} else {
Expand All @@ -509,6 +511,39 @@ where
Ok(())
}

fn update_metadata<Description>(
maybe_current_metadata: Option<
Cow<DatabaseMetadata<<Description as DatabaseDescription>::Height>>,
>,
new_height: <Description as DatabaseDescription>::Height,
) -> DatabaseMetadata<<Description as DatabaseDescription>::Height>
where
Description: DatabaseDescription,
{
let updated_metadata = match maybe_current_metadata.as_ref() {
Some(metadata) => match metadata.as_ref() {
DatabaseMetadata::V1 { .. } => DatabaseMetadata::V1 {
version: Description::version(),
height: new_height,
},
DatabaseMetadata::V2 {
indexation_availability,
..
} => DatabaseMetadata::V2 {
version: Description::version(),
height: new_height,
indexation_availability: indexation_availability.clone(),
},
},
None => DatabaseMetadata::V2 {
version: Description::version(),
height: new_height,
indexation_availability: indexation_availability::<Description>(None),
},
};
updated_metadata
}

#[cfg(feature = "rocksdb")]
pub fn convert_to_rocksdb_direction(direction: IterDirection) -> rocksdb::Direction {
match direction {
Expand All @@ -524,10 +559,6 @@ mod tests {
database_description::DatabaseDescription,
Database,
};
use fuel_core_storage::{
tables::FuelBlocks,
StorageAsMut,
};

fn column_keys_not_exceed_count<Description>()
where
Expand Down Expand Up @@ -1084,4 +1115,145 @@ mod tests {
// rocks db fails
test(db);
}

mod metadata {
use crate::database::database_description::IndexationKind;
use fuel_core_storage::kv_store::StorageColumn;
use std::{
borrow::Cow,
collections::HashSet,
};
use strum::EnumCount;

use super::{
database_description::DatabaseDescription,
update_metadata,
DatabaseHeight,
DatabaseMetadata,
};

#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
struct HeightMock(u64);
impl DatabaseHeight for HeightMock {
fn as_u64(&self) -> u64 {
1
}

fn advance_height(&self) -> Option<Self> {
None
}

fn rollback_height(&self) -> Option<Self> {
None
}
}

const MOCK_VERSION: u32 = 0;

#[derive(EnumCount, enum_iterator::Sequence, Debug, Clone, Copy)]
enum ColumnMock {
Column1,
}

impl StorageColumn for ColumnMock {
fn name(&self) -> String {
"column".to_string()
}

fn id(&self) -> u32 {
42
}
}

#[derive(Debug, Clone, Copy)]
struct DatabaseDescriptionMock;
impl DatabaseDescription for DatabaseDescriptionMock {
type Column = ColumnMock;

type Height = HeightMock;

fn version() -> u32 {
MOCK_VERSION
}

fn name() -> String {
"mock".to_string()
}

fn metadata_column() -> Self::Column {
Self::Column::Column1
}

fn prefix(_: &Self::Column) -> Option<usize> {
None
}
}

#[test]
fn update_metadata_preserves_v1() {
let current_metadata: DatabaseMetadata<HeightMock> = DatabaseMetadata::V1 {
version: MOCK_VERSION,
height: HeightMock(1),
};
let new_metadata = update_metadata::<DatabaseDescriptionMock>(
Some(Cow::Borrowed(&current_metadata)),
HeightMock(2),
);

match new_metadata {
DatabaseMetadata::V1 { version, height } => {
assert_eq!(version, current_metadata.version());
assert_eq!(height, HeightMock(2));
}
DatabaseMetadata::V2 { .. } => panic!("should be V1"),
}
}

#[test]
fn update_metadata_preserves_v2() {
let available_indexation = HashSet::new();

let current_metadata: DatabaseMetadata<HeightMock> = DatabaseMetadata::V2 {
version: MOCK_VERSION,
height: HeightMock(1),
indexation_availability: available_indexation.clone(),
};
let new_metadata = update_metadata::<DatabaseDescriptionMock>(
Some(Cow::Borrowed(&current_metadata)),
HeightMock(2),
);

match new_metadata {
DatabaseMetadata::V1 { .. } => panic!("should be V2"),
DatabaseMetadata::V2 {
version,
height,
indexation_availability,
} => {
assert_eq!(version, current_metadata.version());
assert_eq!(height, HeightMock(2));
assert_eq!(indexation_availability, available_indexation);
}
}
}

#[test]
fn update_metadata_none_becomes_v2() {
let new_metadata =
update_metadata::<DatabaseDescriptionMock>(None, HeightMock(2));

match new_metadata {
DatabaseMetadata::V1 { .. } => panic!("should be V2"),
DatabaseMetadata::V2 {
version,
height,
indexation_availability,
} => {
assert_eq!(version, MOCK_VERSION);
assert_eq!(height, HeightMock(2));
assert_eq!(indexation_availability, IndexationKind::all().collect());
}
}
}
}
}
Loading
Loading