From 29dadbfe38c22484c2d07e279c1c69d206ca08a4 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 11 Jan 2025 05:14:25 +0700 Subject: [PATCH] a lot of grovedb support --- Cargo.lock | 18 ++-- packages/rs-dpp/src/balances/credits.rs | 3 + packages/rs-dpp/src/balances/mod.rs | 1 + .../src/balances/total_tokens_balance/mod.rs | 53 +++++++++++ .../batch_transition/v1/v0_methods.rs | 1 + packages/rs-drive-abci/src/config.rs | 8 ++ .../src/execution/platform_events/mod.rs | 1 + .../v0/mod.rs | 33 ++++++- .../execution/platform_events/tokens/mod.rs | 1 + .../validate_token_aggregated_balance/mod.rs | 1 + .../validate_token_aggregated_balance/v0.rs | 46 +++++++++ packages/rs-drive/Cargo.toml | 12 +-- .../v0/mod.rs | 3 + .../insert/add_contract_to_storage/v0/mod.rs | 2 +- .../contract/insert/insert_contract/v1/mod.rs | 27 ++---- .../contract/update/update_contract/v0/mod.rs | 2 +- .../add_document_to_primary_storage/v0/mod.rs | 2 +- .../v0/mod.rs | 4 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 8 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 10 +- .../for_add_group_action/v0/mod.rs | 3 + .../group/insert/add_group_action/v0/mod.rs | 2 +- .../group/insert/add_new_groups/v0/mod.rs | 4 +- packages/rs-drive/src/drive/group/mod.rs | 24 ++--- .../merge_identity_contract_nonce/v0/mod.rs | 4 +- .../estimation_costs/for_balances/v0/mod.rs | 3 + .../insert/add_new_identity/v0/mod.rs | 2 +- .../src/drive/initialization/v1/mod.rs | 21 ++++ packages/rs-drive/src/drive/mod.rs | 6 +- .../v0/mod.rs | 3 + .../v0/mod.rs | 3 + .../v0/mod.rs | 3 + .../for_total_system_credits_update/v0/mod.rs | 3 + .../src/drive/tokens/apply_status/v0/mod.rs | 14 ++- .../add_to_previous_token_balance/v0/mod.rs | 1 - .../v0/mod.rs | 1 - .../calculate_total_tokens_balance/mod.rs | 42 ++++++++ .../calculate_total_tokens_balance/v0/mod.rs | 47 +++++++++ .../estimated_costs/for_token_balances/mod.rs | 23 +++-- .../for_token_balances/v0/mod.rs | 61 +++--------- .../for_token_identity_infos/mod.rs | 57 +++++++++++ .../for_token_identity_infos/v0/mod.rs | 81 ++++++++++++++++ .../for_token_status_infos/mod.rs | 57 +++++++++++ .../for_token_status_infos/v0/mod.rs | 69 ++++++++++++++ .../for_token_total_supply/v0/mod.rs | 3 + .../src/drive/tokens/estimated_costs/mod.rs | 9 ++ .../src/drive/tokens/freeze/v0/mod.rs | 3 +- packages/rs-drive/src/drive/tokens/mod.rs | 95 +++++++++++++++---- .../add_to_token_total_supply/v0/mod.rs | 23 +++-- .../tokens/system/create_token_trees/mod.rs | 2 +- .../system/create_token_trees/v0/mod.rs | 67 ++++--------- .../remove_from_token_total_supply/v0/mod.rs | 5 +- .../src/drive/tokens/unfreeze/v0/mod.rs | 3 +- .../v0/mod.rs | 4 +- .../v0/mod.rs | 2 +- packages/rs-drive/src/fees/op.rs | 81 +++++++++++++++- .../mod.rs | 6 +- .../v0/mod.rs | 78 +++++---------- .../mod.rs | 2 +- .../v0/mod.rs | 40 ++++---- .../grove_get_big_sum_tree_total_value/mod.rs | 58 +++++++++++ .../v0/mod.rs | 67 +++++++++++++ .../rs-drive/src/util/grove_operations/mod.rs | 3 + packages/rs-platform-version/Cargo.toml | 2 +- .../drive_grove_method_versions/mod.rs | 1 + .../drive_grove_method_versions/v1.rs | 1 + .../drive_identity_method_versions/mod.rs | 1 + .../drive_identity_method_versions/v1.rs | 1 + .../drive_token_method_versions/mod.rs | 1 + .../drive_token_method_versions/v1.rs | 1 + 74 files changed, 1039 insertions(+), 298 deletions(-) create mode 100644 packages/rs-dpp/src/balances/total_tokens_balance/mod.rs create mode 100644 packages/rs-drive-abci/src/execution/platform_events/tokens/mod.rs create mode 100644 packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/mod.rs create mode 100644 packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/v0.rs create mode 100644 packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/mod.rs create mode 100644 packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/v0/mod.rs create mode 100644 packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/mod.rs create mode 100644 packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/v0/mod.rs create mode 100644 packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/mod.rs create mode 100644 packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/v0/mod.rs create mode 100644 packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/mod.rs create mode 100644 packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/v0/mod.rs diff --git a/Cargo.lock b/Cargo.lock index c5f11ebd4ea..f0603cd424a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2141,7 +2141,7 @@ dependencies = [ [[package]] name = "grovedb" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "axum", "bincode", @@ -2175,7 +2175,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "integer-encoding", "intmap", @@ -2185,7 +2185,7 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "grovedb-costs", "hex", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "bincode", "blake3", @@ -2222,12 +2222,12 @@ dependencies = [ [[package]] name = "grovedb-path" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" [[package]] name = "grovedb-storage" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "blake3", "grovedb-costs", @@ -2246,7 +2246,7 @@ dependencies = [ [[package]] name = "grovedb-version" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "thiserror", "versioned-feature-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2255,7 +2255,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "hex", "itertools 0.12.1", @@ -2264,7 +2264,7 @@ dependencies = [ [[package]] name = "grovedbg-types" version = "2.1.0" -source = "git+https://github.com/dashpay/grovedb?rev=2417f7a72900cd3dca943ad52c979bc8abfdaa20#2417f7a72900cd3dca943ad52c979bc8abfdaa20" +source = "git+https://github.com/dashpay/grovedb?rev=263dcd5164c7db597bf7de7b6de133ad7cd77d50#263dcd5164c7db597bf7de7b6de133ad7cd77d50" dependencies = [ "serde", "serde_with 3.9.0", diff --git a/packages/rs-dpp/src/balances/credits.rs b/packages/rs-dpp/src/balances/credits.rs index 678159d24a3..4376686a967 100644 --- a/packages/rs-dpp/src/balances/credits.rs +++ b/packages/rs-dpp/src/balances/credits.rs @@ -22,6 +22,9 @@ pub type Credits = u64; /// Token Amount type pub type TokenAmount = u64; +/// Sum token amount +pub type SumTokenAmount = i128; + /// Signed Credits type is used for internal computations and total credits /// balance verification diff --git a/packages/rs-dpp/src/balances/mod.rs b/packages/rs-dpp/src/balances/mod.rs index a6b48811208..c0f505ac786 100644 --- a/packages/rs-dpp/src/balances/mod.rs +++ b/packages/rs-dpp/src/balances/mod.rs @@ -1,3 +1,4 @@ pub mod total_credits_balance; pub mod credits; +pub mod total_tokens_balance; diff --git a/packages/rs-dpp/src/balances/total_tokens_balance/mod.rs b/packages/rs-dpp/src/balances/total_tokens_balance/mod.rs new file mode 100644 index 00000000000..84aa157643a --- /dev/null +++ b/packages/rs-dpp/src/balances/total_tokens_balance/mod.rs @@ -0,0 +1,53 @@ +use crate::balances::credits::SumTokenAmount; +use crate::ProtocolError; +use std::fmt; + +/// The outcome of verifying token balances +#[derive(Copy, Clone, Debug)] +pub struct TotalTokensBalance { + /// all the tokens in platform + pub total_tokens_in_platform: SumTokenAmount, + /// all the tokens in identity token balances + pub total_identity_token_balances: SumTokenAmount, +} + +impl fmt::Display for TotalTokensBalance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "TotalTokensBalance {{")?; + writeln!( + f, + " total_tokens_in_platform: {},", + self.total_tokens_in_platform + )?; + writeln!( + f, + " total_identity_token_balances: {}", + self.total_identity_token_balances + )?; + write!(f, "}}") + } +} +impl TotalTokensBalance { + /// Is the outcome okay? basically do the values match up + /// Errors in case of overflow + pub fn ok(&self) -> Result { + let TotalTokensBalance { + total_tokens_in_platform, + total_identity_token_balances, + } = *self; + + if total_tokens_in_platform < 0 { + return Err(ProtocolError::CriticalCorruptedCreditsCodeExecution( + "Tokens in platform are less than 0".to_string(), + )); + } + + if total_identity_token_balances < 0 { + return Err(ProtocolError::CriticalCorruptedCreditsCodeExecution( + "Tokens in identity balances are less than 0".to_string(), + )); + } + + Ok(total_tokens_in_platform == total_identity_token_balances) + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs index b1e12f82f6f..91d9120c443 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs @@ -60,6 +60,7 @@ use crate::state_transition::batch_transition::token_freeze_transition::TokenFre use crate::state_transition::batch_transition::token_mint_transition::TokenMintTransitionV0; use crate::state_transition::batch_transition::token_transfer_transition::TokenTransferTransitionV0; use crate::state_transition::batch_transition::token_unfreeze_transition::TokenUnfreezeTransitionV0; +#[cfg(feature = "state-transition-signing")] use crate::tokens::emergency_action::TokenEmergencyAction; impl DocumentsBatchTransitionAccessorsV0 for BatchTransitionV1 { diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index 1e8f5f3c264..e004e14df60 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -105,6 +105,10 @@ pub struct ExecutionConfig { #[serde(default = "ExecutionConfig::default_verify_sum_trees")] pub verify_sum_trees: bool, + /// Should we verify sum trees? Useful to set as `false` for tests + #[serde(default = "ExecutionConfig::default_verify_token_sum_trees")] + pub verify_token_sum_trees: bool, + /// How long in seconds should an epoch last /// It might last a lot longer if the chain is halted #[serde( @@ -614,6 +618,10 @@ impl ExecutionConfig { true } + fn default_verify_token_sum_trees() -> bool { + true + } + fn default_use_document_triggers() -> bool { true } diff --git a/packages/rs-drive-abci/src/execution/platform_events/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/mod.rs index 41b64d63b18..759deac244c 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/mod.rs @@ -22,6 +22,7 @@ pub(in crate::execution) mod initialization; pub(in crate::execution) mod protocol_upgrade; /// State transition processing pub(in crate::execution) mod state_transition_processing; +mod tokens; /// Voting pub(in crate::execution) mod voting; /// Withdrawal methods diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs index b3d9eae7f67..810e091b318 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs @@ -17,6 +17,9 @@ use drive::drive::identity::withdrawals::paths::{ WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, }; use drive::drive::system::misc_path; +use drive::drive::tokens::{ + tokens_root_path, TOKEN_BALANCES_KEY, TOKEN_IDENTITY_INFO_KEY, TOKEN_STATUS_INFO_KEY, +}; use drive::drive::RootTree; use drive::grovedb::{Element, Transaction}; use drive::grovedb_path::SubtreePath; @@ -113,11 +116,39 @@ impl Platform { &platform_version.drive, )?; + let path = tokens_root_path(); + self.drive.grove_insert_if_not_exists( + (&path).into(), + &[TOKEN_BALANCES_KEY], + Element::empty_big_sum_tree(), + Some(transaction), + None, + &platform_version.drive, + )?; + + self.drive.grove_insert_if_not_exists( + (&path).into(), + &[TOKEN_IDENTITY_INFO_KEY], + Element::empty_tree(), + Some(transaction), + None, + &platform_version.drive, + )?; + + self.drive.grove_insert_if_not_exists( + (&path).into(), + &[TOKEN_STATUS_INFO_KEY], + Element::empty_tree(), + Some(transaction), + None, + &platform_version.drive, + )?; + let path = misc_path(); self.drive.grove_insert_if_not_exists( (&path).into(), TOTAL_TOKEN_SUPPLIES_STORAGE_KEY.as_slice(), - Element::empty_tree(), + Element::empty_big_sum_tree(), Some(transaction), None, &platform_version.drive, diff --git a/packages/rs-drive-abci/src/execution/platform_events/tokens/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/tokens/mod.rs new file mode 100644 index 00000000000..b3c9f415e5e --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/tokens/mod.rs @@ -0,0 +1 @@ +mod validate_token_aggregated_balance; diff --git a/packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/mod.rs new file mode 100644 index 00000000000..e084dffc38f --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/mod.rs @@ -0,0 +1 @@ +mod v0; diff --git a/packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/v0.rs b/packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/v0.rs new file mode 100644 index 00000000000..c1defaa1236 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/tokens/validate_token_aggregated_balance/v0.rs @@ -0,0 +1,46 @@ +use dpp::block::epoch::Epoch; +use drive::drive::Drive; +use drive::grovedb::Transaction; + +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::block_execution_context::BlockExecutionContext; +use crate::platform_types::platform::Platform; +use platform_version::version::PlatformVersion; + +impl Platform { + /// Adds operations to GroveDB op batch related to processing + /// and distributing the block fees from the previous block and applies the batch. + /// + /// Returns `ProcessedBlockFeesOutcome`. + #[inline(always)] + pub(super) fn validate_token_aggregated_balance_v0( + &self, + block_execution_context: &BlockExecutionContext, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + if self.config.execution.verify_token_sum_trees { + // Verify sum trees + let credits_verified = self + .drive + .calculate_total_token_balance(Some(transaction), &platform_version.drive) + .map_err(Error::Drive)?; + + if !credits_verified.ok()? { + return Err(Error::Execution( + ExecutionError::CorruptedCreditsNotBalanced(format!( + "credits are not balanced after block execution {:?} off by {}", + credits_verified, + credits_verified + .total_in_trees() + .unwrap() + .abs_diff(credits_verified.total_credits_in_platform) + )), + )); + } + } + + Ok(outcome) + } +} diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index cd76d01dce3..2441804b839 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -52,12 +52,12 @@ enum-map = { version = "2.0.3", optional = true } intmap = { version = "2.0.0", features = ["serde"], optional = true } chrono = { version = "0.4.35", optional = true } itertools = { version = "0.13", optional = true } -grovedb = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20", optional = true, default-features = false } -grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20", optional = true } -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20", optional = true } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20" } -grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20" } +grovedb = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50", optional = true, default-features = false } +grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50", optional = true } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50", optional = true } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50" } +grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50" } [dev-dependencies] criterion = "0.5" diff --git a/packages/rs-drive/src/drive/asset_lock/estimation_costs/add_estimation_costs_for_adding_asset_lock/v0/mod.rs b/packages/rs-drive/src/drive/asset_lock/estimation_costs/add_estimation_costs_for_adding_asset_lock/v0/mod.rs index 3973d252e8d..1d8cb180eea 100644 --- a/packages/rs-drive/src/drive/asset_lock/estimation_costs/add_estimation_costs_for_adding_asset_lock/v0/mod.rs +++ b/packages/rs-drive/src/drive/asset_lock/estimation_costs/add_estimation_costs_for_adding_asset_lock/v0/mod.rs @@ -67,6 +67,9 @@ impl Drive { 12, // 32 + 1 + 1 / 3 SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 2, }, None, diff --git a/packages/rs-drive/src/drive/contract/insert/add_contract_to_storage/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_contract_to_storage/v0/mod.rs index 837d1fcbcc9..07e33e9be1f 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_contract_to_storage/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_contract_to_storage/v0/mod.rs @@ -79,7 +79,7 @@ impl Drive { self.batch_insert_empty_tree_if_not_exists( key_info, - false, + TreeType::NormalTree, storage_flags.as_ref().map(|flags| flags.as_ref()), apply_type, transaction, diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs index 9d5c2536108..69f9dfe2ba7 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs @@ -11,8 +11,7 @@ use dpp::fee::fee_result::FeeResult; use crate::drive::balances::total_tokens_root_supply_path_vec; use crate::drive::tokens::{ - token_balances_path_vec, token_path, tokens_root_path, TOKEN_BALANCES_KEY, - TOKEN_IDENTITY_INFO_KEY, + token_balances_path_vec, token_balances_root_path, token_identity_infos_root_path, }; use crate::error::contract::DataContractError; use crate::util::object_size_info::DriveKeyInfo; @@ -23,9 +22,8 @@ use dpp::serialization::PlatformSerializableWithPlatformVersion; use dpp::version::PlatformVersion; use dpp::ProtocolError; use grovedb::batch::KeyInfoPath; -use grovedb::Element::Item; +use grovedb::Element::SumItem; use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; -use integer_encoding::VarInt; use std::collections::HashMap; impl Drive { @@ -186,7 +184,6 @@ impl Drive { { Drive::add_estimation_costs_for_token_balances( token_id_bytes, - false, estimated_costs_only_with_layer_info, &platform_version.drive, )?; @@ -196,25 +193,17 @@ impl Drive { )?; } - self.batch_insert_empty_tree( - tokens_root_path(), - DriveKeyInfo::KeyRef(&token_id_bytes), - None, - &mut batch_operations, - &platform_version.drive, - )?; - self.batch_insert_empty_sum_tree( - token_path(&token_id_bytes), - DriveKeyInfo::Key(vec![TOKEN_BALANCES_KEY]), + token_balances_root_path(), + DriveKeyInfo::KeyRef(token_id_bytes.as_slice()), None, &mut batch_operations, &platform_version.drive, )?; self.batch_insert_empty_tree( - token_path(&token_id_bytes), - DriveKeyInfo::Key(vec![TOKEN_IDENTITY_INFO_KEY]), + token_identity_infos_root_path(), + DriveKeyInfo::KeyRef(token_id_bytes.as_slice()), None, &mut batch_operations, &platform_version.drive, @@ -251,7 +240,7 @@ impl Drive { PathKeyElement(( path_holding_total_token_supply, token_id.to_vec(), - Item(token_config.base_supply().encode_var_vec(), None), + Element::new_sum_item(token_config.base_supply() as i64), )), &mut batch_operations, &platform_version.drive, @@ -261,7 +250,7 @@ impl Drive { PathKeyElement(( path_holding_total_token_supply, token_id.to_vec(), - Item(0u64.encode_var_vec(), None), + SumItem(0, None), )), &mut batch_operations, &platform_version.drive, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v0/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v0/mod.rs index 22ce029f82c..141749a2ffb 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v0/mod.rs @@ -317,7 +317,7 @@ impl Drive { if !index_cache.contains(index_bytes) { self.batch_insert_empty_tree_if_not_exists( PathFixedSizeKeyRef((type_path, index.name.as_bytes())), - false, + TreeType::NormalTree, storage_flags.as_ref().map(|flags| flags.as_ref()), apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs index c26d1b944cc..ea1ae0f2a7c 100644 --- a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs @@ -135,7 +135,7 @@ impl Drive { // we first insert an empty tree if the document is new self.batch_insert_empty_tree_if_not_exists( path_key_info, - false, + TreeType::NormalTree, storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs index 6b4932e1865..0bfcf82e67f 100644 --- a/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs @@ -109,7 +109,7 @@ impl Drive { // here we are inserting an empty tree that will have a subtree of all other index properties self.batch_insert_empty_tree_if_not_exists( path_key_info.clone(), - false, + TreeType::NormalTree, *storage_flags, apply_type, transaction, @@ -157,7 +157,7 @@ impl Drive { // here we are inserting an empty tree that will have a subtree of all other index properties self.batch_insert_empty_tree_if_not_exists( path_key_info.clone(), - false, + TreeType::NormalTree, *storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs index 320a4625af5..4ca3e7662d8 100644 --- a/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs @@ -120,7 +120,7 @@ impl Drive { // here we are inserting an empty tree that will have a subtree of all other index properties self.batch_insert_empty_tree_if_not_exists( path_key_info.clone(), - false, + TreeType::NormalTree, storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v0/mod.rs index c84ab415615..c3744cbcdcb 100644 --- a/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v0/mod.rs @@ -75,7 +75,7 @@ impl Drive { // a contested resource index self.batch_insert_empty_tree_if_not_exists( path_key_info, - false, + TreeType::NormalTree, *storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs index 43433cb6e70..52297150a0f 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs @@ -153,7 +153,7 @@ impl Drive { document_top_field .clone() .add_path_info(index_path_info.clone()), - false, + TreeType::NormalTree, storage_flags, apply_type, transaction, @@ -200,7 +200,7 @@ impl Drive { self.batch_insert_empty_tree_if_not_exists( DriveKeyInfo::Key(owner_id.to_vec()).add_path_info(index_path_info.clone()), - false, + TreeType::NormalTree, storage_flags, apply_type, transaction, @@ -212,7 +212,7 @@ impl Drive { let inserted_abstain = self.batch_insert_empty_tree_if_not_exists( DriveKeyInfo::Key(RESOURCE_ABSTAIN_VOTE_TREE_KEY_U8_32.to_vec()) .add_path_info(index_path_info.clone()), - false, + TreeType::NormalTree, storage_flags, apply_type, transaction, @@ -224,7 +224,7 @@ impl Drive { let inserted_lock = self.batch_insert_empty_tree_if_not_exists( DriveKeyInfo::Key(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()) .add_path_info(index_path_info.clone()), - false, + TreeType::NormalTree, storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_reference_and_vote_subtree_to_document_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_reference_and_vote_subtree_to_document_operations/v0/mod.rs index 4370b1811d3..cd4fa6ecd11 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_reference_and_vote_subtree_to_document_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_reference_and_vote_subtree_to_document_operations/v0/mod.rs @@ -166,7 +166,7 @@ impl Drive { // here we are the tree that will contain the voting tree let inserted = self.batch_insert_empty_tree_if_not_exists( votes_path_key_info, - true, + TreeType::SumTree, storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs index a23851323de..c6d8faedcbb 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs @@ -93,7 +93,7 @@ impl Drive { // here we are the tree that will contain the voting tree let inserted = self.batch_insert_empty_tree_if_not_exists( votes_path_key_info.clone(), - true, + TreeType::SumTree, storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v0/mod.rs index eb982b4f3c3..5a6a14e759e 100644 --- a/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v0/mod.rs @@ -34,7 +34,7 @@ use dpp::version::PlatformVersion; use grovedb::batch::key_info::KeyInfo; use grovedb::batch::key_info::KeyInfo::KnownKey; use grovedb::batch::KeyInfoPath; -use grovedb::{Element, EstimatedLayerInformation, MaybeTree, TransactionArg}; +use grovedb::{Element, EstimatedLayerInformation, MaybeTree, TransactionArg, TreeType}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; @@ -227,7 +227,7 @@ impl Drive { index_path.clone(), document_top_field.as_slice(), )), - false, + TreeType::NormalTree, storage_flags, BatchInsertTreeApplyType::StatefulBatchInsertTree, transaction, @@ -300,7 +300,7 @@ impl Drive { index_path.clone(), index_property.name.as_bytes(), )), - false, + TreeType::NormalTree, storage_flags, BatchInsertTreeApplyType::StatefulBatchInsertTree, transaction, @@ -332,7 +332,7 @@ impl Drive { index_path.clone(), document_index_field.as_slice(), )), - false, + TreeType::NormalTree, storage_flags, BatchInsertTreeApplyType::StatefulBatchInsertTree, transaction, @@ -409,7 +409,7 @@ impl Drive { // here we are inserting an empty tree that will have a subtree of all other index properties self.batch_insert_empty_tree_if_not_exists( PathKeyInfo::PathKeyRef::<0>((index_path.clone(), &[0])), - false, + TreeType::NormalTree, storage_flags, BatchInsertTreeApplyType::StatefulBatchInsertTree, transaction, diff --git a/packages/rs-drive/src/drive/group/estimated_costs/for_add_group_action/v0/mod.rs b/packages/rs-drive/src/drive/group/estimated_costs/for_add_group_action/v0/mod.rs index 1133447945b..00829a54679 100644 --- a/packages/rs-drive/src/drive/group/estimated_costs/for_add_group_action/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/estimated_costs/for_add_group_action/v0/mod.rs @@ -85,6 +85,9 @@ impl Drive { 1, SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 2, }, None, diff --git a/packages/rs-drive/src/drive/group/insert/add_group_action/v0/mod.rs b/packages/rs-drive/src/drive/group/insert/add_group_action/v0/mod.rs index a0d8ce1dd97..2bb92154586 100644 --- a/packages/rs-drive/src/drive/group/insert/add_group_action/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/insert/add_group_action/v0/mod.rs @@ -160,7 +160,7 @@ impl Drive { // We insert the contract root into the group tree inserted_root_action = self.batch_insert_empty_tree_if_not_exists( PathFixedSizeKeyRef((group_action_root_path, action_id.as_slice())), - false, + TreeType::NormalTree, None, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/group/insert/add_new_groups/v0/mod.rs b/packages/rs-drive/src/drive/group/insert/add_new_groups/v0/mod.rs index bde785e07c0..2064aecb6d9 100644 --- a/packages/rs-drive/src/drive/group/insert/add_new_groups/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/insert/add_new_groups/v0/mod.rs @@ -110,7 +110,7 @@ impl Drive { // We insert the contract root into the group tree let inserted = self.batch_insert_empty_tree_if_not_exists( PathFixedSizeKey((group_tree_path, contract_id.to_vec())), - false, + TreeType::NormalTree, None, apply_type, transaction, @@ -158,7 +158,7 @@ impl Drive { let path = group_contract_path(contract_id.as_slice()); let inserted = self.batch_insert_empty_tree_if_not_exists( PathFixedSizeKeyRef((path, group_pos_bytes.as_slice())), - false, + TreeType::NormalTree, None, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/group/mod.rs b/packages/rs-drive/src/drive/group/mod.rs index d283c314a97..b6f530ccd81 100644 --- a/packages/rs-drive/src/drive/group/mod.rs +++ b/packages/rs-drive/src/drive/group/mod.rs @@ -19,31 +19,31 @@ pub const ACTION_SIGNERS_KEY: &[u8; 1] = b"S"; /// Group root path #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_root_path() -> [&'static [u8]; 1] { +pub fn group_root_path() -> [&'static [u8]; 1] { [Into::<&[u8; 1]>::into(RootTree::GroupActions)] } /// Group root path vector #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_root_path_vec() -> Vec> { +pub fn group_root_path_vec() -> Vec> { vec![vec![RootTree::GroupActions as u8]] } /// Group path #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_contract_path(contract_id: &[u8]) -> [&[u8]; 2] { +pub fn group_contract_path(contract_id: &[u8]) -> [&[u8]; 2] { [Into::<&[u8; 1]>::into(RootTree::GroupActions), contract_id] } /// Group path vector #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_contract_path_vec(contract_id: &[u8]) -> Vec> { +pub fn group_contract_path_vec(contract_id: &[u8]) -> Vec> { vec![vec![RootTree::GroupActions as u8], contract_id.to_vec()] } /// Group path #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_path<'a>( +pub fn group_path<'a>( contract_id: &'a [u8], group_contract_position_bytes: &'a [u8], ) -> [&'a [u8]; 3] { @@ -56,7 +56,7 @@ pub(crate) fn group_path<'a>( /// Group path vector #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_path_vec( +pub fn group_path_vec( contract_id: &[u8], group_contract_position: GroupContractPosition, ) -> Vec> { @@ -69,7 +69,7 @@ pub(crate) fn group_path_vec( /// Group action path #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_action_root_path<'a>( +pub fn group_action_root_path<'a>( contract_id: &'a [u8], group_contract_position_bytes: &'a [u8], ) -> [&'a [u8]; 4] { @@ -83,7 +83,7 @@ pub(crate) fn group_action_root_path<'a>( /// Group action path vector #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_action_root_path_vec( +pub fn group_action_root_path_vec( contract_id: &[u8], group_contract_position: GroupContractPosition, ) -> Vec> { @@ -97,7 +97,7 @@ pub(crate) fn group_action_root_path_vec( /// Group path #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_action_path<'a>( +pub fn group_action_path<'a>( contract_id: &'a [u8], group_contract_position_bytes: &'a [u8], action_id: &'a [u8], @@ -113,7 +113,7 @@ pub(crate) fn group_action_path<'a>( /// Group path vector #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_action_path_vec( +pub fn group_action_path_vec( contract_id: &[u8], group_contract_position: GroupContractPosition, action_id: &[u8], @@ -129,7 +129,7 @@ pub(crate) fn group_action_path_vec( /// Group path #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_action_signers_path<'a>( +pub fn group_action_signers_path<'a>( contract_id: &'a [u8], group_contract_position_bytes: &'a [u8], action_id: &'a [u8], @@ -146,7 +146,7 @@ pub(crate) fn group_action_signers_path<'a>( /// Group path vector #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn group_action_signers_path_vec( +pub fn group_action_signers_path_vec( contract_id: &[u8], group_contract_position: GroupContractPosition, action_id: &[u8], diff --git a/packages/rs-drive/src/drive/identity/contract_info/identity_contract_nonce/merge_identity_contract_nonce/v0/mod.rs b/packages/rs-drive/src/drive/identity/contract_info/identity_contract_nonce/merge_identity_contract_nonce/v0/mod.rs index be3b7075665..500e9ba394e 100644 --- a/packages/rs-drive/src/drive/identity/contract_info/identity_contract_nonce/merge_identity_contract_nonce/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/contract_info/identity_contract_nonce/merge_identity_contract_nonce/v0/mod.rs @@ -119,7 +119,7 @@ impl Drive { // we insert the contract root tree if it doesn't exist already self.batch_insert_empty_tree_if_not_exists( PathKeyInfo::<0>::PathKey((identity_path, vec![IdentityContractInfo as u8])), - false, + TreeType::NormalTree, None, apply_type, transaction, @@ -134,7 +134,7 @@ impl Drive { identity_contract_info_root_path_vec(&identity_id), contract_id.to_vec(), )), - false, + TreeType::NormalTree, None, apply_type, transaction, diff --git a/packages/rs-drive/src/drive/identity/estimation_costs/for_balances/v0/mod.rs b/packages/rs-drive/src/drive/identity/estimation_costs/for_balances/v0/mod.rs index 59696e6aac5..db78d1fff31 100644 --- a/packages/rs-drive/src/drive/identity/estimation_costs/for_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/estimation_costs/for_balances/v0/mod.rs @@ -62,6 +62,9 @@ impl Drive { 1, SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 1, }, None, diff --git a/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs b/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs index 83146f7a86c..26055d92799 100644 --- a/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs @@ -131,7 +131,7 @@ impl Drive { // We insert the identity tree let inserted = self.batch_insert_empty_tree_if_not_exists( PathFixedSizeKey((identity_tree_path, id.to_vec())), - false, + TreeType::NormalTree, Some(&storage_flags), apply_type, transaction, diff --git a/packages/rs-drive/src/drive/initialization/v1/mod.rs b/packages/rs-drive/src/drive/initialization/v1/mod.rs index 4fbf480d0bc..ba85cc27746 100644 --- a/packages/rs-drive/src/drive/initialization/v1/mod.rs +++ b/packages/rs-drive/src/drive/initialization/v1/mod.rs @@ -4,6 +4,9 @@ use crate::drive::balances::TOTAL_TOKEN_SUPPLIES_STORAGE_KEY; use crate::util::batch::GroveDbOpBatch; use crate::drive::system::misc_path_vec; +use crate::drive::tokens::{ + tokens_root_path_vec, TOKEN_BALANCES_KEY, TOKEN_IDENTITY_INFO_KEY, TOKEN_STATUS_INFO_KEY, +}; use crate::drive::{Drive, RootTree}; use crate::error::Error; use crate::util::batch::grovedb_op_batch::GroveDbOpBatchV0Methods; @@ -55,6 +58,24 @@ impl Drive { Element::empty_tree(), ); + batch.add_insert( + tokens_root_path_vec(), + vec![TOKEN_BALANCES_KEY], + Element::empty_big_sum_tree(), + ); + + batch.add_insert( + tokens_root_path_vec(), + vec![TOKEN_IDENTITY_INFO_KEY], + Element::empty_tree(), + ); + + batch.add_insert( + tokens_root_path_vec(), + vec![TOKEN_STATUS_INFO_KEY], + Element::empty_tree(), + ); + Ok(()) } } diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index 1f8a8f8dc58..4f71c6346f5 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -49,10 +49,14 @@ pub(crate) mod prefunded_specialized_balances; pub mod votes; /// Group module +#[cfg(any(feature = "server", feature = "verify"))] pub mod group; #[cfg(feature = "server")] mod shared; -mod tokens; + +/// Token module +#[cfg(any(feature = "server", feature = "verify"))] +pub mod tokens; #[cfg(feature = "server")] use crate::cache::DriveCache; diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/estimation_costs/for_prefunded_specialized_balance_update/v0/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/estimation_costs/for_prefunded_specialized_balance_update/v0/mod.rs index 64cdef76917..5e7925cf1d7 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/estimation_costs/for_prefunded_specialized_balance_update/v0/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/estimation_costs/for_prefunded_specialized_balance_update/v0/mod.rs @@ -35,6 +35,9 @@ impl Drive { 1, SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 1, }, None, diff --git a/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract/v0/mod.rs b/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract/v0/mod.rs index 3b3969df79c..32d25eae456 100644 --- a/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract/v0/mod.rs +++ b/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract/v0/mod.rs @@ -65,6 +65,9 @@ impl Drive { 1, SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 2, }, None, diff --git a/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded/v0/mod.rs b/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded/v0/mod.rs index 0559137ade7..aff3c4d5fc2 100644 --- a/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded/v0/mod.rs +++ b/packages/rs-drive/src/drive/shared/shared_estimation_costs/add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded/v0/mod.rs @@ -56,6 +56,9 @@ impl Drive { 1, SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 2, }, None, diff --git a/packages/rs-drive/src/drive/system/estimation_costs/for_total_system_credits_update/v0/mod.rs b/packages/rs-drive/src/drive/system/estimation_costs/for_total_system_credits_update/v0/mod.rs index 98aaed604c0..40f013d0104 100644 --- a/packages/rs-drive/src/drive/system/estimation_costs/for_total_system_credits_update/v0/mod.rs +++ b/packages/rs-drive/src/drive/system/estimation_costs/for_total_system_credits_update/v0/mod.rs @@ -39,6 +39,9 @@ impl Drive { 12, // about 32 + 1 + 1 / 3 SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 2, }, None, diff --git a/packages/rs-drive/src/drive/tokens/apply_status/v0/mod.rs b/packages/rs-drive/src/drive/tokens/apply_status/v0/mod.rs index 6b2e229d3ea..d7efeb25e47 100644 --- a/packages/rs-drive/src/drive/tokens/apply_status/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/apply_status/v0/mod.rs @@ -1,4 +1,4 @@ -use crate::drive::tokens::{token_path, TOKEN_IDENTITY_INFO_KEY}; +use crate::drive::tokens::token_statuses_root_path; use crate::drive::Drive; use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; @@ -85,10 +85,18 @@ impl Drive { let token_status_bytes = status.serialize_consume_to_bytes()?; + if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { + Self::add_estimation_costs_for_token_status_infos( + token_id, + estimated_costs_only_with_layer_info, + &platform_version.drive, + )?; + } + self.batch_insert( PathKeyElementInfo::PathFixedSizeKeyRefElement::<2>(( - token_path(&token_id), - &[TOKEN_IDENTITY_INFO_KEY], + token_statuses_root_path(), + token_id.as_slice(), Element::Item(token_status_bytes, None), )), &mut drive_operations, diff --git a/packages/rs-drive/src/drive/tokens/balance/add_to_previous_token_balance/v0/mod.rs b/packages/rs-drive/src/drive/tokens/balance/add_to_previous_token_balance/v0/mod.rs index 5d3a0ebac7e..4b81e534d46 100644 --- a/packages/rs-drive/src/drive/tokens/balance/add_to_previous_token_balance/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/balance/add_to_previous_token_balance/v0/mod.rs @@ -84,7 +84,6 @@ impl Drive { if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { Self::add_estimation_costs_for_token_balances( token_id, - false, estimated_costs_only_with_layer_info, &platform_version.drive, )?; diff --git a/packages/rs-drive/src/drive/tokens/balance/remove_from_identity_token_balance/v0/mod.rs b/packages/rs-drive/src/drive/tokens/balance/remove_from_identity_token_balance/v0/mod.rs index 4367a872a80..d6428c10b2f 100644 --- a/packages/rs-drive/src/drive/tokens/balance/remove_from_identity_token_balance/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/balance/remove_from_identity_token_balance/v0/mod.rs @@ -82,7 +82,6 @@ impl Drive { if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { Self::add_estimation_costs_for_token_balances( token_id, - false, estimated_costs_only_with_layer_info, &platform_version.drive, )?; diff --git a/packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/mod.rs b/packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/mod.rs new file mode 100644 index 00000000000..8799421a9db --- /dev/null +++ b/packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/mod.rs @@ -0,0 +1,42 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use dpp::balances::total_tokens_balance::TotalTokensBalance; +use dpp::version::drive_versions::DriveVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Calculates the total credits balance. + /// + /// This function verifies that the sum tree identity credits + pool credits + refunds are equal to the total credits in the system. + /// + /// # Arguments + /// + /// * `transaction` - A `TransactionArg` object representing the transaction to be used for calculating the total credits balance. + /// * `drive_version` - A `DriveVersion` object specifying the version of the Drive. + /// + /// # Returns + /// + /// * `Result` - If successful, returns a `TotalTokensBalance` object representing the total tokens balance. + /// If an error occurs during the calculation, returns an `Error`. + /// + /// # Errors + /// + /// This function will return an error if the version of the Drive is unknown. + pub fn calculate_total_tokens_balance( + &self, + transaction: TransactionArg, + drive_version: &DriveVersion, + ) -> Result { + match drive_version.methods.token.calculate_total_tokens_balance { + 0 => self.calculate_total_tokens_balance_v0(transaction, drive_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "calculate_total_tokens_balance".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/v0/mod.rs b/packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/v0/mod.rs new file mode 100644 index 00000000000..6f312692557 --- /dev/null +++ b/packages/rs-drive/src/drive/tokens/calculate_total_tokens_balance/v0/mod.rs @@ -0,0 +1,47 @@ +use crate::drive::balances::TOTAL_TOKEN_SUPPLIES_STORAGE_KEY; +use crate::drive::system::misc_path; +use crate::drive::tokens::token_balances_root_path; +use crate::drive::{Drive, RootTree}; +use crate::error::Error; +use crate::util::grove_operations::DirectQueryType; +use dpp::balances::total_tokens_balance::TotalTokensBalance; +use dpp::version::drive_versions::DriveVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Verify that the sum tree identity credits + pool credits + refunds are equal to the + /// Total credits in the system + #[inline(always)] + pub(super) fn calculate_total_tokens_balance_v0( + &self, + transaction: TransactionArg, + drive_version: &DriveVersion, + ) -> Result { + let mut drive_operations = vec![]; + let path_holding_total_credits = misc_path(); + let total_tokens_in_platform = self.grove_get_big_sum_tree_total_value( + (&path_holding_total_credits).into(), + TOTAL_TOKEN_SUPPLIES_STORAGE_KEY, + DirectQueryType::StatefulDirectQuery, + transaction, + &mut drive_operations, + drive_version, + )?; + + let tokens_balances_path = token_balances_root_path(); + + let total_identity_token_balances = self.grove_get_big_sum_tree_total_value( + (&tokens_balances_path).into(), + Into::<&[u8; 1]>::into(RootTree::Balances), + DirectQueryType::StatefulDirectQuery, + transaction, + &mut drive_operations, + drive_version, + )?; + + Ok(TotalTokensBalance { + total_tokens_in_platform, + total_identity_token_balances, + }) + } +} diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/mod.rs index d4eb0bff2ed..fcce3e3dff7 100644 --- a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/mod.rs +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/mod.rs @@ -9,24 +9,28 @@ use grovedb::EstimatedLayerInformation; use std::collections::HashMap; impl Drive { - /// Adds estimation costs for token balance changes. + /// Adds estimation costs for token balance changes based on the provided drive version. /// - /// It operates on the provided HashMap, `estimated_costs_only_with_layer_info`, and adds - /// new entries to it, representing the estimated costs for different layers of the balance tree. + /// This method updates the `estimated_costs_only_with_layer_info` HashMap with entries + /// representing the estimated costs for different layers of the balance tree. The method + /// adjusts its behavior depending on the provided `drive_version`, allowing it to support + /// different versioned implementations for cost estimation. /// /// # Parameters - /// - `estimated_costs_only_with_layer_info`: A mutable reference to a HashMap storing - /// the `KeyInfoPath` and `EstimatedLayerInformation`. + /// - `token_id`: A 32-byte identifier for the token whose balance changes are being estimated. + /// - `estimated_costs_only_with_layer_info`: A mutable reference to a HashMap that holds + /// `KeyInfoPath` and `EstimatedLayerInformation` for each token balance layer. + /// - `drive_version`: The version of the drive to determine which estimation logic to apply. /// /// # Returns - /// - `Ok(())` if successful. - /// - `Err(DriveError::UnknownVersionMismatch)` if the method version doesn't match any known versions. + /// - `Ok(())` if the operation is successful. + /// - `Err(DriveError::UnknownVersionMismatch)` if the provided `drive_version` does not match + /// any known supported versions. /// /// # Errors - /// This function will return an error if the method version doesn't match any known versions. + /// This function will return an error if the provided `drive_version` does not match a known version. pub(crate) fn add_estimation_costs_for_token_balances( token_id: [u8; 32], - with_info_tree: bool, estimated_costs_only_with_layer_info: &mut HashMap, drive_version: &DriveVersion, ) -> Result<(), Error> { @@ -39,7 +43,6 @@ impl Drive { 0 => { Self::add_estimation_costs_for_token_balances_v0( token_id, - with_info_tree, estimated_costs_only_with_layer_info, ); Ok(()) diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/v0/mod.rs index 2400e5de715..cf9611d800c 100644 --- a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_balances/v0/mod.rs @@ -7,11 +7,9 @@ use grovedb::EstimatedLayerCount::{EstimatedLevel, PotentiallyAtMaxElements}; use grovedb::EstimatedLayerSizes::{AllItems, AllSubtrees}; use grovedb::{EstimatedLayerInformation, TreeType}; -use crate::drive::tokens::{ - token_balances_path, token_identity_infos_path, token_path, tokens_root_path, -}; +use crate::drive::tokens::{token_balances_path, token_balances_root_path, tokens_root_path}; use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; -use grovedb::EstimatedSumTrees::{AllSumTrees, NoSumTrees, SomeSumTrees}; +use grovedb::EstimatedSumTrees::{AllBigSumTrees, AllSumTrees, NoSumTrees}; use std::collections::HashMap; pub const ESTIMATED_TOKEN_INFO_SIZE_BYTES: u32 = 256; @@ -52,7 +50,6 @@ impl Drive { /// ``` pub(super) fn add_estimation_costs_for_token_balances_v0( token_id: [u8; 32], - with_info_tree: bool, estimated_costs_only_with_layer_info: &mut HashMap, ) { // we have constructed the top layer so contract/documents tree are at the top @@ -76,53 +73,19 @@ impl Drive { KeyInfoPath::from_known_path(tokens_root_path()), EstimatedLayerInformation { tree_type: TreeType::NormalTree, - estimated_layer_count: EstimatedLevel(10, false), // We estimate that on average we need to update 10 nodes - estimated_layer_sizes: AllSubtrees(DEFAULT_HASH_SIZE_U8, NoSumTrees, None), + estimated_layer_count: EstimatedLevel(0, false), // this should be at the top + estimated_layer_sizes: AllSubtrees(1, AllBigSumTrees, None), }, ); - if with_info_tree { - estimated_costs_only_with_layer_info.insert( - KeyInfoPath::from_known_path(token_path(&token_id)), - EstimatedLayerInformation { - tree_type: TreeType::NormalTree, - estimated_layer_count: EstimatedLevel(1, false), - estimated_layer_sizes: AllSubtrees( - 1, - SomeSumTrees { - sum_trees_weight: 1, - non_sum_trees_weight: 1, - }, - None, - ), - }, - ); - } else { - estimated_costs_only_with_layer_info.insert( - KeyInfoPath::from_known_path(token_path(&token_id)), - EstimatedLayerInformation { - tree_type: TreeType::NormalTree, - estimated_layer_count: EstimatedLevel(0, false), - estimated_layer_sizes: AllSubtrees(1, AllSumTrees, None), - }, - ); - } - - if with_info_tree { - // there is one tree for the root path - estimated_costs_only_with_layer_info.insert( - KeyInfoPath::from_known_path(token_identity_infos_path(&token_id)), - EstimatedLayerInformation { - tree_type: TreeType::NormalTree, - estimated_layer_count: PotentiallyAtMaxElements, - estimated_layer_sizes: AllItems( - DEFAULT_HASH_SIZE_U8, - ESTIMATED_TOKEN_INFO_SIZE_BYTES, - None, - ), - }, - ); - } + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(token_balances_root_path()), + EstimatedLayerInformation { + tree_type: TreeType::BigSumTree, + estimated_layer_count: EstimatedLevel(10, false), // we can estimate 10 levels deep + estimated_layer_sizes: AllSubtrees(DEFAULT_HASH_SIZE_U8, AllSumTrees, None), + }, + ); // this is where the balances are estimated_costs_only_with_layer_info.insert( diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/mod.rs new file mode 100644 index 00000000000..a5225fa37be --- /dev/null +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/mod.rs @@ -0,0 +1,57 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use dpp::version::drive_versions::DriveVersion; +use grovedb::batch::KeyInfoPath; +use grovedb::EstimatedLayerInformation; +use std::collections::HashMap; + +impl Drive { + /// Adds estimation costs for token identity infos changes based on the provided drive version. + /// + /// This method updates the `estimated_costs_only_with_layer_info` HashMap with entries + /// representing the estimated costs for different layers of the balance tree. The method + /// adjusts its behavior depending on the provided `drive_version`, allowing it to support + /// different versioned implementations for cost estimation. + /// + /// # Parameters + /// - `token_id`: A 32-byte identifier for the token whose balance changes are being estimated. + /// - `estimated_costs_only_with_layer_info`: A mutable reference to a HashMap that holds + /// `KeyInfoPath` and `EstimatedLayerInformation` for each token balance layer. + /// - `drive_version`: The version of the drive to determine which estimation logic to apply. + /// + /// # Returns + /// - `Ok(())` if the operation is successful. + /// - `Err(DriveError::UnknownVersionMismatch)` if the provided `drive_version` does not match + /// any known supported versions. + /// + /// # Errors + /// This function will return an error if the provided `drive_version` does not match a known version. + pub(crate) fn add_estimation_costs_for_token_identity_infos( + token_id: [u8; 32], + estimated_costs_only_with_layer_info: &mut HashMap, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match drive_version + .methods + .identity + .cost_estimation + .for_token_identity_infos + { + 0 => { + Self::add_estimation_costs_for_token_identity_infos_v0( + token_id, + estimated_costs_only_with_layer_info, + ); + Ok(()) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_estimation_costs_for_token_identity_infos".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/v0/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/v0/mod.rs new file mode 100644 index 00000000000..70b2caae362 --- /dev/null +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_identity_infos/v0/mod.rs @@ -0,0 +1,81 @@ +use crate::drive::Drive; + +use grovedb::batch::KeyInfoPath; +use grovedb::EstimatedLayerCount::{EstimatedLevel, PotentiallyAtMaxElements}; +use grovedb::EstimatedLayerSizes::{AllItems, AllSubtrees}; +use grovedb::{EstimatedLayerInformation, TreeType}; + +use crate::drive::tokens::{ + token_identity_infos_path, token_identity_infos_root_path, tokens_root_path, +}; +use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; +use grovedb::EstimatedSumTrees::{NoSumTrees, SomeSumTrees}; +use std::collections::HashMap; + +pub const ESTIMATED_TOKEN_INFO_SIZE_BYTES: u32 = 32; + +impl Drive { + pub(super) fn add_estimation_costs_for_token_identity_infos_v0( + token_id: [u8; 32], + estimated_costs_only_with_layer_info: &mut HashMap, + ) { + // we have constructed the top layer so contract/documents tree are at the top + // since balance will be on layer 3 (level 2 on left then left) + // updating will mean we will update: + // 1 normal tree (token balances) + // 1 normal tree (identities) + // 1 normal tree (contract/documents) + // hence we should give an equal weight to both + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path([]), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(2, false), + estimated_layer_sizes: AllSubtrees(1, NoSumTrees, None), + }, + ); + + // there is one tree for the root path + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(tokens_root_path()), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(1, false), // this should be at the top + estimated_layer_sizes: AllSubtrees( + 1, + SomeSumTrees { + sum_trees_weight: 0, + big_sum_trees_weight: 1, + count_trees_weight: 0, + count_sum_trees_weight: 0, + non_sum_trees_weight: 1, + }, + None, + ), + }, + ); + + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(token_identity_infos_root_path()), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(10, false), // we can estimate 10 levels deep + estimated_layer_sizes: AllSubtrees(DEFAULT_HASH_SIZE_U8, NoSumTrees, None), + }, + ); + + // this is where the balances are + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(token_identity_infos_path(&token_id)), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: AllItems( + DEFAULT_HASH_SIZE_U8, + ESTIMATED_TOKEN_INFO_SIZE_BYTES, + None, + ), + }, + ); + } +} diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/mod.rs new file mode 100644 index 00000000000..c72eb62ba47 --- /dev/null +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/mod.rs @@ -0,0 +1,57 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use dpp::version::drive_versions::DriveVersion; +use grovedb::batch::KeyInfoPath; +use grovedb::EstimatedLayerInformation; +use std::collections::HashMap; + +impl Drive { + /// Adds estimation costs for token status infos changes based on the provided drive version. + /// + /// This method updates the `estimated_costs_only_with_layer_info` HashMap with entries + /// representing the estimated costs for different layers of the balance tree. The method + /// adjusts its behavior depending on the provided `drive_version`, allowing it to support + /// different versioned implementations for cost estimation. + /// + /// # Parameters + /// - `token_id`: A 32-byte identifier for the token whose balance changes are being estimated. + /// - `estimated_costs_only_with_layer_info`: A mutable reference to a HashMap that holds + /// `KeyInfoPath` and `EstimatedLayerInformation` for each token balance layer. + /// - `drive_version`: The version of the drive to determine which estimation logic to apply. + /// + /// # Returns + /// - `Ok(())` if the operation is successful. + /// - `Err(DriveError::UnknownVersionMismatch)` if the provided `drive_version` does not match + /// any known supported versions. + /// + /// # Errors + /// This function will return an error if the provided `drive_version` does not match a known version. + pub(crate) fn add_estimation_costs_for_token_status_infos( + token_id: [u8; 32], + estimated_costs_only_with_layer_info: &mut HashMap, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match drive_version + .methods + .identity + .cost_estimation + .for_token_identity_infos + { + 0 => { + Self::add_estimation_costs_for_token_status_infos_v0( + token_id, + estimated_costs_only_with_layer_info, + ); + Ok(()) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_estimation_costs_for_token_status_infos".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/v0/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/v0/mod.rs new file mode 100644 index 00000000000..1933c9fd3fe --- /dev/null +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_status_infos/v0/mod.rs @@ -0,0 +1,69 @@ +use crate::drive::Drive; + +use grovedb::batch::KeyInfoPath; +use grovedb::EstimatedLayerCount::EstimatedLevel; +use grovedb::EstimatedLayerSizes::{AllItems, AllSubtrees}; +use grovedb::{EstimatedLayerInformation, TreeType}; + +use crate::drive::tokens::{token_statuses_root_path, tokens_root_path}; +use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; +use grovedb::EstimatedSumTrees::{NoSumTrees, SomeSumTrees}; +use std::collections::HashMap; + +pub const ESTIMATED_TOKEN_STATUS_INFO_SIZE_BYTES: u32 = 32; + +impl Drive { + pub(super) fn add_estimation_costs_for_token_status_infos_v0( + token_id: [u8; 32], + estimated_costs_only_with_layer_info: &mut HashMap, + ) { + // we have constructed the top layer so contract/documents tree are at the top + // since balance will be on layer 3 (level 2 on left then left) + // updating will mean we will update: + // 1 normal tree (token balances) + // 1 normal tree (identities) + // 1 normal tree (contract/documents) + // hence we should give an equal weight to both + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path([]), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(2, false), + estimated_layer_sizes: AllSubtrees(1, NoSumTrees, None), + }, + ); + + // there is one tree for the root path + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(tokens_root_path()), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(1, false), // this should be at the top + estimated_layer_sizes: AllSubtrees( + 1, + SomeSumTrees { + sum_trees_weight: 0, + big_sum_trees_weight: 1, + count_trees_weight: 0, + count_sum_trees_weight: 0, + non_sum_trees_weight: 1, + }, + None, + ), + }, + ); + + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(token_statuses_root_path()), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(10, false), // we can estimate 10 levels deep + estimated_layer_sizes: AllItems( + DEFAULT_HASH_SIZE_U8, + ESTIMATED_TOKEN_STATUS_INFO_SIZE_BYTES, + None, + ), + }, + ); + } +} diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_total_supply/v0/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_total_supply/v0/mod.rs index dca4ebe18e0..7f022ceec82 100644 --- a/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_total_supply/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/for_token_total_supply/v0/mod.rs @@ -68,6 +68,9 @@ impl Drive { 17, SomeSumTrees { sum_trees_weight: 1, + big_sum_trees_weight: 0, + count_trees_weight: 0, + count_sum_trees_weight: 0, non_sum_trees_weight: 3, }, None, diff --git a/packages/rs-drive/src/drive/tokens/estimated_costs/mod.rs b/packages/rs-drive/src/drive/tokens/estimated_costs/mod.rs index d9e96b7e250..8028de53755 100644 --- a/packages/rs-drive/src/drive/tokens/estimated_costs/mod.rs +++ b/packages/rs-drive/src/drive/tokens/estimated_costs/mod.rs @@ -1,2 +1,11 @@ +/// Module for handling operations related to token balances. pub mod for_token_balances; + +/// Module for handling operations related to token total supply. pub mod for_token_total_supply; + +/// Module for handling operations related to token identity information. +pub mod for_token_identity_infos; + +/// Module for handling operations related to token status information. +pub mod for_token_status_infos; diff --git a/packages/rs-drive/src/drive/tokens/freeze/v0/mod.rs b/packages/rs-drive/src/drive/tokens/freeze/v0/mod.rs index 3df4bb38f1d..343cf6accc4 100644 --- a/packages/rs-drive/src/drive/tokens/freeze/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/freeze/v0/mod.rs @@ -88,9 +88,8 @@ impl Drive { ) -> Result, Error> { let mut drive_operations = vec![]; if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { - Self::add_estimation_costs_for_token_balances( + Self::add_estimation_costs_for_token_identity_infos( token_id.to_buffer(), - true, estimated_costs_only_with_layer_info, &platform_version.drive, )?; diff --git a/packages/rs-drive/src/drive/tokens/mod.rs b/packages/rs-drive/src/drive/tokens/mod.rs index be8a53dee1b..e54e92e7974 100644 --- a/packages/rs-drive/src/drive/tokens/mod.rs +++ b/packages/rs-drive/src/drive/tokens/mod.rs @@ -1,81 +1,142 @@ use crate::drive::RootTree; +/// Handles operations related to adding transaction history. mod add_transaction_history_operations; + +/// Defines logic for applying status updates within the system. pub mod apply_status; + +/// Manages operations related to balance handling. pub mod balance; + +/// Implements functionality for burning tokens. pub mod burn; + +/// Computes estimated costs for various operations. pub mod estimated_costs; + +/// Manages freezing operations in the system. pub mod freeze; + +/// Contains informational utility functions. mod info; + +/// Implements minting operations for creating new tokens. pub mod mint; + +/// Manages system-level operations and utilities. pub mod system; + +/// Handles transfer operations, including token movement. pub mod transfer; + +/// Manages unfreezing operations within the system. pub mod unfreeze; +/// Calculates the total token balance across all accounts. +pub mod calculate_total_tokens_balance; + +/// Key for accessing token status information. pub const TOKEN_STATUS_INFO_KEY: u8 = 96; -pub const TOKEN_IDENTITY_INFO_KEY: u8 = 64; + +/// Key for accessing token identity information tree. +pub const TOKEN_IDENTITY_INFO_KEY: u8 = 160; + +/// Key for accessing token balances tree. pub const TOKEN_BALANCES_KEY: u8 = 128; /// The path for the balances tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn tokens_root_path() -> [&'static [u8]; 1] { +pub fn tokens_root_path() -> [&'static [u8]; 1] { [Into::<&[u8; 1]>::into(RootTree::Tokens)] } /// The path for the balances tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn tokens_root_path_vec() -> Vec> { +pub fn tokens_root_path_vec() -> Vec> { vec![Into::<&[u8; 1]>::into(RootTree::Tokens).to_vec()] } -/// The path for the token tree +/// The root path of token balances tree, this refers to a big sum tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn token_path(token_id: &[u8; 32]) -> [&[u8]; 2] { - [Into::<&[u8; 1]>::into(RootTree::Tokens), token_id] +pub fn token_balances_root_path() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::Tokens), + &[TOKEN_BALANCES_KEY], + ] } -/// The path for the token tree +/// The root path of token balances tree, this refers to a big sum tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn token_path_vec(token_id: [u8; 32]) -> Vec> { - vec![vec![RootTree::Tokens as u8], token_id.to_vec()] +pub fn token_balances_root_path_vec() -> Vec> { + vec![vec![RootTree::Tokens as u8], vec![TOKEN_BALANCES_KEY]] +} +/// Returns the root path for token identity information as a fixed-size array of byte slices. +#[cfg(any(feature = "server", feature = "verify"))] +pub fn token_identity_infos_root_path() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::Tokens), + &[TOKEN_IDENTITY_INFO_KEY], + ] +} + +/// Returns the root path for token identity information as a vector of byte vectors. +#[cfg(any(feature = "server", feature = "verify"))] +pub fn token_identity_infos_root_path_vec() -> Vec> { + vec![vec![RootTree::Tokens as u8], vec![TOKEN_IDENTITY_INFO_KEY]] +} + +/// Returns the root path for token statuses as a fixed-size array of byte slices. +#[cfg(any(feature = "server", feature = "verify"))] +pub fn token_statuses_root_path() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::Tokens), + &[TOKEN_STATUS_INFO_KEY], + ] +} + +/// Returns the root path for token statuses as a vector of byte vectors. +#[cfg(any(feature = "server", feature = "verify"))] +pub fn token_statuses_root_path_vec() -> Vec> { + vec![vec![RootTree::Tokens as u8], vec![TOKEN_STATUS_INFO_KEY]] } /// The path for the token balances tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn token_balances_path(token_id: &[u8; 32]) -> [&[u8]; 3] { +pub fn token_balances_path(token_id: &[u8; 32]) -> [&[u8]; 3] { [ Into::<&[u8; 1]>::into(RootTree::Tokens), - token_id, &[TOKEN_BALANCES_KEY], + token_id, ] } /// The path for the token balances tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn token_balances_path_vec(token_id: [u8; 32]) -> Vec> { +pub fn token_balances_path_vec(token_id: [u8; 32]) -> Vec> { vec![ vec![RootTree::Tokens as u8], - token_id.to_vec(), vec![TOKEN_BALANCES_KEY], + token_id.to_vec(), ] } /// The path for the token info tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn token_identity_infos_path(token_id: &[u8; 32]) -> [&[u8]; 3] { +pub fn token_identity_infos_path(token_id: &[u8; 32]) -> [&[u8]; 3] { [ Into::<&[u8; 1]>::into(RootTree::Tokens), - token_id, &[TOKEN_IDENTITY_INFO_KEY], + token_id, ] } /// The path for the token info tree #[cfg(any(feature = "server", feature = "verify"))] -pub(crate) fn token_identity_infos_path_vec(token_id: [u8; 32]) -> Vec> { +pub fn token_identity_infos_path_vec(token_id: [u8; 32]) -> Vec> { vec![ vec![RootTree::Tokens as u8], - token_id.to_vec(), vec![TOKEN_IDENTITY_INFO_KEY], + token_id.to_vec(), ] } diff --git a/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs index 3aa28799baa..686591211a8 100644 --- a/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs @@ -9,9 +9,8 @@ use dpp::block::block_info::BlockInfo; use dpp::fee::fee_result::FeeResult; use dpp::version::PlatformVersion; use grovedb::batch::{KeyInfoPath, QualifiedGroveDbOp}; -use grovedb::Element::Item; +use grovedb::Element::SumItem; use grovedb::{EstimatedLayerInformation, TransactionArg}; -use integer_encoding::VarInt; use std::collections::HashMap; impl Drive { @@ -115,23 +114,27 @@ impl Drive { )?; if let Some(total_token_supply_in_platform) = total_token_supply_in_platform { - let new_total = - total_token_supply_in_platform - .checked_add(amount) - .ok_or(Error::Drive(DriveError::CriticalCorruptedState( - "trying to add an amount that would underflow total supply", - )))?; + let new_total = (total_token_supply_in_platform as i64) + .checked_add(amount as i64) + .ok_or(Error::Drive(DriveError::CriticalCorruptedState( + "trying to add an amount that would underflow total supply", + )))?; let replace_op = QualifiedGroveDbOp::replace_op( path_holding_total_token_supply_vec, token_id.to_vec(), - Item(new_total.encode_var_vec(), None), + SumItem(new_total, None), ); drive_operations.push(GroveOperation(replace_op)); } else if allow_first_mint { + if amount > i64::MAX as u64 { + return Err(Error::Drive(DriveError::CriticalCorruptedState( + "amount is over max allowed in Sum Item (i64::Max)", + ))); + } let insert_op = QualifiedGroveDbOp::insert_only_op( path_holding_total_token_supply_vec, token_id.to_vec(), - Item(amount.encode_var_vec(), None), + SumItem(amount as i64, None), ); drive_operations.push(GroveOperation(insert_op)); } else { diff --git a/packages/rs-drive/src/drive/tokens/system/create_token_trees/mod.rs b/packages/rs-drive/src/drive/tokens/system/create_token_trees/mod.rs index ce7ebc2c376..49656bb930c 100644 --- a/packages/rs-drive/src/drive/tokens/system/create_token_trees/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/create_token_trees/mod.rs @@ -13,7 +13,7 @@ use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; impl Drive { - /// Adds a identity by inserting a new identity subtree structure to the `Identities` subtree. + /// Adds an identity by inserting a new identity subtree structure to the `Identities` subtree. pub fn create_token_trees( &self, token_id: [u8; 32], diff --git a/packages/rs-drive/src/drive/tokens/system/create_token_trees/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/create_token_trees/v0/mod.rs index e60f48dfbdd..e9b8a688cde 100644 --- a/packages/rs-drive/src/drive/tokens/system/create_token_trees/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/create_token_trees/v0/mod.rs @@ -1,7 +1,6 @@ use crate::drive::balances::total_tokens_root_supply_path; use crate::drive::tokens::{ - token_path, tokens_root_path, TOKEN_BALANCES_KEY, TOKEN_IDENTITY_INFO_KEY, - TOKEN_STATUS_INFO_KEY, + token_balances_root_path, token_identity_infos_root_path, token_statuses_root_path, }; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -9,7 +8,7 @@ use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; use crate::util::grove_operations::{BatchInsertApplyType, BatchInsertTreeApplyType, QueryTarget}; use crate::util::object_size_info::PathKeyElementInfo; -use crate::util::object_size_info::PathKeyInfo::PathFixedSizeKey; +use crate::util::object_size_info::PathKeyInfo::PathFixedSizeKeyRef; use dpp::block::block_info::BlockInfo; use dpp::fee::fee_result::FeeResult; use dpp::serialization::PlatformSerializable; @@ -115,7 +114,6 @@ impl Drive { ) -> Result, Error> { let mut batch_operations: Vec = vec![]; - // Decide if we're doing a stateful or stateless insert for cost estimation let non_sum_tree_apply_type = if estimated_costs_only_with_layer_info.is_none() { BatchInsertTreeApplyType::StatefulBatchInsertTree } else { @@ -139,7 +137,7 @@ impl Drive { BatchInsertTreeApplyType::StatefulBatchInsertTree } else { BatchInsertTreeApplyType::StatelessBatchInsertTree { - in_tree_type: TreeType::NormalTree, + in_tree_type: TreeType::BigSumTree, tree_type: TreeType::SumTree, flags_len: 0, } @@ -147,10 +145,10 @@ impl Drive { // Insert an empty tree for this token if it doesn't exist let inserted = self.batch_insert_empty_tree_if_not_exists( - PathFixedSizeKey((tokens_root_path(), token_id.to_vec())), - false, - None, // No storage flags - non_sum_tree_apply_type, + PathFixedSizeKeyRef::<2>((token_balances_root_path(), token_id.as_slice())), + TreeType::SumTree, + None, + token_balance_tree_apply_type, transaction, previous_batch_operations, &mut batch_operations, @@ -160,15 +158,15 @@ impl Drive { if !inserted && !allow_already_exists { // The token root already exists. Depending on your logic, this might be allowed or should be treated as an error. return Err(Error::Drive(DriveError::CorruptedDriveState( - "token root tree already exists".to_string(), + "token balance root tree already exists".to_string(), ))); } let inserted = self.batch_insert_empty_tree_if_not_exists( - PathFixedSizeKey((token_path(&token_id), vec![TOKEN_BALANCES_KEY])), - true, + PathFixedSizeKeyRef::<2>((token_identity_infos_root_path(), token_id.as_slice())), + TreeType::NormalTree, None, - token_balance_tree_apply_type, + non_sum_tree_apply_type, transaction, &mut None, &mut batch_operations, @@ -187,8 +185,8 @@ impl Drive { let inserted = self.batch_insert_if_not_exists( PathKeyElementInfo::PathFixedSizeKeyRefElement::<2>(( - token_path(&token_id), - &[TOKEN_IDENTITY_INFO_KEY], + token_statuses_root_path(), + token_id.as_slice(), Element::Item(token_status_bytes, None), )), item_apply_type, @@ -204,42 +202,19 @@ impl Drive { ))); } - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathFixedSizeKey((token_path(&token_id), vec![TOKEN_STATUS_INFO_KEY])), - false, - None, - non_sum_tree_apply_type, - transaction, - &mut None, - &mut batch_operations, - &platform_version.drive, - )?; - - if !inserted && !allow_already_exists { - // The token root already exists. Depending on your logic, this might be allowed or should be treated as an error. - return Err(Error::Drive(DriveError::CorruptedDriveState( - "token info tree already exists".to_string(), - ))); - } - - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathFixedSizeKey((total_tokens_root_supply_path(), token_id.to_vec())), - false, - None, - non_sum_tree_apply_type, + self.batch_insert_sum_item_if_not_exists( + PathKeyElementInfo::PathFixedSizeKeyRefElement::<2>(( + total_tokens_root_supply_path(), + token_id.as_slice(), + Element::SumItem(0, None), + )), + !allow_already_exists, + item_apply_type, transaction, - &mut None, &mut batch_operations, &platform_version.drive, )?; - if !inserted && !allow_already_exists { - // The token root already exists. Depending on your logic, this might be allowed or should be treated as an error. - return Err(Error::Drive(DriveError::CorruptedDriveState( - "sum tree tree already exists".to_string(), - ))); - } - Ok(batch_operations) } } diff --git a/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs index 311c3254c8d..1bdbe38ebb5 100644 --- a/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs @@ -9,9 +9,8 @@ use dpp::block::block_info::BlockInfo; use dpp::fee::fee_result::FeeResult; use dpp::version::PlatformVersion; use grovedb::batch::QualifiedGroveDbOp; -use grovedb::Element::Item; +use grovedb::Element::SumItem; use grovedb::{batch::KeyInfoPath, EstimatedLayerInformation, TransactionArg}; -use integer_encoding::VarInt; use std::collections::HashMap; impl Drive { @@ -120,7 +119,7 @@ impl Drive { let replace_op = QualifiedGroveDbOp::replace_op( path_holding_total_token_supply_vec, token_id.to_vec(), - Item(new_total.encode_var_vec(), None), + SumItem(new_total as i64, None), ); drive_operations.push(GroveOperation(replace_op)); diff --git a/packages/rs-drive/src/drive/tokens/unfreeze/v0/mod.rs b/packages/rs-drive/src/drive/tokens/unfreeze/v0/mod.rs index ab09dd3f73a..7e581b4b82e 100644 --- a/packages/rs-drive/src/drive/tokens/unfreeze/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/unfreeze/v0/mod.rs @@ -88,9 +88,8 @@ impl Drive { ) -> Result, Error> { let mut drive_operations = vec![]; if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { - Self::add_estimation_costs_for_token_balances( + Self::add_estimation_costs_for_token_identity_infos( token_id.to_buffer(), - true, estimated_costs_only_with_layer_info, &platform_version.drive, )?; diff --git a/packages/rs-drive/src/drive/votes/insert/contested_resource/individual_vote/register_contested_resource_identity_vote/v0/mod.rs b/packages/rs-drive/src/drive/votes/insert/contested_resource/individual_vote/register_contested_resource_identity_vote/v0/mod.rs index fa3782218f6..2a1ddacfddf 100644 --- a/packages/rs-drive/src/drive/votes/insert/contested_resource/individual_vote/register_contested_resource_identity_vote/v0/mod.rs +++ b/packages/rs-drive/src/drive/votes/insert/contested_resource/individual_vote/register_contested_resource_identity_vote/v0/mod.rs @@ -16,7 +16,7 @@ use dpp::fee::fee_result::FeeResult; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use dpp::{bincode, ProtocolError}; use grovedb::reference_path::ReferencePathType; -use grovedb::{Element, MaybeTree, TransactionArg}; +use grovedb::{Element, MaybeTree, TransactionArg, TreeType}; use platform_version::version::PlatformVersion; impl Drive { @@ -118,7 +118,7 @@ impl Drive { self.batch_insert_empty_tree_if_not_exists( PathKeyInfo::PathKey::<0>((votes_identities_path, voter_pro_tx_hash.to_vec())), - false, + TreeType::NormalTree, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, //todo this shouldn't always be stateful transaction, diff --git a/packages/rs-drive/src/drive/votes/insert/vote_poll/add_vote_poll_end_date_query_operations/v0/mod.rs b/packages/rs-drive/src/drive/votes/insert/vote_poll/add_vote_poll_end_date_query_operations/v0/mod.rs index 696b0841882..e3ac582a483 100644 --- a/packages/rs-drive/src/drive/votes/insert/vote_poll/add_vote_poll_end_date_query_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/votes/insert/vote_poll/add_vote_poll_end_date_query_operations/v0/mod.rs @@ -113,7 +113,7 @@ impl Drive { // end data in the documents batch transition self.batch_insert_empty_tree_if_not_exists( path_key_info.clone(), - false, + TreeType::NormalTree, storage_flags.as_ref(), apply_type, transaction, diff --git a/packages/rs-drive/src/fees/op.rs b/packages/rs-drive/src/fees/op.rs index ecd1c605311..e874a89b1da 100644 --- a/packages/rs-drive/src/fees/op.rs +++ b/packages/rs-drive/src/fees/op.rs @@ -9,7 +9,7 @@ use grovedb::batch::key_info::KeyInfo; use grovedb::batch::KeyInfoPath; use grovedb::element::MaxReferenceHop; use grovedb::reference_path::ReferencePathType; -use grovedb::{batch::QualifiedGroveDbOp, Element, ElementFlags}; +use grovedb::{batch::QualifiedGroveDbOp, Element, ElementFlags, TreeType}; use grovedb_costs::OperationCost; use itertools::Itertools; @@ -382,6 +382,54 @@ impl LowLevelDriveOperation { LowLevelDriveOperation::insert_for_known_path_key_element(path, key, tree) } + /// Sets `GroveOperation` for inserting an empty sum tree at the given path and key + pub fn for_known_path_key_empty_big_sum_tree( + path: Vec>, + key: Vec, + storage_flags: Option<&StorageFlags>, + ) -> Self { + let tree = match storage_flags { + Some(storage_flags) => { + Element::new_big_sum_tree_with_flags(None, storage_flags.to_some_element_flags()) + } + None => Element::empty_big_sum_tree(), + }; + + LowLevelDriveOperation::insert_for_known_path_key_element(path, key, tree) + } + + /// Sets `GroveOperation` for inserting an empty count tree at the given path and key + pub fn for_known_path_key_empty_count_tree( + path: Vec>, + key: Vec, + storage_flags: Option<&StorageFlags>, + ) -> Self { + let tree = match storage_flags { + Some(storage_flags) => { + Element::new_count_tree_with_flags(None, storage_flags.to_some_element_flags()) + } + None => Element::empty_count_tree(), + }; + + LowLevelDriveOperation::insert_for_known_path_key_element(path, key, tree) + } + + /// Sets `GroveOperation` for inserting an empty count tree at the given path and key + pub fn for_known_path_key_empty_count_sum_tree( + path: Vec>, + key: Vec, + storage_flags: Option<&StorageFlags>, + ) -> Self { + let tree = match storage_flags { + Some(storage_flags) => { + Element::new_count_sum_tree_with_flags(None, storage_flags.to_some_element_flags()) + } + None => Element::new_count_sum_tree(None), + }; + + LowLevelDriveOperation::insert_for_known_path_key_element(path, key, tree) + } + /// Sets `GroveOperation` for inserting an empty tree at the given path and key pub fn for_estimated_path_key_empty_tree( path: KeyInfoPath, @@ -486,6 +534,37 @@ impl LowLevelDriveOperation { } } +pub trait LowLevelDriveOperationTreeTypeConverter { + /// Sets `GroveOperation` for inserting an empty tree at the given path and key + fn empty_tree_operation_for_known_path_key( + &self, + path: Vec>, + key: Vec, + storage_flags: Option<&StorageFlags>, + ) -> LowLevelDriveOperation; +} + +impl LowLevelDriveOperationTreeTypeConverter for TreeType { + /// Sets `GroveOperation` for inserting an empty tree at the given path and key + fn empty_tree_operation_for_known_path_key( + &self, + path: Vec>, + key: Vec, + storage_flags: Option<&StorageFlags>, + ) -> LowLevelDriveOperation { + let element_flags = storage_flags.map(|storage_flags| storage_flags.to_element_flags()); + let element = match self { + TreeType::NormalTree => Element::empty_tree_with_flags(element_flags), + TreeType::SumTree => Element::empty_sum_tree_with_flags(element_flags), + TreeType::BigSumTree => Element::empty_big_sum_tree_with_flags(element_flags), + TreeType::CountTree => Element::empty_count_tree_with_flags(element_flags), + TreeType::CountSumTree => Element::empty_count_sum_tree_with_flags(element_flags), + }; + + LowLevelDriveOperation::insert_for_known_path_key_element(path, key, element) + } +} + /// Drive cost trait pub trait DriveCost { /// Ephemeral cost diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs index a4f630e691e..5425de9741b 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs @@ -10,7 +10,7 @@ use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; use dpp::version::drive_versions::DriveVersion; -use grovedb::TransactionArg; +use grovedb::{TransactionArg, TreeType}; impl Drive { /// Pushes an "insert empty tree where path key does not yet exist" operation to `drive_operations`. @@ -19,7 +19,7 @@ impl Drive { pub fn batch_insert_empty_tree_if_not_exists( &self, path_key_info: PathKeyInfo, - use_sum_tree: bool, + tree_type: TreeType, storage_flags: Option<&StorageFlags>, apply_type: BatchInsertTreeApplyType, transaction: TransactionArg, @@ -34,7 +34,7 @@ impl Drive { { 0 => self.batch_insert_empty_tree_if_not_exists_v0( path_key_info, - use_sum_tree, + tree_type, storage_flags, apply_type, transaction, diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs index 3aa69889483..e1b0dc30b38 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs @@ -1,8 +1,8 @@ use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; -use crate::fees::op::LowLevelDriveOperation; use crate::fees::op::LowLevelDriveOperation::GroveOperation; +use crate::fees::op::{LowLevelDriveOperation, LowLevelDriveOperationTreeTypeConverter}; use crate::util::grove_operations::BatchInsertTreeApplyType; use crate::util::object_size_info::PathKeyInfo; use crate::util::object_size_info::PathKeyInfo::{ @@ -11,7 +11,7 @@ use crate::util::object_size_info::PathKeyInfo::{ use crate::util::storage_flags::StorageFlags; use dpp::version::drive_versions::DriveVersion; use grovedb::batch::GroveOp; -use grovedb::TransactionArg; +use grovedb::{TransactionArg, TreeType}; impl Drive { /// Pushes an "insert empty tree where path key does not yet exist" operation to `drive_operations`. @@ -19,7 +19,7 @@ impl Drive { pub(crate) fn batch_insert_empty_tree_if_not_exists_v0( &self, path_key_info: PathKeyInfo, - use_sum_tree: bool, + tree_type: TreeType, storage_flags: Option<&StorageFlags>, apply_type: BatchInsertTreeApplyType, transaction: TransactionArg, @@ -30,19 +30,11 @@ impl Drive { //todo: clean up the duplication match path_key_info { PathKeyRef((path, key)) => { - let drive_operation = if use_sum_tree { - LowLevelDriveOperation::for_known_path_key_empty_sum_tree( - path.clone(), - key.to_vec(), - storage_flags, - ) - } else { - LowLevelDriveOperation::for_known_path_key_empty_tree( - path.clone(), - key.to_vec(), - storage_flags, - ) - }; + let drive_operation = tree_type.empty_tree_operation_for_known_path_key( + path.clone(), + key.to_vec(), + storage_flags, + ); // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -105,19 +97,11 @@ impl Drive { DriveError::NotSupportedPrivate("document sizes in batch operations not supported"), )), PathKey((path, key)) => { - let drive_operation = if use_sum_tree { - LowLevelDriveOperation::for_known_path_key_empty_sum_tree( - path.clone(), - key.to_vec(), - storage_flags, - ) - } else { - LowLevelDriveOperation::for_known_path_key_empty_tree( - path.clone(), - key.to_vec(), - storage_flags, - ) - }; + let drive_operation = tree_type.empty_tree_operation_for_known_path_key( + path.clone(), + key.to_vec(), + storage_flags, + ); // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -178,19 +162,11 @@ impl Drive { } PathFixedSizeKey((path, key)) => { let path_items: Vec> = path.into_iter().map(Vec::from).collect(); - let drive_operation = if use_sum_tree { - LowLevelDriveOperation::for_known_path_key_empty_sum_tree( - path_items, - key.to_vec(), - storage_flags, - ) - } else { - LowLevelDriveOperation::for_known_path_key_empty_tree( - path_items, - key.to_vec(), - storage_flags, - ) - }; + let drive_operation = tree_type.empty_tree_operation_for_known_path_key( + path_items, + key.to_vec(), + storage_flags, + ); // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -251,19 +227,11 @@ impl Drive { } PathFixedSizeKeyRef((path, key)) => { let path_items: Vec> = path.into_iter().map(Vec::from).collect(); - let drive_operation = if use_sum_tree { - LowLevelDriveOperation::for_known_path_key_empty_sum_tree( - path_items, - key.to_vec(), - storage_flags, - ) - } else { - LowLevelDriveOperation::for_known_path_key_empty_tree( - path_items, - key.to_vec(), - storage_flags, - ) - }; + let drive_operation = tree_type.empty_tree_operation_for_known_path_key( + path_items, + key.to_vec(), + storage_flags, + ); // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/mod.rs index 943dac0b8e0..9200949046b 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/mod.rs @@ -47,7 +47,7 @@ impl Drive { transaction: TransactionArg, drive_operations: &mut Vec, drive_version: &DriveVersion, - ) -> Result<(), Error> { + ) -> Result { match drive_version .grove_methods .batch diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/v0/mod.rs index 6785633e73e..902f806e797 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_if_not_exists/v0/mod.rs @@ -55,7 +55,7 @@ impl Drive { transaction: TransactionArg, drive_operations: &mut Vec, drive_version: &DriveVersion, - ) -> Result<(), Error> { + ) -> Result { match path_key_element_info { PathKeyRefElement((path, key, element)) => { if let Element::SumItem(new_value, _) = element { @@ -70,11 +70,13 @@ impl Drive { )?; if let Some(Element::SumItem(..)) = existing_element { - if error_if_exists { - return Err(Error::Drive(DriveError::CorruptedDriveState( + return if error_if_exists { + Err(Error::Drive(DriveError::CorruptedDriveState( "expected no sum item".to_string(), - ))); - } + ))) + } else { + Ok(false) + }; // Else do nothing } else if existing_element.is_some() { return Err(Error::Drive(DriveError::CorruptedElementType( @@ -95,7 +97,7 @@ impl Drive { "expected sum item element type", ))); } - Ok(()) + Ok(true) } PathKeyElement((path, key, element)) => { if let Element::SumItem(new_value, _) = element { @@ -110,11 +112,13 @@ impl Drive { )?; if let Some(Element::SumItem(..)) = existing_element { - if error_if_exists { - return Err(Error::Drive(DriveError::CorruptedDriveState( + return if error_if_exists { + Err(Error::Drive(DriveError::CorruptedDriveState( "expected no sum item".to_string(), - ))); - } + ))) + } else { + Ok(false) + }; // Else do nothing } else if existing_element.is_some() { return Err(Error::Drive(DriveError::CorruptedElementType( @@ -135,7 +139,7 @@ impl Drive { "expected sum item element type", ))); } - Ok(()) + Ok(true) } PathFixedSizeKeyRefElement((path, key, element)) => { if let Element::SumItem(new_value, _) = element { @@ -150,11 +154,13 @@ impl Drive { )?; if let Some(Element::SumItem(..)) = existing_element { - if error_if_exists { - return Err(Error::Drive(DriveError::CorruptedDriveState( + return if error_if_exists { + Err(Error::Drive(DriveError::CorruptedDriveState( "expected no sum item".to_string(), - ))); - } + ))) + } else { + Ok(false) + }; // Else do nothing } else if existing_element.is_some() { return Err(Error::Drive(DriveError::CorruptedElementType( @@ -176,7 +182,7 @@ impl Drive { "expected sum item element type", ))); } - Ok(()) + Ok(true) } PathKeyElementSize((key_info_path, key_info, element)) => { if let Element::SumItem(new_value, _) = element { @@ -202,7 +208,7 @@ impl Drive { Element::new_sum_item(new_value), ), ); - Ok(()) + Ok(true) } BatchInsertApplyType::StatefulBatchInsert => { Err(Error::Drive(DriveError::NotSupportedPrivate( diff --git a/packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/mod.rs new file mode 100644 index 00000000000..571cd7461b5 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/mod.rs @@ -0,0 +1,58 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::grove_operations::DirectQueryType; +use dpp::version::drive_versions::DriveVersion; +use grovedb::TransactionArg; +use grovedb_path::SubtreePath; + +impl Drive { + /// Retrieves the total value from a sum tree within groveDB at the specified path and key. + /// The cost of the operation is then appended to `drive_operations` for later processing. + /// + /// # Parameters + /// * `path`: The groveDB hierarchical authenticated structure path where the sum tree is located. + /// * `key`: The key where the sum tree resides within the subtree. + /// * `query_type`: The type of query to perform, either `StatelessDirectQuery` or `StatefulDirectQuery`. + /// * `transaction`: The groveDB transaction associated with this operation. + /// * `drive_operations`: A vector to collect the costs of operations for later computation. + /// * `platform_version`: The platform version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(i64)` if the operation was successful, returning the total value of the sum tree. + /// * `Err(DriveError::UnknownVersionMismatch)` if the platform version does not match known versions. + /// * `Err(DriveError::CorruptedBalancePath)` if the balance path does not refer to a sum tree. + /// * `Err(DriveError::CorruptedCodeExecution)` if trying to query a non-tree element. + pub fn grove_get_big_sum_tree_total_value>( + &self, + path: SubtreePath<'_, B>, + key: &[u8], + query_type: DirectQueryType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result { + match drive_version + .grove_methods + .basic + .grove_get_big_sum_tree_total_value + { + 0 => self.grove_get_big_sum_tree_total_value_v0( + path, + key, + query_type, + transaction, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "grove_get_big_sum_tree_total_value".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/v0/mod.rs new file mode 100644 index 00000000000..71ab45ea201 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/grove_get_big_sum_tree_total_value/v0/mod.rs @@ -0,0 +1,67 @@ +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::fees::op::LowLevelDriveOperation::CalculatedCostOperation; +use crate::util::grove_operations::{DirectQueryType, QueryTarget}; +use grovedb::batch::key_info::KeyInfo; +use grovedb::batch::KeyInfoPath; +use grovedb::{Element, GroveDb, TransactionArg}; +use grovedb_costs::CostContext; +use grovedb_path::SubtreePath; +use platform_version::version::drive_versions::DriveVersion; + +impl Drive { + /// Gets the element at the given path from groveDB. + /// Pushes the `OperationCost` of getting the element to `drive_operations`. + pub(super) fn grove_get_big_sum_tree_total_value_v0>( + &self, + path: SubtreePath<'_, B>, + key: &[u8], + query_type: DirectQueryType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result { + match query_type { + DirectQueryType::StatelessDirectQuery { + in_tree_type, + query_target, + } => { + let key_info_path = KeyInfoPath::from_known_owned_path(path.to_vec()); + let key_info = KeyInfo::KnownKey(key.to_vec()); + let cost = match query_target { + QueryTarget::QueryTargetTree(flags_size, tree_type) => { + Ok(GroveDb::average_case_for_get_tree( + &key_info_path, + &key_info, + flags_size, + tree_type, + in_tree_type, + &drive_version.grove_version, + )?) + } + _ => Err(Error::Drive(DriveError::CorruptedCodeExecution( + "can not query a non tree", + ))), + }?; + + drive_operations.push(CalculatedCostOperation(cost)); + Ok(0) + } + DirectQueryType::StatefulDirectQuery => { + let CostContext { value, cost } = + self.grove + .get_raw(path, key, transaction, &drive_version.grove_version); + drive_operations.push(CalculatedCostOperation(cost)); + let element = value.map_err(Error::GroveDB)?; + match element { + Element::BigSumTree(_, value, _) => Ok(value), + _ => Err(Error::Drive(DriveError::CorruptedBalancePath( + "balance path does not refer to a big sum tree", + ))), + } + } + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/mod.rs b/packages/rs-drive/src/util/grove_operations/mod.rs index 87818cdc13a..82694d57be2 100644 --- a/packages/rs-drive/src/util/grove_operations/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/mod.rs @@ -137,6 +137,8 @@ pub mod batch_insert_sum_item_if_not_exists; /// Moved items that are found in a path query to a new path. pub mod batch_move_items_in_path_query; +/// Get the total value from a big sum tree +pub mod grove_get_big_sum_tree_total_value; /// Get total value from sum tree in grove if it exists pub mod grove_get_optional_sum_tree_total_value; /// Fetch raw grove data if it exists, None otherwise @@ -287,6 +289,7 @@ impl BatchInsertTreeApplyType { } /// Batch insert apply type +#[derive(Clone, Copy)] pub enum BatchInsertApplyType { /// Stateless batch insert StatelessBatchInsert { diff --git a/packages/rs-platform-version/Cargo.toml b/packages/rs-platform-version/Cargo.toml index 6103074b3e3..5bce71ac114 100644 --- a/packages/rs-platform-version/Cargo.toml +++ b/packages/rs-platform-version/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" thiserror = { version = "1.0.63" } bincode = { version = "2.0.0-rc.3" } versioned-feature-core = { git = "https://github.com/dashpay/versioned-feature-core", version = "1.0.0" } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev= "2417f7a72900cd3dca943ad52c979bc8abfdaa20" } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev= "263dcd5164c7db597bf7de7b6de133ad7cd77d50" } once_cell = "1.19.0" [features] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs index 7b281cd6cc6..71d7fc8b00c 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs @@ -36,6 +36,7 @@ pub struct DriveGroveBasicMethodVersions { pub grove_get_raw_item: FeatureVersion, pub grove_get_optional_sum_tree_total_value: FeatureVersion, pub grove_get_raw_optional_item: FeatureVersion, + pub grove_get_big_sum_tree_total_value: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs index 31b39cfad3e..0fa2d7d09c9 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs @@ -29,6 +29,7 @@ pub const DRIVE_GROVE_METHOD_VERSIONS_V1: DriveGroveMethodVersions = DriveGroveM grove_get_raw_item: 0, grove_get_optional_sum_tree_total_value: 0, grove_get_raw_optional_item: 0, + grove_get_big_sum_tree_total_value: 0, }, batch: DriveGroveBatchMethodVersions { batch_insert_empty_tree: 0, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs index 031cd38dfa5..958724c7a8b 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs @@ -69,6 +69,7 @@ pub struct DriveIdentityCostEstimationMethodVersions { pub for_purpose_in_key_reference_tree: FeatureVersion, pub for_root_key_reference_tree: FeatureVersion, pub for_update_revision: FeatureVersion, + pub for_token_identity_infos: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs index d0b23ccc1a0..385078e380f 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs @@ -130,6 +130,7 @@ pub const DRIVE_IDENTITY_METHOD_VERSIONS_V1: DriveIdentityMethodVersions = for_purpose_in_key_reference_tree: 0, for_root_key_reference_tree: 0, for_update_revision: 0, + for_token_identity_infos: 0, }, withdrawals: DriveIdentityWithdrawalMethodVersions { document: DriveIdentityWithdrawalDocumentMethodVersions { diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/mod.rs index 6b88759c6ab..53b97598cf4 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/mod.rs @@ -7,6 +7,7 @@ pub struct DriveTokenMethodVersions { pub fetch: DriveTokenFetchMethodVersions, pub prove: DriveTokenProveMethodVersions, pub update: DriveTokenUpdateMethodVersions, + pub calculate_total_tokens_balance: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/v1.rs index faabf9f280a..2cc010c109a 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_token_method_versions/v1.rs @@ -34,4 +34,5 @@ pub const DRIVE_TOKEN_METHOD_VERSIONS_V1: DriveTokenMethodVersions = DriveTokenM unfreeze: 0, apply_status: 0, }, + calculate_total_tokens_balance: 0, };