Skip to content

Commit

Permalink
more work on tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer committed Dec 5, 2024
1 parent 279d16f commit cf32dd5
Show file tree
Hide file tree
Showing 11 changed files with 1,185 additions and 4 deletions.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use platform_value::{Value, ValueMapHelper};
pub const DATA_CONTRACT_SCHEMA_URI_V0: &str =
"https://github.com/dashpay/platform/blob/master/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json";

pub const TOKEN_SCHEMA_URI_V0: &str =
"https://github.com/dashpay/platform/blob/master/packages/rs-dpp/schema/meta_schemas/document/v0/token-meta.json";

pub const PROPERTY_SCHEMA: &str = "$schema";

const SYSTEM_GENERATED_FIELDS: [&str; 9] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ pub mod document_replace_transition;
pub mod document_transfer_transition;
pub mod document_update_price_transition;
pub mod token_base_transition;
pub mod token_burn_transition;
pub mod token_issuance_transition;
pub mod token_transfer_transition;
pub mod token_burn_transition;

use crate::prelude::Revision;
use crate::state_transition::documents_batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ pub use self::document_transition::{
document_create_transition::DocumentCreateTransition, document_delete_transition,
document_delete_transition::DocumentDeleteTransition, document_replace_transition,
document_replace_transition::DocumentReplaceTransition, token_base_transition,
token_issuance_transition, token_issuance_transition::TokenIssuanceTransition,
token_burn_transition, token_burn_transition::TokenBurnTransition,
token_transfer_transition, token_transfer_transition::TokenTransferTransition,
token_burn_transition, token_burn_transition::TokenBurnTransition, token_issuance_transition,
token_issuance_transition::TokenIssuanceTransition, token_transfer_transition,
token_transfer_transition::TokenTransferTransition,
};

use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize, PlatformSignable};
Expand Down
1 change: 1 addition & 0 deletions packages/rs-drive/src/drive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub mod votes;

#[cfg(feature = "server")]
mod shared;
mod tokens;

#[cfg(feature = "server")]
use crate::cache::DriveCache;
Expand Down
5 changes: 5 additions & 0 deletions packages/rs-drive/src/drive/tokens/balance/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[cfg(feature = "server")]
mod prove;
mod queries;
#[cfg(feature = "server")]
mod update;
150 changes: 150 additions & 0 deletions packages/rs-drive/src/drive/tokens/balance/prove.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use crate::drive::Drive;
use crate::error::Error;

use dpp::version::drive_versions::DriveVersion;

use grovedb::TransactionArg;

impl Drive {
/// Proves an Identity's token balance from the backing store
pub fn prove_identity_token_balance(
&self,
identity_id: [u8; 32],
token_id: [u8; 32],
transaction: TransactionArg,
drive_version: &DriveVersion,
) -> Result<Vec<u8>, Error> {
let balance_query = Self::token_balance_for_identity_id_query(token_id, identity_id);
self.grove_get_proved_path_query(&balance_query, transaction, &mut vec![], drive_version)
}

/// Proves multiple Identity token balances from the backing store
pub fn prove_many_identity_token_balances(
&self,
identity_ids: &[[u8; 32]],
token_id: [u8; 32],
transaction: TransactionArg,
drive_version: &DriveVersion,
) -> Result<Vec<u8>, Error> {
let balance_query = Self::token_balances_for_identity_ids_query(token_id, identity_ids);
self.grove_get_proved_path_query(&balance_query, transaction, &mut vec![], drive_version)
}

/// Proves multiple Identity balances from the backing store by range
pub fn prove_many_identity_token_balances_by_range(
&self,
start_at: Option<([u8; 32], bool)>,
ascending: bool,
limit: u16,
transaction: TransactionArg,
drive_version: &DriveVersion,
) -> Result<Vec<u8>, Error> {
let balance_query = Self::balances_for_range_query(start_at, ascending, limit);
self.grove_get_proved_path_query(&balance_query, transaction, &mut vec![], drive_version)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure;
use dpp::block::block_info::BlockInfo;
use dpp::identity::Identity;

mod prove_identity_balance {
use super::*;
use dpp::identity::accessors::IdentityGettersV0;
use dpp::version::PlatformVersion;

#[test]
fn should_prove_a_single_identity_balance() {
let drive = setup_drive_with_initial_state_structure(None);

let platform_version = PlatformVersion::first();

let identity = Identity::random_identity(3, Some(14), platform_version)
.expect("expected a platform identity");

let identity_id = identity.id().to_buffer();
drive
.add_new_identity(
identity.clone(),
false,
&BlockInfo::default(),
true,
None,
platform_version,
)
.expect("expected to add an identity");
let proof = drive
.prove_identity_balance(identity.id().to_buffer(), None, &platform_version.drive)
.expect("should not error when proving an identity");

let (_, proved_identity_balance) = Drive::verify_identity_balance_for_identity_id(
proof.as_slice(),
identity_id,
false,
platform_version,
)
.expect("expect that this be verified");

assert_eq!(proved_identity_balance, Some(identity.balance()));
}
}

mod prove_many_identity_balances {
use super::*;
use dpp::fee::Credits;
use dpp::identity::accessors::IdentityGettersV0;
use platform_version::version::PlatformVersion;
use std::collections::BTreeMap;

#[test]
fn should_prove_multiple_identity_balances() {
let drive = setup_drive_with_initial_state_structure(None);
let platform_version = PlatformVersion::latest();
let identities: BTreeMap<[u8; 32], Identity> =
Identity::random_identities(10, 3, Some(14), platform_version)
.expect("expected to get random identities")
.into_iter()
.map(|identity| (identity.id().to_buffer(), identity))
.collect();

for identity in identities.values() {
drive
.add_new_identity(
identity.clone(),
false,
&BlockInfo::default(),
true,
None,
platform_version,
)
.expect("expected to add an identity");
}
let identity_ids = identities.keys().copied().collect::<Vec<[u8; 32]>>();
let identity_balances = identities
.into_iter()
.map(|(id, identity)| (id, Some(identity.balance())))
.collect::<BTreeMap<[u8; 32], Option<Credits>>>();
let proof = drive
.prove_many_identity_balances(
identity_ids.as_slice(),
None,
&platform_version.drive,
)
.expect("should not error when proving an identity");

let (_, proved_identity_balances): ([u8; 32], BTreeMap<[u8; 32], Option<Credits>>) =
Drive::verify_identity_balances_for_identity_ids(
proof.as_slice(),
false,
identity_ids.as_slice(),
platform_version,
)
.expect("expect that this be verified");

assert_eq!(proved_identity_balances, identity_balances);
}
}
}
73 changes: 73 additions & 0 deletions packages/rs-drive/src/drive/tokens/balance/queries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::drive::balances::balance_path_vec;
use crate::drive::tokens::token_balances_path_vec;
use crate::drive::Drive;
use crate::query::{Query, QueryItem};
use grovedb::{PathQuery, SizedQuery};
use std::ops::RangeFull;

impl Drive {
/// The query for proving the identities balance of a token from an identity id.
pub fn token_balance_for_identity_id_query(
token_id: [u8; 32],
identity_id: [u8; 32],
) -> PathQuery {
let balance_path = token_balances_path_vec(token_id);
PathQuery::new_single_key(balance_path, identity_id.to_vec())
}

/// The query getting a token balance for many identities
pub fn token_balances_for_identity_ids_query(
token_id: [u8; 32],
identity_ids: &[[u8; 32]],
) -> PathQuery {
let balance_path = token_balances_path_vec(token_id);
let mut query = Query::new();
query.insert_keys(identity_ids.iter().map(|key| key.to_vec()).collect());
PathQuery {
path: balance_path,
query: SizedQuery {
query,
limit: None,
offset: None,
},
}
}

/// The query getting token balances for identities in a range
pub fn token_balances_for_range_query(
token_id: [u8; 32],
start_at: Option<([u8; 32], bool)>,
ascending: bool,
limit: u16,
) -> PathQuery {
let balance_path = token_balances_path_vec(token_id);
let mut query = Query::new_with_direction(ascending);
if ascending {
if let Some((start_at, start_at_included)) = start_at {
if start_at_included {
query.insert_item(QueryItem::RangeFrom(start_at.to_vec()..))
} else {
query.insert_item(QueryItem::RangeAfter(start_at.to_vec()..))
}
} else {
query.insert_item(QueryItem::RangeFull(RangeFull))
}
} else if let Some((start_at, start_at_included)) = start_at {
if start_at_included {
query.insert_item(QueryItem::RangeToInclusive(..=start_at.to_vec()))
} else {
query.insert_item(QueryItem::RangeTo(..start_at.to_vec()))
}
} else {
query.insert_item(QueryItem::RangeFull(RangeFull))
}
PathQuery {
path: balance_path,
query: SizedQuery {
query,
limit: Some(limit),
offset: None,
},
}
}
}
Loading

0 comments on commit cf32dd5

Please sign in to comment.