Skip to content

Commit

Permalink
more token work
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer committed Dec 18, 2024
1 parent dc8e575 commit b07e1a6
Show file tree
Hide file tree
Showing 20 changed files with 481 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl Drive {
}

if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info {
Self::add_estimation_costs_for_balances(
Self::add_estimation_costs_for_token_balances(
estimated_costs_only_with_layer_info,
&platform_version.drive,
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl Drive {
let mut drive_operations = vec![];
let drive_version = &platform_version.drive;
if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info {
Self::add_estimation_costs_for_balances(
Self::add_estimation_costs_for_token_balances(
estimated_costs_only_with_layer_info,
drive_version,
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl Drive {
) -> Result<Vec<LowLevelDriveOperation>, 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_balances(
Self::add_estimation_costs_for_token_balances(
estimated_costs_only_with_layer_info,
&platform_version.drive,
)?;
Expand Down
4 changes: 2 additions & 2 deletions packages/rs-drive/src/drive/initialization/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Drive {

self.grove_insert_empty_tree(
SubtreePath::empty(),
&[RootTree::TokenBalances as u8],
&[RootTree::Tokens as u8],
transaction,
None,
&mut drive_operations,
Expand Down Expand Up @@ -302,7 +302,7 @@ mod tests {

// Merk Level 2
let mut query = Query::new();
query.insert_key(vec![RootTree::TokenBalances as u8]);
query.insert_key(vec![RootTree::Tokens as u8]);
let root_path_query = PathQuery::new(
vec![],
SizedQuery {
Expand Down
10 changes: 5 additions & 5 deletions packages/rs-drive/src/drive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ pub enum RootTree {
WithdrawalTransactions = 80,
/// Balances (For identities)
Balances = 96,
/// Token Balances
TokenBalances = 16,
/// Token Balances and Info
Tokens = 16,
/// Versions desired by proposers
Versions = 120,
/// Registered votes
Expand All @@ -138,7 +138,7 @@ impl fmt::Display for RootTree {
RootTree::Misc => "Misc",
RootTree::WithdrawalTransactions => "WithdrawalTransactions",
RootTree::Balances => "Balances",
RootTree::TokenBalances => "TokenBalances",
RootTree::Tokens => "TokenBalances",
RootTree::Versions => "Versions",
RootTree::Votes => "Votes",
};
Expand Down Expand Up @@ -181,7 +181,7 @@ impl TryFrom<u8> for RootTree {
104 => Ok(RootTree::Misc),
80 => Ok(RootTree::WithdrawalTransactions),
96 => Ok(RootTree::Balances),
16 => Ok(RootTree::TokenBalances),
16 => Ok(RootTree::Tokens),
120 => Ok(RootTree::Versions),
112 => Ok(RootTree::Votes),
_ => Err(Error::Drive(DriveError::NotSupported(
Expand All @@ -205,7 +205,7 @@ impl From<RootTree> for &'static [u8; 1] {
RootTree::Misc => &[104],
RootTree::WithdrawalTransactions => &[80],
RootTree::Balances => &[96],
RootTree::TokenBalances => &[16],
RootTree::Tokens => &[16],
RootTree::NonUniquePublicKeyKeyHashesToIdentities => &[8],
RootTree::Versions => &[120],
RootTree::Votes => &[112],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,115 @@
mod v0;

use crate::drive::identity::update::add_to_previous_balance_outcome::AddToPreviousBalanceOutcome;
use crate::drive::Drive;
use crate::error::drive::DriveError;
use crate::error::Error;
use crate::fees::op::LowLevelDriveOperation;
use dpp::block::block_info::BlockInfo;
use dpp::fee::fee_result::FeeResult;
use dpp::fee::Credits;

use dpp::fee::default_costs::CachedEpochIndexFeeVersions;
use dpp::version::PlatformVersion;
use grovedb::TransactionArg;
use grovedb::batch::KeyInfoPath;
use grovedb::{EstimatedLayerInformation, TransactionArg};
use std::collections::HashMap;

impl Drive {
/// The method to add balance to the previous balance for a token. This function is version controlled.
/// The operations for adding a certain amount of credits to an identity's balance. This function is version controlled.
///
/// # Arguments
///
/// * `identity_id` - The ID of the Identity.
/// * `previous_balance` - The previous balance of the Identity.
/// * `added_balance` - The balance to be added.
/// * `apply` - Whether to apply the operations.
/// * `transaction` - The current transaction.
/// * `drive_operations` - The vector of LowLevelDriveOperations.
/// * `drive_version` - The drive version.
/// * `token_id` - The ID of the Token.
/// * `identity_id` - The ID of the Identity to which credits are to be added.
/// * `balance_to_add` - The amount of credits to be added to the identity's balance.
/// * `block_info` - Information about the current block.
/// * `apply` - A boolean indicating whether the operation should be applied or not.
/// * `transaction` - The transaction information related to the operation.
/// * `platform_version` - The platform version.
/// * `previous_fee_versions` - Cached fee versions, if any.
///
/// # Returns
///
/// * `Result<AddToPreviousBalanceOutcome, Error>` - The outcome if successful, or an error.
pub(in crate::drive::tokens) fn add_to_previous_token_balance(
/// * `Result<FeeResult, Error>` - The resulting fee result if successful, or an error.
pub fn add_to_identity_token_balance(
&self,
token_id: [u8; 32],
identity_id: [u8; 32],
previous_balance: Credits,
added_balance: Credits,
balance_to_add: Credits,
block_info: &BlockInfo,
apply: bool,
transaction: TransactionArg,
drive_operations: &mut Vec<LowLevelDriveOperation>,
platform_version: &PlatformVersion,
) -> Result<AddToPreviousBalanceOutcome, Error> {
previous_fee_versions: Option<&CachedEpochIndexFeeVersions>,
) -> Result<FeeResult, Error> {
match platform_version
.drive
.methods
.token
.update
.add_to_previous_token_balance
.add_to_identity_token_balance
{
0 => self.add_to_previous_token_balance_v0(
0 => self.add_to_identity_token_balance_v0(
token_id,
identity_id,
previous_balance,
added_balance,
balance_to_add,
block_info,
apply,
transaction,
drive_operations,
platform_version,
previous_fee_versions,
),
version => Err(Error::Drive(DriveError::UnknownVersionMismatch {
method: "add_to_identity_token_balance".to_string(),
known_versions: vec![0],
received: version,
})),
}
}

/// Adds a specified amount of credits to an identity balance. This function checks for overflows and ensures the balance does not exceed `MAX_CREDITS`.
/// Balances are stored under the identity's ID in the token balance tree.
///
/// # Arguments
///
/// * `token_id` - The ID of the Token.
/// * `identity_id` - The ID of the Identity to which credits are to be added.
/// * `balance_to_add` - The amount of credits to be added to the identity's balance.
/// * `estimated_costs_only_with_layer_info` - Estimated costs with layer information, if any.
/// * `transaction` - The transaction information related to the operation.
/// * `platform_version` - The platform version.
///
/// # Returns
///
/// * `Result<Vec<LowLevelDriveOperation>, Error>` - The resulting low level drive operations if successful, or an error.
pub(crate) fn add_to_identity_token_balance_operations(
&self,
token_id: [u8; 32],
identity_id: [u8; 32],
balance_to_add: Credits,
estimated_costs_only_with_layer_info: &mut Option<
HashMap<KeyInfoPath, EstimatedLayerInformation>,
>,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<Vec<LowLevelDriveOperation>, Error> {
match platform_version
.drive
.methods
.token
.update
.add_to_identity_token_balance
{
0 => self.add_to_identity_token_balance_operations_v0(
token_id,
identity_id,
balance_to_add,
estimated_costs_only_with_layer_info,
transaction,
platform_version,
),
version => Err(Error::Drive(DriveError::UnknownVersionMismatch {
method: "add_to_previous_token_balance".to_string(),
method: "add_to_identity_token_balance_operations".to_string(),
known_versions: vec![0],
received: version,
})),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,143 @@
use crate::drive::Drive;
use crate::error::identity::IdentityError;
use crate::error::Error;
use crate::fees::op::LowLevelDriveOperation;
use dpp::balances::credits::TokenAmount;
use dpp::block::block_info::BlockInfo;
use dpp::fee::fee_result::FeeResult;
use dpp::fee::Credits;

use crate::drive::tokens::token_balances_path_vec;
use dpp::fee::default_costs::CachedEpochIndexFeeVersions;
use dpp::version::PlatformVersion;
use grovedb::TransactionArg;
use dpp::ProtocolError;
use grovedb::batch::KeyInfoPath;
use grovedb::{Element, EstimatedLayerInformation, TransactionArg};
use std::collections::HashMap;

impl Drive {
/// The method to add balance to the previous balance. This function is version controlled.
pub(super) fn add_to_previous_token_balance_v0(
/// Adds specified amount of credits to identity balance
/// This function checks for overflows and does not exceed MAX_CREDITS
///
/// Balances are stored in the balance tree under the identity's id
pub(in crate::drive::tokens) fn add_to_identity_token_balance_v0(
&self,
token_id: [u8; 32],
identity_id: [u8; 32],
previous_balance: Credits,
added_balance: Credits,
balance_to_add: Credits,
block_info: &BlockInfo,
apply: bool,
transaction: TransactionArg,
drive_operations: &mut Vec<LowLevelDriveOperation>,
platform_version: &PlatformVersion,
) -> Result<AddToPreviousBalanceOutcome, Error> {
// Deduct added balance from existing one
let new_balance = previous_balance
.checked_add(added_balance)
.ok_or(Error::Identity(IdentityError::CriticalBalanceOverflow(
"identity balance add overflow error",
)))?;

Ok(AddToPreviousBalanceOutcomeV0 {
balance_modified: Some(new_balance),
negative_credit_balance_modified: None,
previous_fee_versions: Option<&CachedEpochIndexFeeVersions>,
) -> Result<FeeResult, Error> {
let mut estimated_costs_only_with_layer_info = if apply {
None::<HashMap<KeyInfoPath, EstimatedLayerInformation>>
} else {
Some(HashMap::new())
};

let batch_operations = self.add_to_identity_token_balance_operations_v0(
token_id,
identity_id,
balance_to_add,
&mut estimated_costs_only_with_layer_info,
transaction,
platform_version,
)?;

let mut drive_operations: Vec<LowLevelDriveOperation> = vec![];
self.apply_batch_low_level_drive_operations(
estimated_costs_only_with_layer_info,
transaction,
batch_operations,
&mut drive_operations,
&platform_version.drive,
)?;
let fees = Drive::calculate_fee(
None,
Some(drive_operations),
&block_info.epoch,
self.config.epochs_per_era,
platform_version,
previous_fee_versions,
)?;
Ok(fees)
}

/// Adds specified amount of credits to identity balance
/// This function checks for overflows and does not exceed MAX_CREDITS
///
/// Balances are stored in the identity under key 0
/// This gets operations based on apply flag (stateful vs stateless)
pub(in crate::drive::tokens) fn add_to_identity_token_balance_operations_v0(
&self,
token_id: [u8; 32],
identity_id: [u8; 32],
balance_to_add: TokenAmount,
estimated_costs_only_with_layer_info: &mut Option<
HashMap<KeyInfoPath, EstimatedLayerInformation>,
>,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<Vec<LowLevelDriveOperation>, 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(
estimated_costs_only_with_layer_info,
&platform_version.drive,
)?;
}

let apply = estimated_costs_only_with_layer_info.is_none();

let previous_balance = if apply {
self.fetch_identity_token_balance_operations(
token_id,
identity_id,
apply,
transaction,
&mut drive_operations,
platform_version,
)?
} else {
None // worse case is that we insert
};

let balance_path = token_balances_path_vec(token_id);

if let Some(previous_balance) = previous_balance {
// Check for overflow
let new_balance = (previous_balance as i64)
.checked_add(balance_to_add as i64)
.ok_or(
ProtocolError::CriticalCorruptedCreditsCodeExecution(
"Overflow of total token balance".to_string(),
)
.into(),
)?;

drive_operations.push(LowLevelDriveOperation::replace_for_known_path_key_element(
balance_path,
identity_id.to_vec(),
Element::new_sum_item(new_balance),
));
} else {
if balance_to_add > i64::MAX as u64 {
return Err(
ProtocolError::CriticalCorruptedCreditsCodeExecution(format!(
"Token balance to add over i64 max, is {}",
balance_to_add
))
.into(),
);
}
drive_operations.push(LowLevelDriveOperation::insert_for_known_path_key_element(
balance_path,
identity_id.to_vec(),
Element::new_sum_item(balance_to_add as i64),
));
}
.into())

Ok(drive_operations)
}
}
2 changes: 1 addition & 1 deletion packages/rs-drive/src/drive/tokens/balance/fetch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Drive {
transaction: TransactionArg,
drive_operations: &mut Vec<LowLevelDriveOperation>,
platform_version: &PlatformVersion,
) -> Result<Option<Credits>, Error> {
) -> Result<Option<TokenAmount>, Error> {
match platform_version.drive.methods.token.fetch.balance {
0 => self.fetch_identity_token_balance_operations_v0(
token_id,
Expand Down
Loading

0 comments on commit b07e1a6

Please sign in to comment.