From 516c7e0b769f0b283b98c15f13c809d0e6c0ec88 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 2 Apr 2025 22:26:14 +0700 Subject: [PATCH 01/46] feat: keyword search system contract --- Cargo.lock | 11 ++ packages/data-contracts/Cargo.toml | 1 + packages/data-contracts/src/error.rs | 17 +++ packages/data-contracts/src/lib.rs | 12 +- .../rs-dpp/src/data_contract/accessors/mod.rs | 23 +++ .../src/data_contract/accessors/v1/mod.rs | 9 ++ packages/rs-dpp/src/data_contract/mod.rs | 3 +- .../serialized_version/v1/mod.rs | 7 + .../src/data_contract/v1/accessors/mod.rs | 15 ++ .../src/data_contract/v1/data_contract.rs | 8 ++ .../src/data_contract/v1/serialization/mod.rs | 3 + .../rs-drive/src/cache/system_contracts.rs | 11 ++ .../contract/insert/add_new_keywords/mod.rs | 134 ++++++++++++++++++ .../insert/add_new_keywords/v0/mod.rs | 125 ++++++++++++++++ .../contract/insert/insert_contract/v1/mod.rs | 12 ++ .../rs-drive/src/drive/contract/insert/mod.rs | 1 + .../group/prove/prove_action_infos/v0/mod.rs | 2 + .../prove/prove_action_signers/v0/mod.rs | 3 + .../group/prove/prove_group_info/v0/mod.rs | 2 + .../group/prove/prove_group_infos/v0/mod.rs | 2 + .../prove_identities_token_balances/v0/mod.rs | 3 + .../prove_identity_token_balances/v0/mod.rs | 3 + .../prove_identities_token_infos/v0/mod.rs | 3 + .../info/prove_identity_token_infos/v0/mod.rs | 2 + .../status/prove_token_statuses/v0/mod.rs | 1 + .../v0/mod.rs | 2 + .../drive_contract_method_versions/v2.rs | 2 +- .../system_data_contract_versions/mod.rs | 2 + .../system_data_contract_versions/v1.rs | 2 + packages/search-contract/src/lib.rs | 4 +- packages/token-history-contract/src/lib.rs | 8 +- 31 files changed, 424 insertions(+), 9 deletions(-) create mode 100644 packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 0fb070fb49d..d24b2091467 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1326,6 +1326,7 @@ dependencies = [ "masternode-reward-shares-contract", "platform-value", "platform-version", + "search-contract", "serde_json", "thiserror 1.0.64", "token-history-contract", @@ -4296,6 +4297,16 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "search-contract" +version = "2.0.0-dev.1" +dependencies = [ + "platform-value", + "platform-version", + "serde_json", + "thiserror 1.0.64", +] + [[package]] name = "sec1" version = "0.7.3" diff --git a/packages/data-contracts/Cargo.toml b/packages/data-contracts/Cargo.toml index f10d5785838..a7fbd72d40b 100644 --- a/packages/data-contracts/Cargo.toml +++ b/packages/data-contracts/Cargo.toml @@ -18,3 +18,4 @@ feature-flags-contract = { path = "../feature-flags-contract" } platform-value = { path = "../rs-platform-value" } wallet-utils-contract = { path = "../wallet-utils-contract" } token-history-contract = { path = "../token-history-contract" } +search-contract = { path = "../search-contract" } diff --git a/packages/data-contracts/src/error.rs b/packages/data-contracts/src/error.rs index 7c0c802b71e..107823ab96c 100644 --- a/packages/data-contracts/src/error.rs +++ b/packages/data-contracts/src/error.rs @@ -136,3 +136,20 @@ impl From for Error { } } } + +impl From for Error { + fn from(e: search_contract::Error) -> Self { + match e { + search_contract::Error::UnknownVersionMismatch { + method, + known_versions, + received, + } => Error::UnknownVersionMismatch { + method, + known_versions, + received, + }, + search_contract::Error::InvalidSchemaJson(e) => Error::InvalidSchemaJson(e), + } + } +} diff --git a/packages/data-contracts/src/lib.rs b/packages/data-contracts/src/lib.rs index a78ffefc373..a95ab7340cc 100644 --- a/packages/data-contracts/src/lib.rs +++ b/packages/data-contracts/src/lib.rs @@ -9,6 +9,7 @@ pub use feature_flags_contract; pub use masternode_reward_shares_contract; use platform_value::Identifier; use platform_version::version::PlatformVersion; +pub use search_contract; pub use token_history_contract; pub use wallet_utils_contract; pub use withdrawals_contract; @@ -23,6 +24,7 @@ pub enum SystemDataContract { Dashpay = 4, WalletUtils = 5, TokenHistory = 6, + Search = 7, } pub struct DataContractSource { @@ -43,6 +45,7 @@ impl SystemDataContract { SystemDataContract::Dashpay => dashpay_contract::ID_BYTES, SystemDataContract::WalletUtils => wallet_utils_contract::ID_BYTES, SystemDataContract::TokenHistory => token_history_contract::ID_BYTES, + SystemDataContract::Search => search_contract::ID_BYTES, }; Identifier::new(bytes) } @@ -98,10 +101,17 @@ impl SystemDataContract { SystemDataContract::TokenHistory => DataContractSource { id_bytes: token_history_contract::ID_BYTES, owner_id_bytes: token_history_contract::OWNER_ID_BYTES, - version: platform_version.system_data_contracts.wallet as u32, + version: platform_version.system_data_contracts.token_history as u32, definitions: token_history_contract::load_definitions(platform_version)?, document_schemas: token_history_contract::load_documents_schemas(platform_version)?, }, + SystemDataContract::Search => DataContractSource { + id_bytes: search_contract::ID_BYTES, + owner_id_bytes: search_contract::OWNER_ID_BYTES, + version: platform_version.system_data_contracts.search as u32, + definitions: search_contract::load_definitions(platform_version)?, + document_schemas: search_contract::load_documents_schemas(platform_version)?, + }, }; Ok(data) diff --git a/packages/rs-dpp/src/data_contract/accessors/mod.rs b/packages/rs-dpp/src/data_contract/accessors/mod.rs index edb686751d0..846b6752282 100644 --- a/packages/rs-dpp/src/data_contract/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/accessors/mod.rs @@ -18,6 +18,8 @@ use crate::tokens::errors::TokenError; use crate::ProtocolError; use std::collections::BTreeMap; +use super::EMPTY_KEYWORDS; + pub mod v0; pub mod v1; @@ -268,6 +270,20 @@ impl DataContractV1Getters for DataContract { } } + fn keywords(&self) -> &Vec { + match self { + DataContract::V0(_) => &EMPTY_KEYWORDS, + DataContract::V1(v1) => &v1.keywords, + } + } + + fn keywords_mut(&mut self) -> Option<&mut Vec> { + match self { + DataContract::V0(_) => None, + DataContract::V1(v1) => Some(&mut v1.keywords), + } + } + /// Returns the timestamp in milliseconds when the contract was created. fn created_at(&self) -> Option { match self { @@ -399,4 +415,11 @@ impl DataContractV1Setters for DataContract { v1.updated_at_epoch = epoch; } } + + /// Sets the keywords for the contract. + fn set_keywords(&mut self, keywords: Vec) { + if let DataContract::V1(v1) = self { + v1.keywords = keywords; + } + } } diff --git a/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs b/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs index 8178ab7ec2c..b798c6e1f53 100644 --- a/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs @@ -63,6 +63,12 @@ pub trait DataContractV1Getters: DataContractV0Getters { /// Returns the epoch at which the contract was last updated. fn updated_at_epoch(&self) -> Option; + + /// Returns the keywords for the contract. + fn keywords(&self) -> &Vec; + + /// Returns a mutable reference to the keywords for the contract. + fn keywords_mut(&mut self) -> Option<&mut Vec>; } pub trait DataContractV1Setters: DataContractV0Setters { @@ -95,4 +101,7 @@ pub trait DataContractV1Setters: DataContractV0Setters { /// Sets the block height at which the contract was last updated. fn set_updated_at_epoch(&mut self, epoch: Option); + + /// Sets the keywords for the contract. + fn set_keywords(&mut self, keywords: Vec); } diff --git a/packages/rs-dpp/src/data_contract/mod.rs b/packages/rs-dpp/src/data_contract/mod.rs index 754bd12febb..8cc81bc0800 100644 --- a/packages/rs-dpp/src/data_contract/mod.rs +++ b/packages/rs-dpp/src/data_contract/mod.rs @@ -73,10 +73,11 @@ type PropertyPath = String; pub const INITIAL_DATA_CONTRACT_VERSION: u32 = 1; -// Define static empty BTreeMaps +// Define static empty BTreeMaps and Vecs static EMPTY_GROUPS: Lazy> = Lazy::new(BTreeMap::new); static EMPTY_TOKENS: Lazy> = Lazy::new(BTreeMap::new); +static EMPTY_KEYWORDS: Lazy> = Lazy::new(Vec::new); /// Understanding Data Contract versioning /// Data contract versioning is both for the code structure and for serialization. diff --git a/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs b/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs index 12828ce8f53..b79927dd307 100644 --- a/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs @@ -59,6 +59,10 @@ pub struct DataContractInSerializationFormatV1 { /// The tokens on the contract. #[serde(default, deserialize_with = "deserialize_u16_token_configuration_map")] pub tokens: BTreeMap, + + /// The contract's keywords for searching + #[serde(default)] + pub keywords: Vec, } fn deserialize_u16_group_map<'de, D>( @@ -124,6 +128,7 @@ impl From for DataContractInSerializationFormatV1 { updated_at_epoch: None, groups: Default::default(), tokens: Default::default(), + keywords: Default::default(), } } DataContract::V1(v1) => { @@ -142,6 +147,7 @@ impl From for DataContractInSerializationFormatV1 { updated_at_epoch, groups, tokens, + keywords, } = v1; DataContractInSerializationFormatV1 { @@ -162,6 +168,7 @@ impl From for DataContractInSerializationFormatV1 { updated_at_epoch, groups, tokens, + keywords, } } } diff --git a/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs b/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs index 1a6ae46a1b9..f5991b3d72f 100644 --- a/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs @@ -224,6 +224,16 @@ impl DataContractV1Getters for DataContractV1 { fn updated_at_epoch(&self) -> Option { self.updated_at_epoch } + + /// Returns the keywords for the contract. + fn keywords(&self) -> &Vec { + &self.keywords + } + + /// Returns a mutable reference to the keywords for the contract. + fn keywords_mut(&mut self) -> Option<&mut Vec> { + Some(&mut self.keywords) + } } impl DataContractV1Setters for DataContractV1 { @@ -272,4 +282,9 @@ impl DataContractV1Setters for DataContractV1 { fn set_updated_at_epoch(&mut self, epoch: Option) { self.updated_at_epoch = epoch; } + + /// Sets the keywords for the contract. + fn set_keywords(&mut self, keywords: Vec) { + self.keywords = keywords; + } } diff --git a/packages/rs-dpp/src/data_contract/v1/data_contract.rs b/packages/rs-dpp/src/data_contract/v1/data_contract.rs index 104e6334d94..19d2e7b9325 100644 --- a/packages/rs-dpp/src/data_contract/v1/data_contract.rs +++ b/packages/rs-dpp/src/data_contract/v1/data_contract.rs @@ -61,6 +61,11 @@ use platform_value::Value; /// - Useful for historical analysis, rollback mechanisms, and ensuring changes are anchored /// to specific blockchain states. /// +/// ## 4. **Keywords** (`keywords: Vec`) +/// - Keywords which contracts can be searched for via the new `search` system contract. +/// - This vector can be left empty, but if populated, it must contain unique keywords. +/// - The maximum number of keywords is limited to 20. +/// /// These additions ensure that data contracts are not only more flexible and governed but also /// fully auditable in terms of when and how they evolve over time. #[derive(Debug, Clone, PartialEq)] @@ -102,4 +107,7 @@ pub struct DataContractV1 { /// The tokens on the contract. pub tokens: BTreeMap, + + /// The contract's keywords for searching + pub keywords: Vec, } diff --git a/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs b/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs index 7f8976516be..05e40710b7b 100644 --- a/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs +++ b/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs @@ -111,6 +111,7 @@ impl DataContractV1 { updated_at_epoch: None, groups: Default::default(), tokens: Default::default(), + keywords: Default::default(), }; Ok(data_contract) @@ -137,6 +138,7 @@ impl DataContractV1 { updated_at_epoch, groups, tokens, + keywords, } = data_contract_data; let document_types = DocumentType::create_document_types_from_document_schemas( @@ -165,6 +167,7 @@ impl DataContractV1 { updated_at_epoch, groups, tokens, + keywords, }; Ok(data_contract) diff --git a/packages/rs-drive/src/cache/system_contracts.rs b/packages/rs-drive/src/cache/system_contracts.rs index 7de44da36bd..3c1fd170143 100644 --- a/packages/rs-drive/src/cache/system_contracts.rs +++ b/packages/rs-drive/src/cache/system_contracts.rs @@ -17,6 +17,8 @@ pub struct SystemDataContracts { masternode_reward_shares: ArcSwap, /// Token history contract token_history: ArcSwap, + /// Search contract + search: ArcSwap, } impl SystemDataContracts { @@ -45,6 +47,10 @@ impl SystemDataContracts { SystemDataContract::TokenHistory, platform_version, )?), + search: ArcSwap::from_pointee(load_system_data_contract( + SystemDataContract::Search, + platform_version, + )?), }) } @@ -72,4 +78,9 @@ impl SystemDataContracts { pub fn load_masternode_reward_shares(&self) -> Guard> { self.masternode_reward_shares.load() } + + /// Returns the search contract + pub fn load_search(&self) -> Guard> { + self.search.load() + } } diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs new file mode 100644 index 00000000000..494807c30c4 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -0,0 +1,134 @@ +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::version::PlatformVersion; + +use dpp::prelude::Identifier; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use std::collections::HashMap; + +mod v0; + +impl Drive { + /// Adds keywords to the state. + pub fn add_new_keywords( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &Vec, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 1 => Err(Error::Drive(DriveError::NotSupported( + "Contract keywords are not supported in this version", + ))), + 2 => self.add_new_keywords_v0( + contract_id, + owner_id, + keywords, + block_info, + apply, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_new_keywords".to_string(), + known_versions: vec![0], + received: version, + })), + } + } + + /// Adds keywords creation operations to drive operations + pub fn add_new_keywords_add_to_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &Vec, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 1 => Err(Error::Drive(DriveError::NotSupported( + "Contract keywords are not supported in this version", + ))), + 2 => self.add_new_keywords_add_to_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + apply, + transaction, + drive_operations, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_new_keywords_add_to_operations".to_string(), + known_versions: vec![0], + received: version, + })), + } + } + + /// The operations needed to create keywords + pub fn add_new_keywords_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &Vec, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 1 => Err(Error::Drive(DriveError::NotSupported( + "Contract keywords are not supported in this version", + ))), + 2 => self.add_new_keywords_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_new_keywords_operations".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs new file mode 100644 index 00000000000..31ab9443923 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -0,0 +1,125 @@ +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::object_size_info::DocumentInfo::DocumentOwnedInfo; +use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use platform_version::version::PlatformVersion; +use std::collections::HashMap; + +impl Drive { + /// Adds a keyword by inserting a new keyword subtree structure to the `Identities` subtree. + pub(super) fn add_new_keywords_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &Vec, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let mut drive_operations: Vec = vec![]; + self.add_new_keywords_add_to_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + apply, + transaction, + &mut drive_operations, + platform_version, + )?; + let fees = Drive::calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + self.config.epochs_per_era, + platform_version, + None, + )?; + Ok(fees) + } + + /// Adds keyword creation operations to drive operations + pub(super) fn add_new_keywords_add_to_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &Vec, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let mut estimated_costs_only_with_layer_info = if apply { + None::> + } else { + Some(HashMap::new()) + }; + + let batch_operations = self.add_new_keywords_operations( + contract_id, + owner_id, + keywords, + block_info, + &mut estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + self.apply_batch_low_level_drive_operations( + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + drive_operations, + &platform_version.drive, + ) + } + + /// The operations needed to create a keyword + pub(super) fn add_new_keywords_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &Vec, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let contract = self.cache.system_data_contracts.load_search(); + + let document_type = contract.document_type_for_name("contract")?; + + let document = + build_keyword_document_owned(contract_id, owner_id, keywords, platform_version)?; + + let operations = self.add_document_for_contract_operations( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentOwnedInfo((document, None)), + owner_id: Some(owner_id.to_buffer()), + }, + contract: &contract, + document_type, + }, + true, + block_info, + &mut None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + Ok(operations) + } +} 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 00aefcf9473..8faeae29cb8 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 @@ -307,6 +307,18 @@ impl Drive { )?); } + if !contract.keywords().is_empty() { + batch_operations.extend(self.add_new_keywords_operations( + contract.id(), + contract.owner_id(), + contract.keywords(), + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + Ok(batch_operations) } } diff --git a/packages/rs-drive/src/drive/contract/insert/mod.rs b/packages/rs-drive/src/drive/contract/insert/mod.rs index a222b57bc4d..69d22d495fb 100644 --- a/packages/rs-drive/src/drive/contract/insert/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/mod.rs @@ -1,2 +1,3 @@ mod add_contract_to_storage; +mod add_new_keywords; mod insert_contract; diff --git a/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs index 19fd3a86d8e..cd66e430e60 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs @@ -153,6 +153,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), ), ]), + keywords: Vec::new(), }); drive @@ -380,6 +381,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), ), ]), + keywords: Vec::new(), }); drive diff --git a/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs index 81b39a82c36..5527662be18 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs @@ -148,6 +148,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), ), ]), + keywords: Vec::new(), }); drive @@ -316,6 +317,7 @@ mod tests { }), )]), tokens: BTreeMap::new(), + keywords: Vec::new(), }); drive @@ -409,6 +411,7 @@ mod tests { }), )]), tokens: BTreeMap::new(), + keywords: Vec::new(), }); drive diff --git a/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs index 64dc4bc471f..93772e6c4b7 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs @@ -106,6 +106,7 @@ mod tests { }), )]), tokens: Default::default(), + keywords: Vec::new(), }); let contract_id = contract.id(); @@ -175,6 +176,7 @@ mod tests { updated_at_epoch: None, groups: Default::default(), tokens: Default::default(), + keywords: Vec::new(), }); let contract_id = contract.id(); diff --git a/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs index 4ab9965950e..3b53aae4b05 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs @@ -134,6 +134,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let contract_id = contract.id(); @@ -278,6 +279,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let contract_id = contract.id(); diff --git a/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs index a01a5c55d73..5138aa8845d 100644 --- a/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs @@ -97,6 +97,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -197,6 +198,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -288,6 +290,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive diff --git a/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs index 9ee2f26b2a0..d0069901b8e 100644 --- a/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs @@ -102,6 +102,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), ), ]), + keywords: Vec::new(), }); let token_id_1 = contract.token_id(0).expect("expected token at position 0"); @@ -262,6 +263,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); @@ -349,6 +351,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs b/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs index c63c406d378..43e1886b2f2 100644 --- a/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs @@ -97,6 +97,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -197,6 +198,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -286,6 +288,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive diff --git a/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs b/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs index 4ed3b4cbf53..0a4ad4e064f 100644 --- a/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs @@ -105,6 +105,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), ), ]), + keywords: Vec::new(), }); let token_id_1 = contract.token_id(0).expect("expected token at position 0"); @@ -252,6 +253,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs b/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs index a66e2c2d15c..b4cbfd2a850 100644 --- a/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs @@ -94,6 +94,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), ), ]), + keywords: Vec::new(), }); let token_id_1 = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs index 5cba606590d..83061d04d78 100644 --- a/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs @@ -88,6 +88,7 @@ mod tests { 0, TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); @@ -213,6 +214,7 @@ mod tests { TokenConfigurationV0::default_most_restrictive().with_base_supply(0), ), )]), + keywords: Vec::new(), }); let token_id = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs index 5197624ade2..9f4565afee3 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs @@ -17,7 +17,7 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V2: DriveContractMethodVersions = }, insert: DriveContractInsertMethodVersions { add_contract_to_storage: 0, - insert_contract: 1, // <--- changed to v1 (for token insertion + insert_contract: 1, // <--- changed to v1 (for token insertion) }, update: DriveContractUpdateMethodVersions { update_contract: 1 }, // <--- changed to v1 (for token insertion) costs: DriveContractCostsMethodVersions { diff --git a/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs b/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs index cc444b25e9d..6da698cea2e 100644 --- a/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs +++ b/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs @@ -10,4 +10,6 @@ pub struct SystemDataContractVersions { pub masternode_reward_shares: FeatureVersion, pub feature_flags: FeatureVersion, pub wallet: FeatureVersion, + pub token_history: FeatureVersion, + pub search: FeatureVersion, } diff --git a/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs b/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs index a55db9a296b..375ebe521b5 100644 --- a/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs +++ b/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs @@ -8,4 +8,6 @@ pub const SYSTEM_DATA_CONTRACT_VERSIONS_V1: SystemDataContractVersions = masternode_reward_shares: 1, feature_flags: 1, wallet: 1, + token_history: 1, + search: 1, }; diff --git a/packages/search-contract/src/lib.rs b/packages/search-contract/src/lib.rs index f7767ea6c26..47c5cb9816f 100644 --- a/packages/search-contract/src/lib.rs +++ b/packages/search-contract/src/lib.rs @@ -16,7 +16,7 @@ pub const OWNER_ID_BYTES: [u8; 32] = [0; 32]; pub const ID: Identifier = Identifier(IdentifierBytes32(ID_BYTES)); pub const OWNER_ID: Identifier = Identifier(IdentifierBytes32(OWNER_ID_BYTES)); pub fn load_definitions(platform_version: &PlatformVersion) -> Result, Error> { - match platform_version.system_data_contracts.withdrawals { + match platform_version.system_data_contracts.search { 1 => Ok(None), version => Err(Error::UnknownVersionMismatch { method: "search_contract::load_definitions".to_string(), @@ -26,7 +26,7 @@ pub fn load_definitions(platform_version: &PlatformVersion) -> Result Result { - match platform_version.system_data_contracts.withdrawals { + match platform_version.system_data_contracts.search { 1 => v1::load_documents_schemas(), version => Err(Error::UnknownVersionMismatch { method: "search_contract::load_documents_schemas".to_string(), diff --git a/packages/token-history-contract/src/lib.rs b/packages/token-history-contract/src/lib.rs index 3bf08b2e25b..e176a5a61f3 100644 --- a/packages/token-history-contract/src/lib.rs +++ b/packages/token-history-contract/src/lib.rs @@ -16,20 +16,20 @@ pub const OWNER_ID_BYTES: [u8; 32] = [0; 32]; pub const ID: Identifier = Identifier(IdentifierBytes32(ID_BYTES)); pub const OWNER_ID: Identifier = Identifier(IdentifierBytes32(OWNER_ID_BYTES)); pub fn load_definitions(platform_version: &PlatformVersion) -> Result, Error> { - match platform_version.system_data_contracts.withdrawals { + match platform_version.system_data_contracts.token_history { 1 => Ok(None), version => Err(Error::UnknownVersionMismatch { - method: "wallet_contract::load_definitions".to_string(), + method: "token_history_contract::load_definitions".to_string(), known_versions: vec![1], received: version, }), } } pub fn load_documents_schemas(platform_version: &PlatformVersion) -> Result { - match platform_version.system_data_contracts.withdrawals { + match platform_version.system_data_contracts.token_history { 1 => v1::load_documents_schemas(), version => Err(Error::UnknownVersionMismatch { - method: "wallet_contract::load_documents_schemas".to_string(), + method: "token_history_contract::load_documents_schemas".to_string(), known_versions: vec![1], received: version, }), From 65a4b612c8c9e832dd239b1f2ad5fc32556daac6 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 01:08:52 +0700 Subject: [PATCH 02/46] local network builds, deserialization of st fails --- .pnp.cjs | 23 ++++ Cargo.toml | 3 +- Dockerfile | 109 +++++++++--------- package.json | 3 +- .../create_genesis_state/v1/mod.rs | 4 + .../v0/mod.rs | 15 ++- .../contract/insert/add_new_keywords/mod.rs | 12 +- .../insert/add_new_keywords/v0/mod.rs | 97 ++++++++++++---- .../contract/insert/insert_contract/v1/mod.rs | 2 +- packages/search-contract/Cargo.toml | 2 +- .../schema/v1/search-contract-documents.json | 38 ++++-- yarn.lock | 16 +++ 12 files changed, 229 insertions(+), 95 deletions(-) diff --git a/.pnp.cjs b/.pnp.cjs index c92c2a3a410..473a9c1079f 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -65,6 +65,10 @@ const RAW_RUNTIME_STATE = "name": "@dashevo/platform-test-suite",\ "reference": "workspace:packages/platform-test-suite"\ },\ + {\ + "name": "@dashevo/search-contract",\ + "reference": "workspace:packages/search-contract"\ + },\ {\ "name": "@dashevo/token-history-contract",\ "reference": "workspace:packages/token-history-contract"\ @@ -101,6 +105,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/masternode-reward-shares-contract", ["workspace:packages/masternode-reward-shares-contract"]],\ ["@dashevo/platform", ["workspace:."]],\ ["@dashevo/platform-test-suite", ["workspace:packages/platform-test-suite"]],\ + ["@dashevo/search-contract", ["workspace:packages/search-contract"]],\ ["@dashevo/token-history-contract", ["workspace:packages/token-history-contract"]],\ ["@dashevo/wallet-lib", ["workspace:packages/wallet-lib"]],\ ["@dashevo/wallet-utils-contract", ["workspace:packages/wallet-utils-contract"]],\ @@ -2879,6 +2884,24 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@dashevo/search-contract", [\ + ["workspace:packages/search-contract", {\ + "packageLocation": "./packages/search-contract/",\ + "packageDependencies": [\ + ["@dashevo/search-contract", "workspace:packages/search-contract"],\ + ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ + ["chai", "npm:4.3.10"],\ + ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ + ["eslint", "npm:8.53.0"],\ + ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ + ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ + ["mocha", "npm:11.1.0"],\ + ["sinon", "npm:17.0.1"],\ + ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@dashevo/token-history-contract", [\ ["workspace:packages/token-history-contract", {\ "packageLocation": "./packages/token-history-contract/",\ diff --git a/Cargo.toml b/Cargo.toml index 1dd2d2ecdbf..92dca6d948d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,8 @@ members = [ "packages/rs-json-schema-compatibility-validator", "packages/check-features", "packages/wallet-utils-contract", - "packages/token-history-contract" + "packages/token-history-contract", + "packages/search-contract" ] exclude = ["packages/wasm-sdk"] # This one is experimental and not ready for use diff --git a/Dockerfile b/Dockerfile index 47e7e5a77fe..b5fb55bfd85 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,25 +68,25 @@ FROM node:20-alpine${ALPINE_VERSION} AS deps-base # Install some dependencies # RUN apk add --no-cache \ - alpine-sdk \ - bash \ - binutils \ - ca-certificates \ - clang-static clang-dev \ - cmake \ - curl \ - git \ - libc-dev \ - linux-headers \ - llvm-static llvm-dev \ - openssl-dev \ - snappy-static snappy-dev \ - perl \ - python3 \ - unzip \ - wget \ - xz \ - zeromq-dev + alpine-sdk \ + bash \ + binutils \ + ca-certificates \ + clang-static clang-dev \ + cmake \ + curl \ + git \ + libc-dev \ + linux-headers \ + llvm-static llvm-dev \ + openssl-dev \ + snappy-static snappy-dev \ + perl \ + python3 \ + unzip \ + wget \ + xz \ + zeromq-dev # Configure snappy, dependency of librocksdb-sys RUN <> /platform/packages/dapi-grpc/build.rs && \ cargo build \ - --profile "${CARGO_BUILD_PROFILE}" \ - --package drive-abci \ - ${FEATURES_FLAG} \ - --locked && \ + --profile "${CARGO_BUILD_PROFILE}" \ + --package drive-abci \ + ${FEATURES_FLAG} \ + --locked && \ cp target/${OUT_DIRECTORY}/drive-abci /artifacts/ && \ if [[ -x /usr/bin/sccache ]]; then sccache --show-stats; fi && \ # Remove /platform to reduce layer size @@ -523,11 +525,11 @@ RUN --mount=type=cache,sharing=shared,id=cargo_registry_index,target=${CARGO_HOM source /root/env && \ unset CFLAGS CXXFLAGS && \ cargo chef cook \ - --recipe-path recipe.json \ - --profile "$CARGO_BUILD_PROFILE" \ - --package wasm-dpp \ - --target wasm32-unknown-unknown \ - --locked && \ + --recipe-path recipe.json \ + --profile "$CARGO_BUILD_PROFILE" \ + --package wasm-dpp \ + --target wasm32-unknown-unknown \ + --locked && \ if [[ -x /usr/bin/sccache ]]; then sccache --show-stats; fi @@ -551,6 +553,7 @@ COPY --parents \ packages/withdrawals-contract \ packages/wallet-utils-contract \ packages/token-history-contract \ + packages/search-contract \ packages/masternode-reward-shares-contract \ packages/feature-flags-contract \ packages/dpns-contract \ @@ -674,6 +677,7 @@ COPY --from=build-dashmate-helper /platform/packages/dapi-grpc packages/dapi-grp COPY --from=build-dashmate-helper /platform/packages/dash-spv packages/dash-spv COPY --from=build-dashmate-helper /platform/packages/wallet-utils-contract packages/wallet-utils-contract COPY --from=build-dashmate-helper /platform/packages/token-history-contract packages/token-history-contract +COPY --from=build-dashmate-helper /platform/packages/search-contract packages/search-contract COPY --from=build-dashmate-helper /platform/packages/withdrawals-contract packages/withdrawals-contract COPY --from=build-dashmate-helper /platform/packages/masternode-reward-shares-contract packages/masternode-reward-shares-contract COPY --from=build-dashmate-helper /platform/packages/feature-flags-contract packages/feature-flags-contract @@ -750,6 +754,7 @@ COPY --from=build-dapi /platform/packages/dapi-grpc /platform/packages/dapi-grpc COPY --from=build-dapi /platform/packages/js-grpc-common /platform/packages/js-grpc-common COPY --from=build-dapi /platform/packages/wasm-dpp /platform/packages/wasm-dpp COPY --from=build-dapi /platform/packages/token-history-contract /platform/packages/token-history-contract +COPY --from=build-dapi /platform/packages/search-contract /platform/packages/search-contract RUN cp /platform/packages/dapi/.env.example /platform/packages/dapi/.env diff --git a/package.json b/package.json index 091c572b30d..ea3156fbfdb 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "packages/dash-spv", "packages/wasm-dpp", "packages/withdrawals-contract", - "packages/token-history-contract" + "packages/token-history-contract", + "packages/search-contract" ], "resolutions": { "elliptic": "6.5.7", diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs index d6a1cf70396..725cef56a44 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs @@ -51,6 +51,10 @@ impl Platform { SystemDataContract::TokenHistory, system_data_contracts.load_token_history(), ), + ( + SystemDataContract::Search, + system_data_contracts.load_search(), + ), ]); //todo add Wallet Utils (maybe) 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 1557075db17..6422b858408 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 @@ -475,11 +475,22 @@ impl Platform { &platform_version.drive, )?; - let contract = + let token_history_contract = load_system_data_contract(SystemDataContract::TokenHistory, platform_version)?; self.drive.insert_contract( - &contract, + &token_history_contract, + *block_info, + true, + Some(transaction), + platform_version, + )?; + + let search_contract = + load_system_data_contract(SystemDataContract::Search, platform_version)?; + + self.drive.insert_contract( + &search_contract, *block_info, true, Some(transaction), diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index 494807c30c4..6211ccaa09c 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -15,7 +15,7 @@ mod v0; impl Drive { /// Adds keywords to the state. - pub fn add_new_keywords( + pub fn add_new_contract_keywords( &self, contract_id: Identifier, owner_id: Identifier, @@ -35,7 +35,7 @@ impl Drive { 1 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 2 => self.add_new_keywords_v0( + 2 => self.add_new_contract_keywords_v0( contract_id, owner_id, keywords, @@ -53,7 +53,7 @@ impl Drive { } /// Adds keywords creation operations to drive operations - pub fn add_new_keywords_add_to_operations( + pub fn add_new_contract_keywords_add_to_operations( &self, contract_id: Identifier, owner_id: Identifier, @@ -74,7 +74,7 @@ impl Drive { 1 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 2 => self.add_new_keywords_add_to_operations_v0( + 2 => self.add_new_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -93,7 +93,7 @@ impl Drive { } /// The operations needed to create keywords - pub fn add_new_keywords_operations( + pub fn add_new_contract_keywords_operations( &self, contract_id: Identifier, owner_id: Identifier, @@ -115,7 +115,7 @@ impl Drive { 1 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 2 => self.add_new_keywords_operations_v0( + 2 => self.add_new_contract_keywords_operations_v0( contract_id, owner_id, keywords, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 31ab9443923..7784d9b2409 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -5,16 +5,17 @@ use crate::util::object_size_info::DocumentInfo::DocumentOwnedInfo; use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::document::{Document, DocumentV0}; use dpp::fee::fee_result::FeeResult; use dpp::identifier::Identifier; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use platform_version::version::PlatformVersion; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; impl Drive { /// Adds a keyword by inserting a new keyword subtree structure to the `Identities` subtree. - pub(super) fn add_new_keywords_v0( + pub(super) fn add_new_contract_keywords_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -25,7 +26,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.add_new_keywords_add_to_operations_v0( + self.add_new_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -47,7 +48,7 @@ impl Drive { } /// Adds keyword creation operations to drive operations - pub(super) fn add_new_keywords_add_to_operations_v0( + pub(super) fn add_new_contract_keywords_add_to_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -64,7 +65,7 @@ impl Drive { Some(HashMap::new()) }; - let batch_operations = self.add_new_keywords_operations( + let batch_operations = self.add_new_contract_keywords_operations( contract_id, owner_id, keywords, @@ -84,7 +85,7 @@ impl Drive { } /// The operations needed to create a keyword - pub(super) fn add_new_keywords_operations_v0( + pub(super) fn add_new_contract_keywords_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -97,29 +98,77 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result, Error> { let contract = self.cache.system_data_contracts.load_search(); - let document_type = contract.document_type_for_name("contract")?; - let document = - build_keyword_document_owned(contract_id, owner_id, keywords, platform_version)?; + let mut operations: Vec = vec![]; + + for keyword in keywords { + let document = self.build_contract_keyword_document_owned_v0( + contract_id, + owner_id, + keyword, + block_info, + )?; - let operations = self.add_document_for_contract_operations( - DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentOwnedInfo((document, None)), - owner_id: Some(owner_id.to_buffer()), + let ops = self.add_document_for_contract_operations( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentOwnedInfo((document, None)), + owner_id: Some(owner_id.to_buffer()), + }, + contract: &contract, + document_type, }, - contract: &contract, - document_type, - }, - true, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - )?; + true, + block_info, + &mut None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + operations.extend(ops); + } Ok(operations) } + + pub(super) fn build_contract_keyword_document_owned_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keyword: &String, + block_info: &BlockInfo, + ) -> Result { + let document_id = Document::generate_document_id_v0( + &contract_id, + &owner_id, + "contract", + 0u64.to_be_bytes().as_slice(), + ); + + let properties = BTreeMap::from([ + ("keyword".to_string(), keyword.into()), + ("contractId".to_string(), contract_id.into()), + ]); + + let document: Document = DocumentV0 { + id: document_id, + owner_id, + properties, + revision: None, + created_at: Some(block_info.time_ms), + updated_at: None, + transferred_at: None, + created_at_block_height: Some(block_info.height), + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + + Ok(document) + } } 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 8faeae29cb8..59a30e76062 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 @@ -308,7 +308,7 @@ impl Drive { } if !contract.keywords().is_empty() { - batch_operations.extend(self.add_new_keywords_operations( + batch_operations.extend(self.add_new_contract_keywords_operations( contract.id(), contract.owner_id(), contract.keywords(), diff --git a/packages/search-contract/Cargo.toml b/packages/search-contract/Cargo.toml index 675a039cc3d..5d33b3db642 100644 --- a/packages/search-contract/Cargo.toml +++ b/packages/search-contract/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "search-contract" -description = "Search data contract schema and tools. Search contract is using to find other contracts and tokens" +description = "Search data contract schema and tools. Search contract is used to find other contracts and tokens" version = "2.0.0-dev.1" edition = "2021" rust-version.workspace = true diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/search-contract/schema/v1/search-contract-documents.json index f146ecb3e6c..5b68486f445 100644 --- a/packages/search-contract/schema/v1/search-contract-documents.json +++ b/packages/search-contract/schema/v1/search-contract-documents.json @@ -7,12 +7,16 @@ "creationRestrictionMode": 2, "indices": [ { - "name": "byKeyword", + "name": "byKeywordAndContractId", "properties": [ { "keyword": "asc" + }, + { + "contractId": "asc" } - ] + ], + "unique": true } ], "properties": { @@ -21,10 +25,18 @@ "minLength": 3, "maxLength": 50, "position": 0 + }, + "contractId": { + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 1, + "contentMediaType": "application/x.dash.dpp.identifier" } }, "required": [ - "$contractId", + "contractId", "keyword" ], "additionalProperties": false @@ -37,12 +49,16 @@ "creationRestrictionMode": 2, "indices": [ { - "name": "byKeyword", + "name": "byKeywordAndTokenId", "properties": [ { "keyword": "asc" + }, + { + "tokenId": "asc" } - ] + ], + "unique": true } ], "properties": { @@ -51,12 +67,20 @@ "minLength": 3, "maxLength": 50, "position": 0 + }, + "tokenId": { + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 1, + "contentMediaType": "application/x.dash.dpp.identifier" } }, "required": [ - "$tokenId", + "tokenId", "keyword" ], "additionalProperties": false } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9c01abcf7d1..7597309d082 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1854,6 +1854,22 @@ __metadata: languageName: node linkType: hard +"@dashevo/search-contract@workspace:packages/search-contract": + version: 0.0.0-use.local + resolution: "@dashevo/search-contract@workspace:packages/search-contract" + dependencies: + "@dashevo/wasm-dpp": "workspace:*" + chai: "npm:^4.3.10" + dirty-chai: "npm:^2.0.1" + eslint: "npm:^8.53.0" + eslint-config-airbnb-base: "npm:^15.0.0" + eslint-plugin-import: "npm:^2.29.0" + mocha: "npm:^11.1.0" + sinon: "npm:^17.0.1" + sinon-chai: "npm:^3.7.0" + languageName: unknown + linkType: soft + "@dashevo/token-history-contract@workspace:*, @dashevo/token-history-contract@workspace:packages/token-history-contract": version: 0.0.0-use.local resolution: "@dashevo/token-history-contract@workspace:packages/token-history-contract" From dc74e5a53bee83afee32a643884cd7440817832f Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 01:25:24 +0700 Subject: [PATCH 03/46] fix --- .../drive/contract/insert/add_new_keywords/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index 6211ccaa09c..2b3f19cb329 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -32,10 +32,10 @@ impl Drive { .insert .insert_contract { - 1 => Err(Error::Drive(DriveError::NotSupported( + 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 2 => self.add_new_contract_keywords_v0( + 1 => self.add_new_contract_keywords_v0( contract_id, owner_id, keywords, @@ -71,10 +71,10 @@ impl Drive { .insert .insert_contract { - 1 => Err(Error::Drive(DriveError::NotSupported( + 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 2 => self.add_new_contract_keywords_add_to_operations_v0( + 1 => self.add_new_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -112,10 +112,10 @@ impl Drive { .insert .insert_contract { - 1 => Err(Error::Drive(DriveError::NotSupported( + 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 2 => self.add_new_contract_keywords_operations_v0( + 1 => self.add_new_contract_keywords_operations_v0( contract_id, owner_id, keywords, From a636eee657a1c3f793c78e8c8d81b71c4bd473e5 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 01:39:43 +0700 Subject: [PATCH 04/46] fix: search contract base58 id --- packages/search-contract/lib/systemIds.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/search-contract/lib/systemIds.js b/packages/search-contract/lib/systemIds.js index 7335d3d1635..f1aa5b80c07 100644 --- a/packages/search-contract/lib/systemIds.js +++ b/packages/search-contract/lib/systemIds.js @@ -1,4 +1,4 @@ module.exports = { ownerId: '11111111111111111111111111111111', - contractId: '8v8CoKCDdBcQu1Y7GDNJjR7a5vkMmgpXycJURkaUhfU9', + contractId: '7CSFGeF4WNzgDmx94zwvHkYaG3Dx4XEe5LFsFgJswLbm', }; From 485df310f6eef61f6b8aa6efcd3608514c05b5f1 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 02:02:29 +0700 Subject: [PATCH 05/46] fix non unique document id --- .../src/drive/contract/insert/add_new_keywords/v0/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 7784d9b2409..4eee6da28d3 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -102,11 +102,12 @@ impl Drive { let mut operations: Vec = vec![]; - for keyword in keywords { + for (i, keyword) in keywords.iter().enumerate() { let document = self.build_contract_keyword_document_owned_v0( contract_id, owner_id, keyword, + i as u64, block_info, )?; @@ -138,13 +139,14 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, keyword: &String, + keyword_index: u64, block_info: &BlockInfo, ) -> Result { let document_id = Document::generate_document_id_v0( &contract_id, &owner_id, "contract", - 0u64.to_be_bytes().as_slice(), + keyword_index.to_be_bytes().as_slice(), ); let properties = BTreeMap::from([ From 10ec7fd70dfe53fd59b530258aed005dbad05b31 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 02:11:00 +0700 Subject: [PATCH 06/46] add back byKeyword index --- .../schema/v1/search-contract-documents.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/search-contract/schema/v1/search-contract-documents.json index 5b68486f445..9d061f4910a 100644 --- a/packages/search-contract/schema/v1/search-contract-documents.json +++ b/packages/search-contract/schema/v1/search-contract-documents.json @@ -6,6 +6,14 @@ "referenceType": "contract", "creationRestrictionMode": 2, "indices": [ + { + "name": "byKeyword", + "properties": [ + { + "keyword": "asc" + } + ] + }, { "name": "byKeywordAndContractId", "properties": [ @@ -48,6 +56,14 @@ "referenceType": "token", "creationRestrictionMode": 2, "indices": [ + { + "name": "byKeyword", + "properties": [ + { + "keyword": "asc" + } + ] + }, { "name": "byKeywordAndTokenId", "properties": [ From 0ace4f9a8ec4fb12736068504a4b2143fd5dcf06 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 03:05:29 +0700 Subject: [PATCH 07/46] enforce max keywords in document meta schema --- .../document/v0/document-meta.json | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json b/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json index 5570d74da3c..78bbeccef3b 100644 --- a/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json +++ b/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json @@ -227,7 +227,9 @@ "properties": { "position": true }, - "required": ["position"] + "required": [ + "position" + ] } } } @@ -420,7 +422,9 @@ "maxLength": 256 } }, - "required": ["resolution"], + "required": [ + "resolution" + ], "additionalProperties": false } }, @@ -580,6 +584,17 @@ "type": "string" } }, + "keywords": { + "type": "array", + "description": "List of up to 20 descriptive keywords for the contract, used in the Keyword Search contract", + "items": { + "type": "string", + "minLength": 3, + "maxLength": 50 + }, + "maxItems": 20, + "uniqueItems": true + }, "additionalProperties": { "type": "boolean", "const": false @@ -591,4 +606,4 @@ "properties", "additionalProperties" ] -} +} \ No newline at end of file From cff2d75931d93b681b32b4775c548027a6568633 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 03:07:56 +0700 Subject: [PATCH 08/46] remove token keywords from schema --- .../schema/v1/search-contract-documents.json | 50 ------------------- packages/search-contract/src/v1/mod.rs | 8 --- 2 files changed, 58 deletions(-) diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/search-contract/schema/v1/search-contract-documents.json index 9d061f4910a..25a468e7e34 100644 --- a/packages/search-contract/schema/v1/search-contract-documents.json +++ b/packages/search-contract/schema/v1/search-contract-documents.json @@ -48,55 +48,5 @@ "keyword" ], "additionalProperties": false - }, - "token": { - "type": "object", - "documentsMutable": false, - "canBeDeleted": false, - "referenceType": "token", - "creationRestrictionMode": 2, - "indices": [ - { - "name": "byKeyword", - "properties": [ - { - "keyword": "asc" - } - ] - }, - { - "name": "byKeywordAndTokenId", - "properties": [ - { - "keyword": "asc" - }, - { - "tokenId": "asc" - } - ], - "unique": true - } - ], - "properties": { - "keyword": { - "type": "string", - "minLength": 3, - "maxLength": 50, - "position": 0 - }, - "tokenId": { - "type": "array", - "byteArray": true, - "minItems": 32, - "maxItems": 32, - "position": 1, - "contentMediaType": "application/x.dash.dpp.identifier" - } - }, - "required": [ - "tokenId", - "keyword" - ], - "additionalProperties": false } } \ No newline at end of file diff --git a/packages/search-contract/src/v1/mod.rs b/packages/search-contract/src/v1/mod.rs index e5d6a067712..c237ea3343d 100644 --- a/packages/search-contract/src/v1/mod.rs +++ b/packages/search-contract/src/v1/mod.rs @@ -9,14 +9,6 @@ pub mod document_types { pub const KEY_INDEX: &str = "byKeyword"; } } - - pub mod token { - pub const NAME: &str = "token"; - - pub mod properties { - pub const KEY_INDEX: &str = "byKeyword"; - } - } } pub fn load_documents_schemas() -> Result { From 206872f7bd6e4c6ddd08e59f23e0bfe5e5f49e77 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 16:12:49 +0700 Subject: [PATCH 09/46] validation is working --- .../data_contract/serialized_version/mod.rs | 9 + .../src/errors/consensus/basic/basic_error.rs | 7 + .../consensus/basic/data_contract/mod.rs | 4 + packages/rs-dpp/src/errors/consensus/codes.rs | 2 + .../advanced_structure/v0/mod.rs | 42 +++ .../data_contract_create/mod.rs | 294 ++++++++++++++++++ .../schema/v1/search-contract-documents.json | 12 - .../src/errors/consensus/consensus_error.rs | 8 +- 8 files changed, 365 insertions(+), 13 deletions(-) diff --git a/packages/rs-dpp/src/data_contract/serialized_version/mod.rs b/packages/rs-dpp/src/data_contract/serialized_version/mod.rs index 5595f288a39..cfc34db8115 100644 --- a/packages/rs-dpp/src/data_contract/serialized_version/mod.rs +++ b/packages/rs-dpp/src/data_contract/serialized_version/mod.rs @@ -21,6 +21,8 @@ use platform_versioning::PlatformVersioned; #[cfg(feature = "data-contract-serde-conversion")] use serde::{Deserialize, Serialize}; +use super::EMPTY_KEYWORDS; + pub(in crate::data_contract) mod v0; pub(in crate::data_contract) mod v1; @@ -97,6 +99,13 @@ impl DataContractInSerializationFormat { } } + pub fn keywords(&self) -> &Vec { + match self { + DataContractInSerializationFormat::V0(_) => &EMPTY_KEYWORDS, + DataContractInSerializationFormat::V1(v1) => &v1.keywords, + } + } + pub fn eq_without_auto_fields(&self, other: &Self) -> bool { match (self, other) { ( diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index 9c883845be4..463a8a21e3e 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -75,6 +75,7 @@ use crate::consensus::basic::{ }; use crate::consensus::ConsensusError; +use super::data_contract::{DuplicateKeywordsError, TooManyKeywordsError}; use crate::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use crate::consensus::basic::overflow_error::OverflowError; use crate::consensus::basic::token::{ @@ -205,6 +206,12 @@ pub enum BasicError { #[error(transparent)] DataContractHaveNewUniqueIndexError(DataContractHaveNewUniqueIndexError), + #[error(transparent)] + TooManyKeywordsError(TooManyKeywordsError), + + #[error(transparent)] + DuplicateKeywordsError(DuplicateKeywordsError), + // Document #[error(transparent)] DataContractNotPresentError(DataContractNotPresentError), diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs index cb59f46d74d..c41777979f7 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -9,6 +9,7 @@ mod data_contract_unique_indices_changed_error; mod document_types_are_missing_error; mod duplicate_index_error; mod duplicate_index_name_error; +mod duplicate_keywords_error; mod group_exceeds_max_members_error; mod group_member_has_power_of_zero_error; mod group_member_has_power_over_limit_error; @@ -31,6 +32,7 @@ mod invalid_token_distribution_function_divide_by_zero_error; mod invalid_token_distribution_function_incoherence_error; mod invalid_token_distribution_function_invalid_parameter_error; mod invalid_token_distribution_function_invalid_parameter_tuple_error; +mod keywords_over_limit; mod non_contiguous_contract_group_positions_error; mod non_contiguous_contract_token_positions_error; mod system_property_index_already_present_error; @@ -69,6 +71,7 @@ pub use unique_indices_limit_reached_error::*; pub use contested_unique_index_on_mutable_document_type_error::*; pub use contested_unique_index_with_unique_index_error::*; +pub use duplicate_keywords_error::*; pub use group_exceeds_max_members_error::*; pub use group_member_has_power_of_zero_error::*; pub use group_member_has_power_over_limit_error::*; @@ -82,6 +85,7 @@ pub use invalid_token_distribution_function_divide_by_zero_error::*; pub use invalid_token_distribution_function_incoherence_error::*; pub use invalid_token_distribution_function_invalid_parameter_error::*; pub use invalid_token_distribution_function_invalid_parameter_tuple_error::*; +pub use keywords_over_limit::*; pub use non_contiguous_contract_group_positions_error::*; pub use non_contiguous_contract_token_positions_error::*; pub use token_payment_by_burning_only_allowed_on_internal_token_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index f58b0f07ccb..9ebc2a7a691 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -106,6 +106,8 @@ impl ErrorWithCode for BasicError { Self::UnknownGasFeesPaidByError(_) => 10259, Self::UnknownDocumentActionTokenEffectError(_) => 10260, Self::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(_) => 10261, + Self::TooManyKeywordsError(_) => 10262, + Self::DuplicateKeywordsError(_) => 10263, // Group Errors: 10350-10399 Self::GroupPositionDoesNotExistError(_) => 10350, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs index 5f2db600793..78791ca5c29 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs @@ -1,15 +1,21 @@ +use std::collections::HashSet; + use crate::error::Error; use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; +use dpp::consensus::basic::data_contract::DuplicateKeywordsError; +use dpp::consensus::basic::data_contract::TooManyKeywordsError; use dpp::consensus::basic::data_contract::{ InvalidDataContractIdError, InvalidDataContractVersionError, InvalidTokenBaseSupplyError, NonContiguousContractTokenPositionsError, }; use dpp::consensus::basic::BasicError; +use dpp::consensus::ConsensusError; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; use dpp::data_contract::{TokenContractPosition, INITIAL_DATA_CONTRACT_VERSION}; +use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::DataContract; use dpp::state_transition::data_contract_create_transition::accessors::DataContractCreateTransitionAccessorsV0; use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; @@ -148,6 +154,42 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 } } + // Validate there are no more than 20 keywords + if self.data_contract().keywords().len() > 20 { + let bump_action = StateTransitionAction::BumpIdentityNonceAction( + BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), + ); + + return Ok(ConsensusValidationResult::new_with_data_and_errors( + bump_action, + vec![ConsensusError::BasicError( + BasicError::TooManyKeywordsError(TooManyKeywordsError::new( + self.data_contract().id().to_string(Encoding::Base58), + self.data_contract().keywords().len() as u8, + )), + )], + )); + } + // Validate the keywords are all unique + let mut seen_keywords = HashSet::new(); + for keyword in self.data_contract().keywords() { + if !seen_keywords.insert(keyword) { + let bump_action = StateTransitionAction::BumpIdentityNonceAction( + BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), + ); + + return Ok(ConsensusValidationResult::new_with_data_and_errors( + bump_action, + vec![ConsensusError::BasicError( + BasicError::DuplicateKeywordsError(DuplicateKeywordsError::new( + self.data_contract().id().to_string(Encoding::Base58), + keyword.to_string(), + )), + )], + )); + } + } + Ok(ConsensusValidationResult::default()) } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index b8b2a41aa6e..2837afd2feb 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2447,4 +2447,298 @@ mod tests { assert_eq!(token_balance, None); } } + + mod keywords { + use super::*; + use dpp::{ + data_contract::conversion::value::v0::DataContractValueConversionMethodsV0, + platform_value::string_encoding::Encoding, + }; + + #[test] + fn test_data_contract_creation_fails_with_more_than_twenty_keywords() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + // Create a test identity and keys + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // Load the base contract JSON and convert it to `DataContract` + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + // Convert the contract back to Value so we can mutate its fields + let mut contract_value = data_contract + .to_value(PlatformVersion::latest()) + .expect("to_value failed"); + + // Insert 21 keywords to exceed the max limit + let mut excessive_keywords: Vec = vec![]; + for i in 0..21 { + excessive_keywords.push(Value::Text(format!("keyword{}", i))); + } + contract_value["keywords"] = Value::Array(excessive_keywords); + + // Build a new DataContract from the mutated Value + let data_contract_with_excessive_keywords = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract from Value"); + + // Create the DataContractCreateTransition + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract_with_excessive_keywords, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create data contract transition"); + + // Serialize the transition + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected a serialized data contract transition"); + + let transaction = platform.drive.grove.start_transaction(); + + // Process the state transition + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + // We expect a failure due to the JSON schema rejecting >20 keywords + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::TooManyKeywordsError(_)), + _ + )] + ); + } + + #[test] + fn test_data_contract_creation_fails_with_duplicate_keywords() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + // Create a test identity and keys + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // Load the base contract JSON and convert it to `DataContract` + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + // Convert to Value to mutate fields + let mut contract_value = data_contract + .to_value(PlatformVersion::latest()) + .expect("to_value failed"); + + // Insert some duplicates + let duplicated_keywords = vec!["keyword1", "keyword2", "keyword2"]; + contract_value["keywords"] = Value::Array( + duplicated_keywords + .into_iter() + .map(|str| Value::Text(str.to_string())) + .collect(), + ); + + // Build a new DataContract from the mutated Value + let data_contract_with_duplicates = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract from Value"); + + // Create the DataContractCreateTransition + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract_with_duplicates, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create data contract transition"); + + // Serialize the transition + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected a serialized data contract transition"); + + let transaction = platform.drive.grove.start_transaction(); + + // Process the state transition + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + // Expect failure + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::DuplicateKeywordsError(_)), + _ + )] + ); + } + + #[test] + fn test_data_contract_creation_succeeds_with_valid_keywords() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + // Create a test identity and keys + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // Load the base contract JSON and convert to `DataContract` + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + // Convert to Value so we can adjust fields if needed + let mut contract_value = data_contract + .to_value(PlatformVersion::latest()) + .expect("to_value failed"); + + // Insert a valid set of keywords: all distinct, fewer than 20 + let valid_keywords = vec!["k1", "k2", "k3"]; + contract_value["keywords"] = Value::Array( + valid_keywords + .into_iter() + .map(|str| Value::Text(str.to_string())) + .collect(), + ); + + // Build a new DataContract from the mutated Value + let data_contract_valid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract from Value"); + + // Create the DataContractCreateTransition + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract_valid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create data contract transition"); + + // Serialize the transition + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected a serialized data contract transition"); + + let transaction = platform.drive.grove.start_transaction(); + + // Process the state transition + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + // This time we expect success + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + // Commit the transaction since it's valid + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Get the data contract ID from the transition + let unique_identifiers = data_contract_create_transition.unique_identifiers(); + let unique_identifier = unique_identifiers + .first() + .expect("expected at least one unique identifier"); + let unique_identifier_str = unique_identifier.as_str(); + let data_contract_id_str = unique_identifier_str + .split('-') + .last() + .expect("expected to extract data contract id from unique identifier"); + let data_contract_id = Identifier::from_string(data_contract_id_str, Encoding::Base58) + .expect("failed to create Identifier from string"); + + // Fetch the contract from the platform + let contract = platform + .drive + .fetch_contract(data_contract_id.into(), None, None, None, platform_version) + .value + .expect("expected to get contract") + .expect("expected to find the contract"); + + // Check the keywords in the contract + let keywords = contract.contract.keywords(); + assert_eq!(keywords.len(), 3); + assert_eq!(keywords[0], "k1"); + assert_eq!(keywords[1], "k2"); + assert_eq!(keywords[2], "k3"); + } + } } diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/search-contract/schema/v1/search-contract-documents.json index 25a468e7e34..2f7be903882 100644 --- a/packages/search-contract/schema/v1/search-contract-documents.json +++ b/packages/search-contract/schema/v1/search-contract-documents.json @@ -13,18 +13,6 @@ "keyword": "asc" } ] - }, - { - "name": "byKeywordAndContractId", - "properties": [ - { - "keyword": "asc" - }, - { - "contractId": "asc" - } - ], - "unique": true } ], "properties": { diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 33d3d1b2d13..bd3619abd1e 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError, }; use wasm_bindgen::{JsError, JsValue}; -use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; +use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; @@ -761,6 +761,12 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(e) => { generic_consensus_error!(TokenPaymentByBurningOnlyAllowedOnInternalTokenError, e).into() } + BasicError::TooManyKeywordsError(e) => { + generic_consensus_error!(TooManyKeywordsError, e).into() + } + BasicError::DuplicateKeywordsError(e) => { + generic_consensus_error!(DuplicateKeywordsError, e).into() + } } } From c9af4a6bacff397500e2c6bdcb775b179f82521f Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 17:38:10 +0700 Subject: [PATCH 10/46] validation works --- .../data_contract/duplicate_keywords_error.rs | 44 ++++ .../data_contract/keywords_over_limit.rs | 44 ++++ .../keyword_test/keyword_base_contract.json | 193 ++++++++++++++++++ 3 files changed, 281 insertions(+) create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs create mode 100644 packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs new file mode 100644 index 00000000000..d35591a6fc6 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs @@ -0,0 +1,44 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Data contract {contract_id} has duplicated keyword '{keyword}'.")] +#[platform_serialize(unversioned)] +pub struct DuplicateKeywordsError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + contract_id: String, + keyword: String, +} + +impl DuplicateKeywordsError { + pub fn new(contract_id: String, keyword: String) -> Self { + Self { + contract_id, + keyword, + } + } + + pub fn contract_id(&self) -> &str { + &self.contract_id + } + + pub fn keyword(&self) -> &str { + &self.keyword + } +} + +impl From for ConsensusError { + fn from(err: DuplicateKeywordsError) -> Self { + Self::BasicError(BasicError::DuplicateKeywordsError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs new file mode 100644 index 00000000000..36b069f7cbb --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs @@ -0,0 +1,44 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Data contract {contract_id} has too many keywords: '{keywords_len}'. The maximum is 20.")] +#[platform_serialize(unversioned)] +pub struct TooManyKeywordsError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + contract_id: String, + keywords_len: u8, +} + +impl TooManyKeywordsError { + pub fn new(contract_id: String, keywords_len: u8) -> Self { + Self { + contract_id, + keywords_len, + } + } + + pub fn contract_id(&self) -> &str { + &self.contract_id + } + + pub fn keywords_len(&self) -> &u8 { + &self.keywords_len + } +} + +impl From for ConsensusError { + fn from(err: TooManyKeywordsError) -> Self { + Self::BasicError(BasicError::TooManyKeywordsError(err)) + } +} diff --git a/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json b/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json new file mode 100644 index 00000000000..323e27eff7d --- /dev/null +++ b/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json @@ -0,0 +1,193 @@ +{ + "$format_version": "1", + "id": "4Bqs6itzfoDXzmgQibYZQABbqYsXmawVf7SKe3mKDQVd", + "config": { + "$format_version": "1", + "canBeDeleted": false, + "readonly": false, + "keepsHistory": false, + "documentsKeepHistoryContractDefault": false, + "documentsMutableContractDefault": true, + "documentsCanBeDeletedContractDefault": true, + "requiresIdentityEncryptionBoundedKey": null, + "requiresIdentityDecryptionBoundedKey": null, + "sizedIntegerTypes": true + }, + "version": 1, + "ownerId": "2b994p95akyNFKtkDnDvBRUotDbkH54MHwGbhQLr5gcU", + "schemaDefs": null, + "keywords": [], + "documentSchemas": { + "preorder": { + "type": "object", + "indices": [ + { + "name": "saltedHash", + "properties": [ + { + "saltedDomainHash": "asc" + } + ], + "unique": true + } + ], + "properties": { + "saltedDomainHash": { + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 0, + "description": "Double sha-256 of the concatenation of a 32 byte random salt and a normalized domain name" + } + }, + "required": [ + "saltedDomainHash" + ], + "additionalProperties": false, + "$comment": "Preorder documents are immutable: modification and deletion are restricted" + } + }, + "createdAt": null, + "updatedAt": null, + "createdAtBlockHeight": null, + "updatedAtBlockHeight": null, + "createdAtEpoch": null, + "updatedAtEpoch": null, + "groups": {}, + "tokens": { + "0": { + "$format_version": "0", + "conventions": { + "$format_version": "0", + "localizations": { + "en": { + "$format_version": "0", + "shouldCapitalize": false, + "singularForm": "paul2", + "pluralForm": "paul2s" + } + }, + "decimals": 8 + }, + "conventionsChangeRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "baseSupply": 100000, + "maxSupply": null, + "keepsHistory": { + "$format_version": "0", + "keepsTransferHistory": false, + "keepsFreezingHistory": false, + "keepsMintingHistory": false, + "keepsBurningHistory": false + }, + "startAsPaused": false, + "maxSupplyChangeRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "distributionRules": { + "$format_version": "0", + "perpetualDistribution": null, + "perpetualDistributionRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "preProgrammedDistribution": null, + "newTokensDestinationIdentity": null, + "newTokensDestinationIdentityRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "mintingAllowChoosingDestination": false, + "mintingAllowChoosingDestinationRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + } + }, + "manualMintingRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "manualBurningRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "freezeRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "unfreezeRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "destroyFrozenFundsRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "emergencyActionRules": { + "V0": { + "authorized_to_make_change": "NoOne", + "admin_action_takers": "NoOne", + "changing_authorized_action_takers_to_no_one_allowed": false, + "changing_admin_action_takers_to_no_one_allowed": false, + "self_changing_admin_action_takers_allowed": false + } + }, + "mainControlGroup": null, + "mainControlGroupCanBeModified": "NoOne" + } + } +} \ No newline at end of file From a20035c3501b490e443c11833ceaf26483026a19 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 22:06:18 +0700 Subject: [PATCH 11/46] more validation --- .../src/errors/consensus/basic/basic_error.rs | 11 +- .../invalid_keyword_encoding_error.rs | 44 +++++ .../invalid_keyword_length_error.rs | 44 +++++ .../consensus/basic/data_contract/mod.rs | 4 + packages/rs-dpp/src/errors/consensus/codes.rs | 2 + .../advanced_structure/v0/mod.rs | 42 ++++- .../data_contract_create/mod.rs | 1 + .../keyword_test/keyword_base_contract.json | 157 +----------------- .../src/errors/consensus/consensus_error.rs | 8 +- 9 files changed, 153 insertions(+), 160 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index 463a8a21e3e..737684a00c4 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -75,7 +75,10 @@ use crate::consensus::basic::{ }; use crate::consensus::ConsensusError; -use super::data_contract::{DuplicateKeywordsError, TooManyKeywordsError}; +use super::data_contract::{ + DuplicateKeywordsError, InvalidKeywordEncodingError, InvalidKeywordLengthError, + TooManyKeywordsError, +}; use crate::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use crate::consensus::basic::overflow_error::OverflowError; use crate::consensus::basic::token::{ @@ -212,6 +215,12 @@ pub enum BasicError { #[error(transparent)] DuplicateKeywordsError(DuplicateKeywordsError), + #[error(transparent)] + InvalidKeywordLengthError(InvalidKeywordLengthError), + + #[error(transparent)] + InvalidKeywordEncodingError(InvalidKeywordEncodingError), + // Document #[error(transparent)] DataContractNotPresentError(DataContractNotPresentError), diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs new file mode 100644 index 00000000000..57657d6c3d6 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs @@ -0,0 +1,44 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Data contract {contract_id} has invalid keyword '{keyword}'. Keywords must be ASCII.")] +#[platform_serialize(unversioned)] +pub struct InvalidKeywordEncodingError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + contract_id: String, + keyword: String, +} + +impl InvalidKeywordEncodingError { + pub fn new(contract_id: String, keyword: String) -> Self { + Self { + contract_id, + keyword, + } + } + + pub fn contract_id(&self) -> &str { + &self.contract_id + } + + pub fn keyword(&self) -> &str { + &self.keyword + } +} + +impl From for ConsensusError { + fn from(err: InvalidKeywordEncodingError) -> Self { + Self::BasicError(BasicError::InvalidKeywordEncodingError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs new file mode 100644 index 00000000000..9c9c8b8c52c --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs @@ -0,0 +1,44 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Data contract {contract_id} has keyword with invalid length: '{keyword}'. Valid length is between 3 and 50 characters.")] +#[platform_serialize(unversioned)] +pub struct InvalidKeywordLengthError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + contract_id: String, + keyword: String, +} + +impl InvalidKeywordLengthError { + pub fn new(contract_id: String, keyword: String) -> Self { + Self { + contract_id, + keyword, + } + } + + pub fn contract_id(&self) -> &str { + &self.contract_id + } + + pub fn keyword(&self) -> &str { + &self.keyword + } +} + +impl From for ConsensusError { + fn from(err: InvalidKeywordLengthError) -> Self { + Self::BasicError(BasicError::InvalidKeywordLengthError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs index c41777979f7..c0610a52f0d 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -27,6 +27,8 @@ mod invalid_document_type_required_security_level; mod invalid_index_property_type_error; mod invalid_indexed_property_constraint_error; mod invalid_json_schema_ref_error; +mod invalid_keyword_encoding_error; +mod invalid_keyword_length_error; mod invalid_token_base_supply_error; mod invalid_token_distribution_function_divide_by_zero_error; mod invalid_token_distribution_function_incoherence_error; @@ -80,6 +82,8 @@ pub use group_position_does_not_exist_error::*; pub use group_total_power_has_less_than_required_power_error::*; pub use incompatible_document_type_schema_error::*; pub use invalid_document_type_name_error::*; +pub use invalid_keyword_encoding_error::*; +pub use invalid_keyword_length_error::*; pub use invalid_token_base_supply_error::*; pub use invalid_token_distribution_function_divide_by_zero_error::*; pub use invalid_token_distribution_function_incoherence_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 9ebc2a7a691..aeef3882fcd 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -108,6 +108,8 @@ impl ErrorWithCode for BasicError { Self::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(_) => 10261, Self::TooManyKeywordsError(_) => 10262, Self::DuplicateKeywordsError(_) => 10263, + Self::InvalidKeywordLengthError(_) => 10264, + Self::InvalidKeywordEncodingError(_) => 10265, // Group Errors: 10350-10399 Self::GroupPositionDoesNotExistError(_) => 10350, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs index 78791ca5c29..665b162e751 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs @@ -5,12 +5,12 @@ use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; -use dpp::consensus::basic::data_contract::DuplicateKeywordsError; -use dpp::consensus::basic::data_contract::TooManyKeywordsError; +use dpp::consensus::basic::data_contract::{DuplicateKeywordsError, InvalidKeywordLengthError}; use dpp::consensus::basic::data_contract::{ InvalidDataContractIdError, InvalidDataContractVersionError, InvalidTokenBaseSupplyError, NonContiguousContractTokenPositionsError, }; +use dpp::consensus::basic::data_contract::{InvalidKeywordEncodingError, TooManyKeywordsError}; use dpp::consensus::basic::BasicError; use dpp::consensus::ConsensusError; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; @@ -170,9 +170,45 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 )], )); } - // Validate the keywords are all unique + + // Validate the keywords are all unique, between 3 and 50 characters, and all ASCII let mut seen_keywords = HashSet::new(); for keyword in self.data_contract().keywords() { + // First check keyword length + if keyword.len() < 3 || keyword.len() > 50 { + let bump_action = StateTransitionAction::BumpIdentityNonceAction( + BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), + ); + + return Ok(ConsensusValidationResult::new_with_data_and_errors( + bump_action, + vec![ConsensusError::BasicError( + BasicError::InvalidKeywordLengthError(InvalidKeywordLengthError::new( + self.data_contract().id().to_string(Encoding::Base58), + keyword.to_string(), + )), + )], + )); + } + + // Then check keyword is ASCII + if !keyword.is_ascii() { + let bump_action = StateTransitionAction::BumpIdentityNonceAction( + BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), + ); + + return Ok(ConsensusValidationResult::new_with_data_and_errors( + bump_action, + vec![ConsensusError::BasicError( + BasicError::InvalidKeywordEncodingError(InvalidKeywordEncodingError::new( + self.data_contract().id().to_string(Encoding::Base58), + keyword.to_string(), + )), + )], + )); + } + + // Then check uniqueness if !seen_keywords.insert(keyword) { let bump_action = StateTransitionAction::BumpIdentityNonceAction( BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index 2837afd2feb..7509db70dab 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2713,6 +2713,7 @@ mod tests { .expect("expected to commit transaction"); // Get the data contract ID from the transition + // Is there a simpler way to get the ID? let unique_identifiers = data_contract_create_transition.unique_identifiers(); let unique_identifier = unique_identifiers .first() diff --git a/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json b/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json index 323e27eff7d..11d440ef449 100644 --- a/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json +++ b/packages/rs-drive-abci/tests/supporting_files/contract/keyword_test/keyword_base_contract.json @@ -1,21 +1,8 @@ { "$format_version": "1", "id": "4Bqs6itzfoDXzmgQibYZQABbqYsXmawVf7SKe3mKDQVd", - "config": { - "$format_version": "1", - "canBeDeleted": false, - "readonly": false, - "keepsHistory": false, - "documentsKeepHistoryContractDefault": false, - "documentsMutableContractDefault": true, - "documentsCanBeDeletedContractDefault": true, - "requiresIdentityEncryptionBoundedKey": null, - "requiresIdentityDecryptionBoundedKey": null, - "sizedIntegerTypes": true - }, - "version": 1, "ownerId": "2b994p95akyNFKtkDnDvBRUotDbkH54MHwGbhQLr5gcU", - "schemaDefs": null, + "version": 1, "keywords": [], "documentSchemas": { "preorder": { @@ -48,146 +35,6 @@ "$comment": "Preorder documents are immutable: modification and deletion are restricted" } }, - "createdAt": null, - "updatedAt": null, - "createdAtBlockHeight": null, - "updatedAtBlockHeight": null, - "createdAtEpoch": null, - "updatedAtEpoch": null, "groups": {}, - "tokens": { - "0": { - "$format_version": "0", - "conventions": { - "$format_version": "0", - "localizations": { - "en": { - "$format_version": "0", - "shouldCapitalize": false, - "singularForm": "paul2", - "pluralForm": "paul2s" - } - }, - "decimals": 8 - }, - "conventionsChangeRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "baseSupply": 100000, - "maxSupply": null, - "keepsHistory": { - "$format_version": "0", - "keepsTransferHistory": false, - "keepsFreezingHistory": false, - "keepsMintingHistory": false, - "keepsBurningHistory": false - }, - "startAsPaused": false, - "maxSupplyChangeRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "distributionRules": { - "$format_version": "0", - "perpetualDistribution": null, - "perpetualDistributionRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "preProgrammedDistribution": null, - "newTokensDestinationIdentity": null, - "newTokensDestinationIdentityRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "mintingAllowChoosingDestination": false, - "mintingAllowChoosingDestinationRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - } - }, - "manualMintingRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "manualBurningRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "freezeRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "unfreezeRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "destroyFrozenFundsRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "emergencyActionRules": { - "V0": { - "authorized_to_make_change": "NoOne", - "admin_action_takers": "NoOne", - "changing_authorized_action_takers_to_no_one_allowed": false, - "changing_admin_action_takers_to_no_one_allowed": false, - "self_changing_admin_action_takers_allowed": false - } - }, - "mainControlGroup": null, - "mainControlGroupCanBeModified": "NoOne" - } - } + "tokens": {} } \ No newline at end of file diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index bd3619abd1e..9e84de3d9d1 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError, }; use wasm_bindgen::{JsError, JsValue}; -use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; +use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordEncodingError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; @@ -767,6 +767,12 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::DuplicateKeywordsError(e) => { generic_consensus_error!(DuplicateKeywordsError, e).into() } + BasicError::InvalidKeywordEncodingError(e) => { + generic_consensus_error!(InvalidKeywordEncodingError, e).into() + } + BasicError::InvalidKeywordLengthError(e) => { + generic_consensus_error!(InvalidKeywordLengthError, e).into() + } } } From e5804c1d25ee6b275810c9cd34222a938a20301a Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 22:17:20 +0700 Subject: [PATCH 12/46] more tests --- .../data_contract_create/mod.rs | 224 +++++++++++++++++- 1 file changed, 220 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index 7509db70dab..ead04e899c3 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2623,6 +2623,222 @@ mod tests { ); } + #[test] + fn test_data_contract_creation_fails_with_keyword_too_short() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + // Create identity + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // Load the base contract JSON and convert it to `DataContract` + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + // Convert to Value for mutation + let mut contract_value = data_contract + .to_value(PlatformVersion::latest()) + .expect("to_value failed"); + + // Insert a keyword with length < 3 + contract_value["keywords"] = Value::Array(vec![Value::Text("hi".to_string())]); + + // Build a new DataContract + let data_contract_invalid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract"); + + // Create DataContractCreateTransition + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract_invalid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create transition"); + + // Process + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected to serialize"); + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + // Assert that we get the correct error + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::InvalidKeywordLengthError(_)), + _ + )] + ); + } + + #[test] + fn test_data_contract_creation_fails_with_keyword_too_long() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + let mut contract_value = data_contract + .to_value(platform_version) + .expect("to_value failed"); + + // Create a 51-char keyword + let too_long_keyword = "x".repeat(51); + contract_value["keywords"] = Value::Array(vec![Value::Text(too_long_keyword)]); + + let data_contract_invalid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract"); + + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract_invalid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected to serialize"); + + let transaction = platform.drive.grove.start_transaction(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::InvalidKeywordLengthError(_)), + _ + )] + ); + } + + #[test] + fn test_data_contract_creation_fails_with_non_ascii_keyword() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + let mut contract_value = data_contract + .to_value(platform_version) + .expect("to_value failed"); + + // Insert a keyword with a non-ASCII char, e.g. ü + contract_value["keywords"] = Value::Array(vec![Value::Text("kü".to_string())]); + + let data_contract_invalid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract"); + + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract_invalid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected to serialize"); + + let transaction = platform.drive.grove.start_transaction(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::InvalidKeywordEncodingError(_)), + _ + )] + ); + } + #[test] fn test_data_contract_creation_succeeds_with_valid_keywords() { let platform_version = PlatformVersion::latest(); @@ -2651,7 +2867,7 @@ mod tests { .expect("to_value failed"); // Insert a valid set of keywords: all distinct, fewer than 20 - let valid_keywords = vec!["k1", "k2", "k3"]; + let valid_keywords = vec!["key1", "key2", "key3"]; contract_value["keywords"] = Value::Array( valid_keywords .into_iter() @@ -2737,9 +2953,9 @@ mod tests { // Check the keywords in the contract let keywords = contract.contract.keywords(); assert_eq!(keywords.len(), 3); - assert_eq!(keywords[0], "k1"); - assert_eq!(keywords[1], "k2"); - assert_eq!(keywords[2], "k3"); + assert_eq!(keywords[0], "key1"); + assert_eq!(keywords[1], "key2"); + assert_eq!(keywords[2], "key3"); } } } From 5778b4f9142961ddc7cdf58e71fd99a7374dd08f Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 3 Apr 2025 22:43:41 +0700 Subject: [PATCH 13/46] fix tests for extra storage cost for empty keywords --- packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index 496136cd309..c5466ff6e23 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -630,7 +630,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2488410); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2488810); let check_result = platform .check_tx( @@ -1141,7 +1141,7 @@ mod tests { // The processing fees should be twice as much as a fee multiplier of 0, // since a fee multiplier of 100 means 100% more of 1 (gives 2) - assert_eq!(processing_result.aggregated_fees().processing_fee, 4976820); + assert_eq!(processing_result.aggregated_fees().processing_fee, 4977620); let check_result = platform .check_tx( @@ -1613,7 +1613,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2488410); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2488810); platform .drive @@ -2069,7 +2069,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2488410); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2488810); platform .drive From 7f47870d56e7466ff60588597a6dfbce4298e761 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 4 Apr 2025 10:00:19 +0700 Subject: [PATCH 14/46] fix error enum ordering --- .../src/errors/consensus/basic/basic_error.rs | 24 +++++++++---------- .../data_contract_create/mod.rs | 2 +- .../src/errors/consensus/consensus_error.rs | 6 ++--- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index 737684a00c4..d727e14f865 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -209,18 +209,6 @@ pub enum BasicError { #[error(transparent)] DataContractHaveNewUniqueIndexError(DataContractHaveNewUniqueIndexError), - #[error(transparent)] - TooManyKeywordsError(TooManyKeywordsError), - - #[error(transparent)] - DuplicateKeywordsError(DuplicateKeywordsError), - - #[error(transparent)] - InvalidKeywordLengthError(InvalidKeywordLengthError), - - #[error(transparent)] - InvalidKeywordEncodingError(InvalidKeywordEncodingError), - // Document #[error(transparent)] DataContractNotPresentError(DataContractNotPresentError), @@ -531,6 +519,18 @@ pub enum BasicError { TokenPaymentByBurningOnlyAllowedOnInternalTokenError( TokenPaymentByBurningOnlyAllowedOnInternalTokenError, ), + + #[error(transparent)] + TooManyKeywordsError(TooManyKeywordsError), + + #[error(transparent)] + DuplicateKeywordsError(DuplicateKeywordsError), + + #[error(transparent)] + InvalidKeywordLengthError(InvalidKeywordLengthError), + + #[error(transparent)] + InvalidKeywordEncodingError(InvalidKeywordEncodingError), } impl From for ConsensusError { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index ead04e899c3..9aa0193e912 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2794,7 +2794,7 @@ mod tests { .expect("to_value failed"); // Insert a keyword with a non-ASCII char, e.g. ü - contract_value["keywords"] = Value::Array(vec![Value::Text("kü".to_string())]); + contract_value["keywords"] = Value::Array(vec![Value::Text("keü".to_string())]); let data_contract_invalid = DataContract::from_value(contract_value, true, platform_version) diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 9e84de3d9d1..244b233fc66 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -767,12 +767,12 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::DuplicateKeywordsError(e) => { generic_consensus_error!(DuplicateKeywordsError, e).into() } - BasicError::InvalidKeywordEncodingError(e) => { - generic_consensus_error!(InvalidKeywordEncodingError, e).into() - } BasicError::InvalidKeywordLengthError(e) => { generic_consensus_error!(InvalidKeywordLengthError, e).into() } + BasicError::InvalidKeywordEncodingError(e) => { + generic_consensus_error!(InvalidKeywordEncodingError, e).into() + } } } From a9f91351d0cd1fbaa3ee54c208089510892431e5 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 4 Apr 2025 10:32:47 +0700 Subject: [PATCH 15/46] add test for search contract creation restriction --- .../batch/tests/document/creation.rs | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 5b413b56e07..422bd9c960b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -7,6 +7,8 @@ mod creation_tests { use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{get_contested_resource_vote_state_response_v0, GetContestedResourceVoteStateResponseV0}; use assert_matches::assert_matches; + use dpp::platform_value::string_encoding::Encoding; + use dpp::prelude::Identifier; use rand::distributions::Standard; use dpp::consensus::basic::document::DocumentFieldMaxSizeExceededError; use dpp::consensus::ConsensusError; @@ -2468,6 +2470,141 @@ mod creation_tests { assert_eq!(consensus_error.to_string(), "Document Creation on 86LHvdC1Tqx5P97LQUSibGFqf2vnKFpB6VkqQ7oso86e:card is not allowed because of the document type's creation restriction mode Owner Only"); } + #[test] + fn test_document_creation_on_search_system_contract_fails_due_to_restriction() { + // Build test platform + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_initial_state_structure(); + + // Create an identity that will attempt to create the document + let (identity, signer, key) = setup_identity(&mut platform, 999, dash_to_credits!(0.1)); + + // Obtain the current platform state and version + let platform_state = platform.state.load(); + let platform_version = platform_state + .current_platform_version() + .expect("expected to get current platform version"); + + // Load the system Search contract + let search_contract = platform.drive.cache.system_data_contracts.load_search(); + + platform + .drive + .apply_contract( + &search_contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("expected to apply contract successfully"); + + // Get the document type from the search contract. + let doc_type = search_contract + .document_type_for_name("contract") + .expect("expected to find 'contract' in Search contract"); + + // Verify that the document type has the restrictive creation mode + assert_eq!( + doc_type.creation_restriction_mode(), + CreationRestrictionMode::NoCreationAllowed, + "Expected creation restriction mode to be NoCreationAllowed (2)." + ); + + // Create a random document + let mut rng = StdRng::seed_from_u64(123456); + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = doc_type + .random_document_with_identifier_and_entropy( + &mut rng, + identity.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected to create a random document"); + + // Set fields in the document + document.set("keyword", "meme".into()); + document.set("contractId", Identifier::random().into()); + + // Create the transition + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + doc_type, + entropy.0, + &key, + 1, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + // Start transaction and submit the transition + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + println!("Processing result: {:?}", processing_result); + + // Since the creationRestrictionMode is 2 (NoCreationAllowed), this should fail + assert_eq!( + processing_result.invalid_paid_count(), + 1, + "Expected exactly 1 invalid paid transition" + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Check the returned consensus error + let result = processing_result.into_execution_results().remove(0); + let PaidConsensusError(consensus_error, _) = result else { + panic!("expected a paid consensus error"); + }; + + // Compare message to whatever your code sets for this error + assert_eq!( + consensus_error.to_string(), + format!( + "Document Creation on {}:{} is not allowed because of the document type's creation restriction mode No Creation Allowed", + search_contract.id().to_string(Encoding::Base58), + "contract" + ), + "Mismatch in error message" + ); + } + #[test] fn test_document_creation_paid_with_a_token_burn() { let platform_version = PlatformVersion::latest(); From c9e91120e1233429f61f1aa89ea043a9aae2e299 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 4 Apr 2025 12:16:15 +0700 Subject: [PATCH 16/46] fix tests --- .../src/execution/check_tx/v0/mod.rs | 2 +- .../contract/insert/add_new_keywords/mod.rs | 2 +- .../insert/add_new_keywords/v0/mod.rs | 2 +- .../rs-drive/src/drive/contract/insert/mod.rs | 1 + .../rs-drive/tests/deterministic_root_hash.rs | 4 +- packages/rs-drive/tests/query_tests.rs | 60 +++++++++---------- 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index c5466ff6e23..d84943877b5 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -1699,7 +1699,7 @@ mod tests { assert_eq!( update_processing_result.aggregated_fees().processing_fee, - 2503110 + 2503570 ); let check_result = platform diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index 2b3f19cb329..b889c109546 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -97,7 +97,7 @@ impl Drive { &self, contract_id: Identifier, owner_id: Identifier, - keywords: &Vec, + keywords: &[String], block_info: &BlockInfo, estimated_costs_only_with_layer_info: &mut Option< HashMap, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 4eee6da28d3..2393ecc6a5d 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -89,7 +89,7 @@ impl Drive { &self, contract_id: Identifier, owner_id: Identifier, - keywords: &Vec, + keywords: &[String], block_info: &BlockInfo, estimated_costs_only_with_layer_info: &mut Option< HashMap, diff --git a/packages/rs-drive/src/drive/contract/insert/mod.rs b/packages/rs-drive/src/drive/contract/insert/mod.rs index 69d22d495fb..ea57897be76 100644 --- a/packages/rs-drive/src/drive/contract/insert/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/mod.rs @@ -1,3 +1,4 @@ mod add_contract_to_storage; +#[allow(clippy::too_many_arguments)] mod add_new_keywords; mod insert_contract; diff --git a/packages/rs-drive/tests/deterministic_root_hash.rs b/packages/rs-drive/tests/deterministic_root_hash.rs index 08d4f5d605c..ef4654ac3ae 100644 --- a/packages/rs-drive/tests/deterministic_root_hash.rs +++ b/packages/rs-drive/tests/deterministic_root_hash.rs @@ -282,6 +282,8 @@ mod tests { load_system_data_contract(SystemDataContract::Dashpay, platform_version) .expect("should load dpns contract"); + println!("Dashpay contract: {:?}", dashpay_contract); + drive .apply_contract( &dashpay_contract, @@ -302,7 +304,7 @@ mod tests { // We expect a different app hash because data contract is not serialized the same way let expected_app_hash = match platform_version.protocol_version { 0..=8 => "1b80f4a9f00597b3f1ddca904b3cee67576868adcdd802c0a3f91e14209bb402", - _ => "107bcfc100e64a51e60b3e7ca7e7823b11968c2db599c212a8d09869e3ce1dd0", + _ => "aa29a0d3dcdcb1dc1b446830931762e0b9c2e2d97d6f426f8dbe4e0eda8e6130", }; assert_eq!( diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index bb18047a5e6..8353aeecb0b 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -2509,8 +2509,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 59, 253, 119, 177, 148, 100, 153, 121, 228, 238, 250, 185, 103, 53, 113, 8, 30, 192, - 75, 150, 153, 2, 24, 109, 93, 91, 97, 75, 106, 35, 29, 252, + 163, 83, 211, 88, 187, 57, 197, 189, 189, 39, 40, 150, 102, 186, 188, 111, 200, 230, + 134, 21, 72, 136, 135, 92, 102, 206, 72, 43, 127, 87, 26, 82, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -3823,8 +3823,8 @@ mod tests { assert_eq!( root_hash.as_slice(), vec![ - 5, 92, 86, 251, 178, 238, 8, 246, 80, 139, 148, 81, 135, 108, 57, 197, 114, 102, - 219, 71, 50, 0, 47, 252, 106, 157, 118, 30, 128, 199, 55, 126, + 243, 205, 195, 230, 73, 41, 217, 87, 42, 205, 142, 71, 144, 29, 239, 97, 174, 131, + 226, 122, 190, 78, 58, 99, 94, 106, 233, 185, 194, 198, 246, 205 ], ); } @@ -3974,8 +3974,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 59, 253, 119, 177, 148, 100, 153, 121, 228, 238, 250, 185, 103, 53, 113, 8, 30, 192, - 75, 150, 153, 2, 24, 109, 93, 91, 97, 75, 106, 35, 29, 252, + 163, 83, 211, 88, 187, 57, 197, 189, 189, 39, 40, 150, 102, 186, 188, 111, 200, 230, + 134, 21, 72, 136, 135, 92, 102, 206, 72, 43, 127, 87, 26, 82, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -4426,8 +4426,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 40, 208, 218, 141, 51, 7, 57, 5, 17, 42, 78, 70, 239, 65, 98, 146, 20, 42, 68, 135, - 241, 126, 28, 204, 213, 7, 128, 14, 31, 163, 15, 2, + 138, 110, 99, 80, 216, 232, 45, 246, 159, 207, 139, 253, 210, 64, 32, 114, 102, 107, + 21, 120, 163, 19, 189, 99, 109, 95, 56, 217, 134, 206, 160, 215, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -4549,8 +4549,8 @@ mod tests { // Make sure the state is deterministic let expected_app_hash = vec![ - 59, 253, 119, 177, 148, 100, 153, 121, 228, 238, 250, 185, 103, 53, 113, 8, 30, 192, - 75, 150, 153, 2, 24, 109, 93, 91, 97, 75, 106, 35, 29, 252, + 163, 83, 211, 88, 187, 57, 197, 189, 189, 39, 40, 150, 102, 186, 188, 111, 200, 230, + 134, 21, 72, 136, 135, 92, 102, 206, 72, 43, 127, 87, 26, 82, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5347,8 +5347,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 134, 179, 83, 10, 119, 219, 251, 215, 151, 38, 111, 63, 245, 250, 229, 201, 136, - 190, 129, 75, 226, 88, 216, 93, 69, 152, 224, 156, 93, 170, 125, + 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, + 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, ]; assert_eq!(root_hash.as_slice(), expected_app_hash,); @@ -5443,8 +5443,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 134, 179, 83, 10, 119, 219, 251, 215, 151, 38, 111, 63, 245, 250, 229, 201, 136, - 190, 129, 75, 226, 88, 216, 93, 69, 152, 224, 156, 93, 170, 125, + 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, + 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5539,8 +5539,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 134, 179, 83, 10, 119, 219, 251, 215, 151, 38, 111, 63, 245, 250, 229, 201, 136, - 190, 129, 75, 226, 88, 216, 93, 69, 152, 224, 156, 93, 170, 125, + 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, + 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5635,8 +5635,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 134, 179, 83, 10, 119, 219, 251, 215, 151, 38, 111, 63, 245, 250, 229, 201, 136, - 190, 129, 75, 226, 88, 216, 93, 69, 152, 224, 156, 93, 170, 125, + 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, + 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5831,8 +5831,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 236, 213, 202, 143, 111, 54, 250, 174, 57, 239, 156, 18, 122, 223, 88, 20, 13, 180, 89, - 144, 31, 20, 138, 189, 2, 148, 160, 95, 231, 108, 216, 163, + 89, 74, 31, 85, 116, 81, 139, 178, 90, 11, 123, 172, 93, 187, 25, 125, 35, 201, 210, + 64, 40, 43, 40, 68, 230, 228, 168, 46, 63, 219, 98, 240, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6038,8 +6038,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 236, 213, 202, 143, 111, 54, 250, 174, 57, 239, 156, 18, 122, 223, 88, 20, 13, 180, 89, - 144, 31, 20, 138, 189, 2, 148, 160, 95, 231, 108, 216, 163, + 89, 74, 31, 85, 116, 81, 139, 178, 90, 11, 123, 172, 93, 187, 25, 125, 35, 201, 210, + 64, 40, 43, 40, 68, 230, 228, 168, 46, 63, 219, 98, 240, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6248,8 +6248,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 236, 213, 202, 143, 111, 54, 250, 174, 57, 239, 156, 18, 122, 223, 88, 20, 13, 180, 89, - 144, 31, 20, 138, 189, 2, 148, 160, 95, 231, 108, 216, 163, + 89, 74, 31, 85, 116, 81, 139, 178, 90, 11, 123, 172, 93, 187, 25, 125, 35, 201, 210, + 64, 40, 43, 40, 68, 230, 228, 168, 46, 63, 219, 98, 240, ]; assert_eq!(root_hash.as_slice(), expected_app_hash,); @@ -6462,8 +6462,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 174, 178, 50, 69, 201, 231, 248, 75, 88, 168, 83, 29, 141, 40, 117, 63, 157, 205, 24, - 56, 113, 108, 224, 27, 225, 24, 134, 153, 157, 130, 80, 200, + 244, 130, 169, 10, 90, 218, 48, 147, 73, 95, 89, 174, 234, 151, 228, 21, 155, 188, 165, + 185, 121, 77, 221, 236, 82, 228, 82, 133, 102, 214, 251, 40, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6542,8 +6542,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 174, 178, 50, 69, 201, 231, 248, 75, 88, 168, 83, 29, 141, 40, 117, 63, 157, 205, 24, - 56, 113, 108, 224, 27, 225, 24, 134, 153, 157, 130, 80, 200, + 244, 130, 169, 10, 90, 218, 48, 147, 73, 95, 89, 174, 234, 151, 228, 21, 155, 188, 165, + 185, 121, 77, 221, 236, 82, 228, 82, 133, 102, 214, 251, 40, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6643,8 +6643,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 174, 178, 50, 69, 201, 231, 248, 75, 88, 168, 83, 29, 141, 40, 117, 63, 157, 205, 24, - 56, 113, 108, 224, 27, 225, 24, 134, 153, 157, 130, 80, 200, + 244, 130, 169, 10, 90, 218, 48, 147, 73, 95, 89, 174, 234, 151, 228, 21, 155, 188, 165, + 185, 121, 77, 221, 236, 82, 228, 82, 133, 102, 214, 251, 40, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); From cf84d785ac1d53f684d207ac3d39377ae47fe54c Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 4 Apr 2025 12:29:25 +0700 Subject: [PATCH 17/46] fix tests --- .../src/drive/contract/insert/add_new_keywords/mod.rs | 4 ++-- .../src/drive/contract/insert/add_new_keywords/v0/mod.rs | 4 ++-- packages/rs-drive/tests/query_tests_history.rs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index b889c109546..d8a71befb74 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -19,7 +19,7 @@ impl Drive { &self, contract_id: Identifier, owner_id: Identifier, - keywords: &Vec, + keywords: &[String], block_info: &BlockInfo, apply: bool, transaction: TransactionArg, @@ -57,7 +57,7 @@ impl Drive { &self, contract_id: Identifier, owner_id: Identifier, - keywords: &Vec, + keywords: &[String], block_info: &BlockInfo, apply: bool, transaction: TransactionArg, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 2393ecc6a5d..57c16d09351 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -19,7 +19,7 @@ impl Drive { &self, contract_id: Identifier, owner_id: Identifier, - keywords: &Vec, + keywords: &[String], block_info: &BlockInfo, apply: bool, transaction: TransactionArg, @@ -52,7 +52,7 @@ impl Drive { &self, contract_id: Identifier, owner_id: Identifier, - keywords: &Vec, + keywords: &[String], block_info: &BlockInfo, apply: bool, transaction: TransactionArg, diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index 2ffe58ce495..cb72796f888 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -1666,8 +1666,8 @@ fn test_query_historical_latest_platform_version() { assert_eq!( root_hash.as_slice(), vec![ - 133, 44, 161, 89, 108, 253, 236, 16, 93, 4, 122, 187, 249, 226, 208, 148, 47, 201, 46, - 129, 167, 114, 63, 221, 133, 12, 1, 136, 135, 208, 226, 213 + 198, 240, 42, 199, 134, 177, 186, 144, 191, 122, 14, 217, 209, 140, 131, 144, 63, 232, + 141, 193, 177, 136, 200, 150, 42, 110, 151, 216, 85, 161, 78, 44 ] ); @@ -3032,8 +3032,8 @@ fn test_query_historical_latest_platform_version() { assert_eq!( root_hash.as_slice(), vec![ - 124, 248, 167, 74, 81, 40, 160, 183, 10, 34, 119, 221, 225, 7, 207, 42, 42, 205, 8, - 149, 201, 22, 165, 217, 125, 191, 152, 223, 66, 102, 9, 180 + 244, 221, 68, 246, 214, 152, 18, 222, 186, 119, 187, 173, 119, 184, 146, 5, 27, 145, + 125, 63, 233, 17, 138, 99, 99, 177, 83, 145, 4, 8, 124, 155 ] ); } From ec80ce153ebd8dcc2f3be90eb3d159f81add673d Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 4 Apr 2025 12:50:18 +0700 Subject: [PATCH 18/46] fix --- .../src/drive/contract/insert/add_new_keywords/mod.rs | 6 +++--- packages/rs-drive/tests/deterministic_root_hash.rs | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index d8a71befb74..1e0aad9be1c 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -46,7 +46,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_keywords".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } @@ -86,7 +86,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_keywords_add_to_operations".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } @@ -126,7 +126,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_keywords_operations".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive/tests/deterministic_root_hash.rs b/packages/rs-drive/tests/deterministic_root_hash.rs index ef4654ac3ae..35b3d7e7b57 100644 --- a/packages/rs-drive/tests/deterministic_root_hash.rs +++ b/packages/rs-drive/tests/deterministic_root_hash.rs @@ -282,8 +282,6 @@ mod tests { load_system_data_contract(SystemDataContract::Dashpay, platform_version) .expect("should load dpns contract"); - println!("Dashpay contract: {:?}", dashpay_contract); - drive .apply_contract( &dashpay_contract, From 935f32b9ee329763ef638393dcf55027501ea747 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 4 Apr 2025 14:27:10 +0700 Subject: [PATCH 19/46] generate test vectors and fix sdk test data yarn start --- .../create_genesis_state/test/tokens.rs | 4 ++++ ...a9664c6f3704dadf217d5b236f608cb4dc8a1.json | Bin 0 -> 60322 bytes ...0e0999c3aba33924223d8fdbfbf7d7678f3e1.json | Bin 60305 -> 0 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218912 -> 218933 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...914b55a2eeea35e7831ef86e2708b558f915f.json | Bin 60305 -> 0 bytes ...4eacbb5ffa75f6cb27d3ee8a17b185852f102.json | Bin 0 -> 60358 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218912 -> 218969 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...a9664c6f3704dadf217d5b236f608cb4dc8a1.json | Bin 0 -> 60316 bytes ...337e03233ad6fd5c394dd4e6033f39e9447e8.json | Bin 0 -> 60442 bytes ...9bb958387b94269284a209a3e5d1636812919.json | Bin 60431 -> 0 bytes ...0e0999c3aba33924223d8fdbfbf7d7678f3e1.json | Bin 60305 -> 0 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218912 -> 218927 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...501c1ba166a2dd8f6efb31b0289dc011da983.json | Bin 27353 -> 29015 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...cc2a50d7b433b50a88dc35fb34a80ecf9019f.json | Bin 55055 -> 0 bytes ...086bcaf743e2fa8f6b8b143deb29b5265e971.json | Bin 0 -> 55048 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218912 -> 218927 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218912 -> 218957 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...48c03122daf7ab2e77108f4bf44af1ad15eae.json | Bin 27353 -> 29045 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + ...067bd9ccc29eca3092a5664a5a9ba3bb7e967.json | Bin 223617 -> 225261 bytes ...99a143d6ae990bb9bc89cb34f7c5db8b1b705.json | 1 - ...a891ce226199229e3031f71994d14dd32f088.json | 1 + 35 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_9064a0dc37a9f6f767159a4325ba9664c6f3704dadf217d5b236f608cb4dc8a1.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_dc96f69a023cba74603789911c80e0999c3aba33924223d8fdbfbf7d7678f3e1.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_89578d545ba2f6d4859c6ba9135914b55a2eeea35e7831ef86e2708b558f915f.json create mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_c4bb9b2e03829c0926d347692bc4eacbb5ffa75f6cb27d3ee8a17b185852f102.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9064a0dc37a9f6f767159a4325ba9664c6f3704dadf217d5b236f608cb4dc8a1.json create mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9267cfc8e7a6f302a2a7d179bc9337e03233ad6fd5c394dd4e6033f39e9447e8.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_acef348f0a2248716aa25e8ebcd9bb958387b94269284a209a3e5d1636812919.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_dc96f69a023cba74603789911c80e0999c3aba33924223d8fdbfbf7d7678f3e1.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_614b964c1234c9998fb8e27da8dcc2a50d7b433b50a88dc35fb34a80ecf9019f.json create mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_96c4914304501c97094650f1da1086bcaf743e2fa8f6b8b143deb29b5265e971.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json create mode 100644 packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs index 28147c64bea..6eef53767ff 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs @@ -248,6 +248,7 @@ impl Platform { updated_at_epoch: None, groups, tokens, + keywords: vec!["key1".into(), "key2".into()], }); self.drive.apply_contract( @@ -275,6 +276,7 @@ impl Platform { IDENTITY_ID_1.to_buffer(), mint_amount, false, + false, block_info, true, transaction, @@ -288,6 +290,7 @@ impl Platform { IDENTITY_ID_2.to_buffer(), mint_amount, false, + false, block_info, true, transaction, @@ -302,6 +305,7 @@ impl Platform { IDENTITY_ID_3.to_buffer(), mint_amount, false, + false, block_info, true, transaction, diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_9064a0dc37a9f6f767159a4325ba9664c6f3704dadf217d5b236f608cb4dc8a1.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_9064a0dc37a9f6f767159a4325ba9664c6f3704dadf217d5b236f608cb4dc8a1.json new file mode 100644 index 0000000000000000000000000000000000000000..d8f00611846ffdd3e971212f0473be1ebfba84dd GIT binary patch literal 60322 zcmeI4ZF3t}a)tBRzhVldDkZfbL-0isollZw$BM08ujOn~krdSs7?QAn85l2;Xh;8j z&$)L1%m5%c&&Wz`HgrK2h`BG_eNLb5dqMlRFOsA)NayLBev!|oX@B1NGWks(>f?Lo z#dMs`-@MDFvtg0zL8sU0#%IHUfBe_~`0>T#zkKuj=l}fh=-bJkze)f2Z_j^u@|TCt zpIkiu?)Yqa^6y{2m_0duan$>|znrOk&W9JPU2fh-Py1>9Bzu~TvU%n`&(qN?i$>_- zG)o6XKDyd^@HWdPvu}s9c`@C7I4JsyahA_#-)U4i=®r`dVB7&!{{omO+6FXrjl zDBB)CpDxyht%iS9G5?l1)9jbUaGK4Y4P@JJe)V2W^zK0V7um8HVS$+Vbc)A?{~ML%5!!9V$*PVS@}8NwgJ+D}8kyo1e6XZ=paD$ghp z_1pN*jf+MbuUVyl!Wa4}V$Mh0D$m6{=Ca z&R}g9X4&O+Kz7A9t{|bf$Ugj#&ga=Q2-$zXO!t0$y!T%Ry}j4J9d&!BAMb6(O_8hl znGBP6)kz}3}emI;ZqF44I z(VI~=o9Ux8PYw@~{$*-$mJ%obn2ttCI+|Q+?mUqj-9(ObwY`X)r1>D(`zP;{CuuTH z74&H?dMEFSd6twoB=hubHcKX>w4WvOBDom8%aUR-kLH<5HP5SYsIjRI<%;yfQotk@ z^^kO|0WY$2DtBTkZsc(w3(bgW)-R@m+5U1{hk92Y)O>nf`DyK61>sK3jH;)dfSPux zekio(rDV+J(_wzG>H1^``Swma#rtg9PiI-8Mk(=|y?f}}#j8$Ne+^%CLbkr@jP!1rg=`!o?}zhCJv~@G?dhF%8*9~z zR5^TEjEjqDI=M{5sI>of3DViY+5Jtv-0K%(cREgq=Zo1qIm;4t8R^I?T8p9p4fC}# z*IGC(=ig}Q4J?VJuvV^GC(ynBSqbcLVsQR!wjpH+H|UBL{C-yF~|^TX@eJv$`92e*@kPK3Z+gqrlx~IXtL5#ZH3U|R@=?$w9agC7Bl+Cg*yJ< zmqR)!6z^XwH`rc0gm>Ato)yI?OY;T@{N!^=5so#u2BFLw#=fl7%(V%jMC66?x|r-$MRc}n zy9&Su71VBLPG#bQD#Y6d!4)LQ)SyS>SMu+BmcZc{+j5M1%(Y7!hIekF-i9sZHIpxL zUT*l;*(6Nu`R*fAu6ailsl(3!&8A>_xI28 zBvfCkpRPO9Q%E7xC9AHAMUrQ=1W8vlZa?{{TJbb<;+*pMI70@%b1OSebDeSaR3G=o z!@*#r&Lo^cX8V;}jqk&y#vhXV`}dPSR6ei9KMALaya*?fQIYE^(h9D-j+3Ks+2Q*S zA9Ry+R%*;3IlD@J{N}5qcW`vFpTvX2syZu)rdcu^kK^_1m&v#o4A0A26V6!!-y!P= z76$6#MyGULs0^0XVa4MWIyEg`-C53BUqb#qH;OYgD%s#$mCj8Ks9ji8`DW?b(L=x<)CjH~)`DUXl zd0H%Vqm|4q)4ju!2k|y9+_$OQ$@0+g_`_8Ft9Y!IURTnp`-%My^h_(6vP{}=i@YLt=N{>!_H$>5o#KO5$XvUMFb$o3pF!C!?Y6h_p*!YG*drt#awf z7aza)hcABX{ON7y%a^@FU3VXJb&T@sxZCSJ($78p?e`~ouRlHitU<@!lSdv`pH!WC ztmik4T8%w8Ew_2lJ$vd$N&9#{acEx5tSR3KB4!b8O{^ZzWm#)SY zs{cOjp311;Yh3j7Bz&SJgNY7=%=AWzk;ZxWfsOb6<&#^?IX<;Hijv;kYEHyK;a=`_ zy!NZnd<7x~CI&m0ZWlu|B9sn`Y&r>1>V-E);gh5A$;0l+LH9(T_ZkJT*R!>Tz>LxE zrRDxnL9+o(_;vE|_TYrzZzE%LDomAoD{lFbe>`1M&GD_n8E_7EI=+F+I~mhEJh|RN zyYGD*0y}Jmm@pMq?n|-+9 z-DZO$|8FIKb$vQGAlKZalLy_CTeYEXkH#x4ns4C@Q$9UlQ#=dq5?R~aFlRR0!m%QV z3;23L+lg1F^NskN6bGE5j#h5yL!%jCX8db~siN_{ItA%0RLs#ui!S)VM)T zD?rCCrG?iHEaAEBAtaB$p)EW`f5`s%PNx7VrmyiU>#M#jY@Wl zeos~*MrpjTqlimJ=wVjAlPRiYxST1rh$k&TSN5STU|x7}vc6MEfg(Jly!CiQ+Q2|8 zQ<{b7A(u&@oD^apghM7#5_%U>F%>8TUnwJ`3K&7{LZ+BkEt*5K&uNtC4NS}?5~wyZ)q=DTZl^|gvD2jvyyU1=?m`n#*+FrXULm%~ z3q(knL>zYlsytDXNWxm#2oIgGunn^p@FvHIw}=%ayd|2zVJ|47WD=6-7H0vGmb9#f zgD}eDwFUITJRvtW#)4WENWyj@a8nnWTSC*p5J(5005-SB>q`WXl*Ql^l&K4)>=VeG z2(W>)@8TXj0(cifSF0J>A|is4PE)Aw<{=@K#}lvZ1*~88LbHg>nkR%LF;I-{^g9um zBr2lph~sGv#*G>)ZJ8jHiVzMX2%8FnNUNBrMW)0p5Vh<`i#8IrE;bCMA*}e85y-3P zc=HOvfM@}nLQ0i~ikqTJ@Rn~EysUJEr77Q~AZZc_ND&cwh{-`#|edQl<>BW&9!)yWnnAv{jyIoTdmz<~IN`0gkc1+{C831s zw03Ab^@0S-eHvPywg>Pa<3dKcA(O}y6U%Uuv6F_nm6B`8QdX?=v*U4o8y8y%{ROwslO+T(16A!7C`yGaSt;%t3Epb!xkyamZ?Lk77g0YqNJEm)vv z2O^V*G_m4KR;D`KJRhB3jjycPU|KgrrXynzhfSEke6$5^L0KKA%A*`4ctw9{jvyL4 zsyatQGFwlO{zS8#PZo zd))$V;)v@w;jLXjKp^{N3FV&XO4R__AGt@oaEMei(Jm^=kV}}Zq?=+Py*p8&=Hc!{ z+4%o0;NnHv16PXhYOb+S&`|c#uD;xY$g&fVD51S3f%5v2DWW+(E+I{W_P7$k5Hb7j zPLx~!>3#XX395Wa)!c3@$W9zsd_6@a58YKNaTHkMbsUc! z4|xsTr>#59P&rO?tn``$%B?%W!t~IKSY^cZg1h*DK=Q)AYYN>(X9NO@9Pvg($vqzC zxFf7r<23XZ@`6mU3$#5Tys|MO3FQeqsM>KJTk8)3o#o-A~<9}B2~yHG$ne?QbU1Kn+;2beJAp61Yx}{r_fzOW+AP%`-Cb^LmDpmPT4D~ z=oIBUA*6GVSCEJcjWEi0(-_G+5ff?&@>KCemNVkfm13p=ppj|E3SNJWGLf$q?Txn}1tqeGa?hYp#6>5?8Ri`$p&Un~ zZIP#~K*x@^A}~r54aPi)X#x@a-yr;FR!+B1B&S-YEm4M;wv1OaHAqxxh-A6DWpcCU zDFOmU$vh{Hl)E6fp%~JWg-xR8VjW&c!|yG4Yu!#mm`uqF!dp4w3P^l+Eo*U8p>UyH z#6!wWl_d-LB3?l(+K@zE5bbri__5JxON7xlQiX>(RU*PW z4ID1{PIjSsWx`V-Z6R5@Ri<@HUUO>UT_o=)yg^Hie&aKa!>e5gfelKF8mfMS1esPt z)|JWY7S&c*(AdHRact>jQFE;6%3?Snxq}m5jZN}+i6J6+i%Sn}K`UA?ta%<8I8`*w zYV5nmHy(^uW~dQ}seq%DM?TsTq$e6Ij0g>^jmlrLi?@LMRK6qmbq7cwvq{K`-&=rm(wKD)WMPEg*~qaXiw) z6C1-(8b%p{Vyjd_<5iVlpo};T6wOvt!r<}89ShNcHvYC~gB79{B&Uv0tl@#zNzsBH z5`-3pA(AL5WE%-rnc(m)#j}vOQ8kdB^XzM`Q7xjx7MJlZurk>Vb4MB?zdv!liOq-vn-ZXs)$LV>o1+||m;|HN$je`^*$u|7wMZhoP9 zS1X(U-x{Hy-POwLh+6&pu2%YB3#mmV)T&EsA07X>Yb7dtcY`bS0@d`p!Bus-i^g3v zsu8HZ|NG|#s!Bw1(dqs(#u+&nuQJd*124Ni?6l|y_|1>+MbWhk!IwdHheG4?8Vf9f z><)#`gM!n!`N~2;s1e}k-AKG8K=+^VRslJJ2FLaP4!pJ_&9NpZqu`*yE(GX?@c*EX zC?I!(|9^G4e;a9d$GSV#RU=S+{~5V~#2gL&d}(#s?cH{1f7sInhSDtQQI_Y0=%!6MH;3VBK6mJYL@rA*=X*7=`jQMin{k^dW-dErd0h z5(BHeyR~GHn&pb*KdxN|u}D3LrOPGkpx13ztgI+hv=j^y4@ClrkWE4?qra=AU$P_X zn_tjnQ$V}$Vu+^r9*F9kVueJArVG?j2a4XW!*sN0ks9cXr#crz0%5lj2`s=cTSaw> zI1&UqqHqzbJVhi#8ba3>&tZ-u_&k`{FPBTN8+{Tdckxq1q z!`nEpGRaASyrxR7(*vQOqZCR8^8$)(3&*2XHm`AbJ%wjSv<>Ydk|4um6{2aP zo;+;7b|F-WRy7Y4PFO_=x@;g&Q$YsXUnMM=f>ERY)kQ4#NI;_IkUX;2dcj?c1raMZ z=P0(3v9M>eo>Pe?TbLyBf^6X_u$FlWMFeV&*C%QquUT_T&q~2x#wckf?6)0Q0=JbM zX>_BT^~^VpJY7C4$J<+d>ZoI>cR$ zBj4qS!$m<+@{&?s?n0(muau0Wt{D_<@jHK|qpS;G=lIK;1Ko$|+ZrJmzPxD)j=uVN zq?!7ol}>Hn!}y($uibRz7QYkvw6BNCc##l0UJyvri&PNTeu7} z%C#1`ti&K0tE@oj>a3Fsq)L@sB2(I=w}5UTh^TFizLPvMe8_PzikK8L$e=Xt032Jy zsGyt8*SATnF1uNvpjFIe=?p=^(g#_=;wgIwiwuEG(ziCZ{r&*?GU)nWVCd;fp+o;( k!=ZMpd?_S5qFCHuNAJ)j&cE-l@!IjA_EGtR{(AlKuUJj-C;$Ke literal 0 HcmV?d00001 diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_dc96f69a023cba74603789911c80e0999c3aba33924223d8fdbfbf7d7678f3e1.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_dc96f69a023cba74603789911c80e0999c3aba33924223d8fdbfbf7d7678f3e1.json deleted file mode 100644 index 337ea0939ed4739da7d8e2951affed9bc33be86b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60305 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 joxvrx@?H&$NC-~Vriq#qhbB}Y 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 KCLdg{ANoJsL}}ju diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json deleted file mode 100644 index e048700d163..00000000000 --- a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json +++ /dev/null @@ -1 +0,0 @@ -acbfb39d5f22cd2f096af600d2f19d618fa9898fecd778393c777d1b1785ee5fbad857cf62b3b69ade96894bafe42c7c \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json new file mode 100644 index 00000000000..5992d970292 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json @@ -0,0 +1 @@ +b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_89578d545ba2f6d4859c6ba9135914b55a2eeea35e7831ef86e2708b558f915f.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_89578d545ba2f6d4859c6ba9135914b55a2eeea35e7831ef86e2708b558f915f.json deleted file mode 100644 index a0e6e681a0683377b732c47bc65861a1ac4da0a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60305 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 diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_c4bb9b2e03829c0926d347692bc4eacbb5ffa75f6cb27d3ee8a17b185852f102.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_c4bb9b2e03829c0926d347692bc4eacbb5ffa75f6cb27d3ee8a17b185852f102.json new file mode 100644 index 0000000000000000000000000000000000000000..4890cb0a83921eb49ba1b3b268934309ff20fee3 GIT binary patch literal 60358 zcmeI4TXP#%c7^loU(tn9m695g0eF!_=Si~cv0`h+v7AXNlA>w?O%fK+4FjMg+N1wI zYn{^ox&e^ruVtlXQglHUh(4FS*IN5>4ru@OMUr#|={$YYFY@^`?aw=3Cco)JeSGh{ zn2yu=n|IlCHY{>I==3^!@!4?TAOHAYKfZYUmv5f`{NEoQeLMM&Z_+>g`}1F({N>^E zCl}AZJ3gD9{O8v%W>1b^9QD5LFJ@|=^WnvEm)rNz(|(#i$)0ATY@T_~^K>-Jq7iyH z&C)@UkFGZ!yv?%7?AzgNUQ9P14vPNOILqg=?=-3$^i}Ep)9gIG8X1N9PRlvZujc95 zDBB!ApI)sDTMqxKV*ZXf)9jb4;WV2)8_2fd{QB#>KfRvJ1^tuaDj#Hn?=t(6UyVi; z0P1s|X1nLihQDTmXZbw4$fiGCPqLX7wef-3k0rq?(tG76#rr&)J`23}cKoy8de*

dRilAQzca{^i;ymXXn|}#A$Nr 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 literal 0 HcmV?d00001 diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9267cfc8e7a6f302a2a7d179bc9337e03233ad6fd5c394dd4e6033f39e9447e8.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9267cfc8e7a6f302a2a7d179bc9337e03233ad6fd5c394dd4e6033f39e9447e8.json new file mode 100644 index 0000000000000000000000000000000000000000..f83ccb50780049b144ba750801f5100f2a707859 GIT binary patch literal 60442 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 diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_dc96f69a023cba74603789911c80e0999c3aba33924223d8fdbfbf7d7678f3e1.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_dc96f69a023cba74603789911c80e0999c3aba33924223d8fdbfbf7d7678f3e1.json deleted file mode 100644 index 337ea0939ed4739da7d8e2951affed9bc33be86b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60305 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 diff --git a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json deleted file mode 100644 index e048700d163..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json +++ /dev/null @@ -1 +0,0 @@ -acbfb39d5f22cd2f096af600d2f19d618fa9898fecd778393c777d1b1785ee5fbad857cf62b3b69ade96894bafe42c7c \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json new file mode 100644 index 00000000000..5992d970292 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json @@ -0,0 +1 @@ +b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json index 139f6b006ce2f29a75e7c6e93dfec71996eeeb4e..1a711e0ad724c2217b3e613ef0c3014e1c96c972 100644 GIT binary patch literal 29015 zcmeI5L2esI5Jj`rDGaT-;7Fuw`Vu*S;a#*a0>puncq8cU{;#V=4ISC+*O9UkK-;9) zJyrGV*RPtPJiNPj^XBsF?U%nkeg5O}{hPbITV8!=@9^$+^ZNApap;(S zd;s_I&o7_9-Uj%;zx;FC-n`G>_ZRmUzg*m1{`&jn`wz?2^=8>_uCLl-w^^2VdA;Oc zp6~NKe->V6(QdPU$GX!^>#e)I|Fc!cwcA5CbF(?T&C_lBXKAknj_`P#xQV;Cxg`|b zzIk+lV_k2`tsQG0LaigL|K4p5ajL~y2R-cDPjblSB0$7V3faa zWXy84|FMUJj~yT&U>E{nR;+xgfKI7+iX`ym{qvRe-9e~`V>)_a!_=ONb+W!Qap3ij zYh`5zG869D;^O~V@~@BoVvECTv_T%9T`6G|@(pD)zNH+qTdIzQmA5{S1a9E!2urM# z38GG2M52bRu-HVw;wFUSCh#iMk}lbdPXvO}N7siPBal$nz(qO?+cDAl&$w3!Ay&rM z_b8-Nk@Sfq{-iamWUVGH+N?1_Ad2eAwaQ(@&8EBQq0V@ASss>ehPoOqDeU76q$t$E z4OaucDhEX&$Df)OhjWxkPdUS4gA4>vus5l9Ay0%bj1Qh9UQ@z^9CU+Xp7LtWL`gRSLl3RY!2i%mMRcxLuX0V-Y@{fB{OP=p@25MsAvmjM=3lWt{2 ziY>W_SBgPq3D>3BhOx;vWWDlme{bdAFiuVM3-RNGsD#X|#vRcrs$)!iuR`sGI7rd5m5u zwj}9_ka5ZIgea1C>yjy0G{Nu?HIQQ%QOGMfqb zGqSQ}!i06wJenm(jA~|28T-4WsBiSw_>;W_8~f; zS9NAQgDs_DfSs8k7K}(D6fM`PGm6FGUQjg+ z1%FzFj$2_%a$&KRYK&JBTZ%}=PMecbL-^K8wpgkg698qaFa6hOCQ)aLOnR|voLXp3 zGGb!Kg#4Vk2(QGX0#Qk1i-l{vMMkM4Z;9Gw+_ZqiOYW3J$E7HVvCP}|jPE*N#I+ubX&;@PFw5Ane9Fix(@khxi z1d#HWEj;YBnZO5g-F^eS9J5wPqM5j;VyQ5_Dh*ZOiHRMrOcXtd%B7f4!jkpUD|ls1 z7?g-Qz#5?FiALuMIS&P_njHLy)$3yTG=cSDxbiB)g9^EZnPHa-RhNhm!w3#0l54Z2 zfDN6VwP(?s_(ShH-iWl?7?zgDJ1?qcWowJz(iv1%Q@a*F(+uN`62;1o=$sR^oV}o@P>md+ zmKF0LEKOLrdh8~TeT$97il;sGFg!3A_qjO;Heab{R(5F3fs^trn>0zdC*rXVeLNvPGhbi3u^6j-mgi z{V{i`TxW5juz?H@6>vix++MqCQs&f8N*UY>LzKYE0h{Azi(z0_8?&VXap}nMRp~{| zRJyATnJr+Iq+8jPpBNmiJnMC@lui4bhEHX-xzM%x;*?R?@(nC}ugJ+4;54}QOdP+#$8WRvJTvS70G||$1VoSVIog*ex6s^-Zjgv*& zNuv6t6|4zhZSGP{3fQ@RW>D&+l`U{o((2w;Rp7=e=-PU-IL!!Fasoqk%$AZJ6?=!* z@Pybi8d}E;ym-~v{;VzV$G@(?*Oy)K9bWmCto27g%NkNS)J H^YQ*0RQ_wV literal 27353 zcmeI5&u$b)5QlU2Qy`!Buw!-&%S+?|5V!b%B87+~T#(5t2IufFCbU)bM&o>w1#%d7Y8JA8M)d-?Rg=b>}@ z;f~zPKR5Jm*ImCCxoh zNc;LBiCpV&+8r0Za$xNp)Vjj@@5Antq#D+`=;_$Ll1sJ}AtGrKC>&)S%l9Nt{QjMd zbSjtQo89sCb~>d)=)Q|}c)%5+H{n1;5mRKh)PZ<>xK8KixI11oqOMzJZ+Us#!`m@( zwl9tlxGZFg1UM$qd*-|hX(TY>ukf=8u95$vGN`k1YLdS97T@CK>CS5KdoE|wx#fva z?K+P-X1O{(ogwgv0|fxaAsA-m%Et=m+=}N+LSMeWU0L5>O|d-~A$7NWEkHNFM8O$bb7fOoC}gf=i#L_kpM zt2a+%WwyYrwYn^&n0$K_u6#~PkwclPjk0kq@J6B-Agm9us$fgO&11j{dx+A_Exs~} zV_gXx>;?tv)7*wjgZ1g3HbnZNiJ}%KrSbeJZIg*}Q9GcCWK5HBFq4V7IA%7q#KzkE zX%xoHgi!0-w9?M>C6=rlS8|$AViQ}^SIt=qd!*YdhNFmW^`_kcJdH(_bL5j-xV{+; zWEGZ7Ru#gv`eNhz)RKb>y(k*{lb$6aol_ z)j(j2J&R5hpd2w^k9Cb49I6d=I<1w%`dl8^kRztDa>!#IA>u1l9Z_6zWr0wDNzAm7 zTCdsyTY^RTq*+nilEk-?E9LV*KszJf1hE2d317;<7EwFf31oWh!f3y81+aGoloBtz+CWk(f2u#PNP&bhct~HZ}|+y)m#J zHxhEU;?I{)wJfqqr5j?qbxoHeN=zlU&`XVVL6I&r+!z633h}+=K>;wYu-U1xL7DioyZF_=7cB#axoz8y=(fx~SSH0P_n#hkBbJ_ZOOCJIVg(Pq^Lhqdm+D9_N8 zZpT`tV~64XG5$VV=ry7v;zZfX5YFoI;+Rmf8sSt|=cFh5C&G=ZR-;)S^QczibBIa^ zvt_~_5M@G?e41Vp0u;GFl?u{trHFKC(-ZKm>9pp)smpDmu%($q zoOxt}0!U0~t2J4fS;_UAl;c2HpH65P&K7!tVmMZ@&DL@yYsx~l4uRNIx;ap>C8*8e za3(~uGTM=qTt993<~DMOrg?3wLP*j*n0@$E4GATg*}Uv;yDe;>L4qXlAWa`p9ulvj8nNq$v0_2 zlM-4Rd+0luIM&|u$U5q!C(i=4OSGu~F+}0moM=pE!%?P=2od=ty($DOrT@!nooQ2Y z{DEB#4uBha0d5qhw3C(G5(R|`OAdQd&LPVv2nuX4m>(lCh?d`0g}vy!JBu&0`gZ`l$lEnV4S%9aqy>hk?a ztgfz~e4@A^3JCF)iju`DMC4WlZW<0kTgYipR%ICiesWSZ_CssKQUTXntQKVta|gs! zG73fu6db>Mwb!?HRmp^(d?>s!AA}A?szTccOJai6pfGmrSsBL`QBG^w_904@cD$rm zN|ELv>RZovHt&bU_w7eG{J>_POSgy6*BfA?qdQN<=UMM(zoel39EkVX?tf3gzx$C8 zdaJwK9A}N6Fh}N)Dx?XQTfNf@%=rnHa`ZPS*b?l=e`cHlRIn1T27|6AY}$Xq2Fzf@-ZgP`IuE%KSc%Wr6T^xKboCyJ@~i8hiEM z_ndp1WH-qf_S3R}0I@->NcMfHs&nd8-AiGA`yxp?gLIz0=@p#EZ%;3#XaD)^Urr9rx;WV2)AIP@h{N`ESpWaO73jLE}kq@%Lx0!v(7o$-n z0QEUfv;A{s!(X$(^L(CNWz!#TCfQ7j+W3I%#}eQ*=)Llr;(eY?p9kD~d;VKuJ?md* z<5VH_7HhjZ%jmoe&;2k`PKXYQaXK{DmfwW$O1#S0>uC*~ZI)EA&{GjRpIv5C1E=$Zvk6T@Rx;+s0TkhQ_|0~SEW-B5C5mzJAD1y$wBY@m&yD(OV$P_BQqiqN#;r6hr?MSdSxFH zy%}Y*nZ8Q%sCwE7sA-q# zmqL49O2%wH9p+b?u1|K5@9_Nfl81-qB4YR8LGR=Go7eX?7a0%p@3Q=Aey!b4Hex$Y zKdhcT*nBuCX2aby-6Uz$lgP}YBs;n~O71@?F76*yIZO_pThD0$T>UUd%i*YH&*Wb3QWNbjau$i_kPemK9@)9&hNPw%wbSgT&8 z%Hiu`TwG1l$#o(|rTw={kS@9x_c!@+uV0Ma={O}`EN1iMB1_a|q$96rEs6p(%-7D` zYT>w?f2XB)uq2kkTDfYSK==N>67WyTp$*CIG|i#ojojPd%;V%zLT6o9?2|#L(1}}u zC02uUcHJzab`<$fj9NWyq&BrL4qv@GS_@I_(T)_W$Whx+ZYtGQD7T}i8oB1{|Bd7e zfbPw{Ou3y+Ye}f`o_)|cMHOR76p2YTp3HBYqkWxll=G?HPt*~-Q@0T5^oePj{8gu> zpa4Gng}%W3MG~5PX<5G9d2`>{T^T;jREV?b%QPIIZsBPo>tMnSXf*BUSJD_369YKxHZx3v=f8A4T)X?xa^qTqnMK&0wK4!WGrIX2M z*bkNPUq2iu~QIBxI{x36 zLpmuG?_VxA*j_w@ciFaH6vZe@^9Bg~=yOUDjy1_3yBw;=N#0*etk$xz@@f|IIXM&} zH$|TPTRgh!v+r%90>%0mq-WRe)h1>wTa`&ZEd^I&Ush`7+JsOd@kN4wf)SgOngv5r@f+U$5^l1D_{(a99I2>bJj&YBHT2>0>&Z*7tRAATr{qsBt z)z|8$>kjo4Qpj}4s+(ew?B-v`2NEO z-6Wlr8Z$^PZjv9q{wnEpPtJ~#c#v3CXC=`zONQfdyq^6s85e`$Wm#*&IcwlMWF5i6 zKwaGEl&%Yv!LmB6c)UWVrp2o}%USD7$lvEiai&Hk8+@bExv2rQ3yUh>EL}T#h`3UW zV_2`zy-76-l)|-JzZI3MMYfs|H502Qb#@q2eZHsV>D=A!bna+%eCBJ?KW?6HHoB6h z#X>h)$?Q5kJU)96Z}Y-^o4TDW4;_!cOx3@N$7<yqz$*oJA=An zs{(VI>TZQ}wNe$57E1H|W^4TE$rns3o$9QsMeSFEb+M>@y&C;wRP^6|lMSz~ecw^} zxnVW&))A{Uo=u9rFV}X>-tp{eS}Z1^uUgtZFW%|~$kO39Gkm*}jyG<#-ULvUYO(7J zN!)p_V`28DKT351@#L7j%LG{8b>GwPZp#Gh_;-U;KX7S$=b0~c){k`I6t3bsdw!_t zMfJ0(ffJojLEc>4RBee*Mnl~|X{(S2o!MM>*81c)eev;&fBNFL&R^elzWk|otjqN7 zfevYYogVahkMy~xzy1D9@AaqW&l+@kaQ4XK>XWKdPxbt+QLC}t^KzR92j>s-n2gk6pSNSE&B)>A|^-3ckig&(Fd)S~8gE zK*&sQq!?+Ohj(qf_b;F9F(=w`_VD2BWWPBP2ZejN*Xi0X1$wVL4nz!040bTxE}pH| zDdTf?aCRI5^&nXG$RE$Tj@y~w3|}@0V6SIu4S^Y>-Al{;Q9-i-P57nw>~$^#e;XO2 zQ(>x%UUAEh{PBEAHOIFOXTUkwX`sS7I~mhEKD*sQyYGD*0y}Jmm@pMq?n~bxQSN;aZ?vMZr_O)9xrigoEjc4{iIt+56LcQ zuuN)hzf+r7!dMga4$BFFFEu4CYff|qcaOE9IqG&%eNqLHrF3KA6S`b9iqOwkv5GIjLqTEnbg0Zru zQ3U09i|~@{bG9N!WDg0i11rY~)eQ#~XENR{Lm=z|iK<-i6xxfnNI+O(?7OH-;BZq- ze7Dk4I4I9y!)7={DhdZ|^Sp(4g|b74!&p&AoPaWn$VeQIWWiJ93*t$jA~=$Ww=hzsIf5G5ef%k6fy=4RwR+0JN{Bm=xp;ydVO^)5MM0Ia)HF( zgApH8SUKOANs1E5H3wFjkB%4+WgMj-7l=zvG`&!4Re~vEi@zEB zSzQ(igsvVe6i`MeN+_>k{dGnY7aUS$9943J0`eE;avKT>FA^dR7G#uoo`MucK)_vW z7_UTz8^I^T0!cug!gk1xv}jjk72$0Z9F%=FOeGH%R;Qus3RiUs5w<^Rf`HD5UHNDxZjSo6C>bJhoO&Uu5JVzXP_>ozqPpV{an3gnROte&wl;|bsw5TJg+)n>C0vSLQ?W8* zi3|1`s;;7nNehp$vZ_Vuxo;=FJHmR=P5_=~WfHcEcu~fR$VllpVWWAXSdos}B%u{b zThPXjRCBvP0%iNlH5f{7#%m~UoYZ~#wtPl_= zQ1Y5!ZIg&Jp-O>PR@O8x)->fm*UCf|j3%YM#uH9DhCxD``|Byh3yYfwL#9N>fk{eR zx<1JflP6#SOp@1nk>oAM!`dXrjR-oV$S~4^Mg-9=?s?yK}PC;Hor6uBQtKgY8PGM?5 zywLj17dJ78G+AdPm{7@`(KM=m94#ByixL!syHbfD;w{K{lTe_OV&N^qt2uj}N|BJw zVX;7vdCVRp?T1lu-I>Fe&lwBB(+J=|)~Su*fQLk8s;q zs1JvM!UafyA`G!Ts-!T9oOh&N)4a9|AzT1K^~of*UY~d^1|qm^jJ7~gQkf%1W^+U1 z3EVab9w?$C&4I8z5W8|b$v#h!EYOn+Y#K{ni1;AHy?*0*#0Jw~lH8$**4#%4Mf1TW zI>hpF3du@OQ7|b|Aq%iCEewM|xATRu8k(fVQGNGu07k0+He<}4Bu_hv+VY?1;66V|*Uv5m0;fs#ouP`)W8 zCOP|PHgWhITk43sAS!J~5aK9G5NLO0w2<*;hLYU$6V^n}?M1AZsIh5r1|iCci1B#` z%Tr=GQW&&y2@?U=Q(81Okf<#b#%EY47p42nSxN$BMMdLj?l(5ub&Bw<#FrS~k`9_{^yk1q4M^E}OLERO>0ij!uE%W?$6pQ$3VzRCVPD0x>v( z+;@b@kUFmEoC@GfnReOI}%m-Ydvo2HAu6(8v*4VQc;yC_ho!Wu+@^0|dw zdPu1yuW790JKaT7P6+EpcT@t<$_zCEF%@u>^2kS9 zg7id#g%P2F*0)NKUAzV4r}7=iuiH5SnN5O6LOV`c8gC)12>Cr2rkGWNY$2>s>#M~b zC<3<=#W{-(Bb2v7oM2(NNni~(tyW5wooejLJ@>D&TNMg>TppU>G+5vp(2)Ccw1|)^&%#<3oLSkWs?dYts02rEd)mi zjt<%qC^SA233);PIf^Jj%RThMNeYj^A}ZoW+`@&XaeM43C>>%35iD#EG07RK*rL-4 zp_5&fltCA;TDBmq99Ll_v9d2MG!X7WI|^F`5%d&+NOI5!Y8I)j2y_pYJp>NJM_h>Z zdlpJqr3Tr>vIC=J_(;!YN3;vcSx*t+$u1tx#frr$kP1z)BPyDtDBBTDp|~r;(0%Mk zlpw@Ls6PsqtfCEo$CFI-VBta|tmcZ8k{0=H-$^ps3u2PTM-Ddzk!G&!L4kFJBH3XV zM0KbPraELu8(kM(Ez7qKO0_Vb4BviB`$P2_nxvbP6 z?Ndob>Vl5;l<+~XK!>35s(@%0#fp&1^q}VpWKV2ay3-MN}NU-o=`0JA4gN>pchrIF>cw_G=t(tHY;c^#ReWddw*L>xRtj?msrxD&$!`rfKR%9e|g|G0d0W1V^stCy=-w|CH@ zUO5u*uA-MolizDKL*puZa?tQ%EY=5u(rbUB!?nn;Av&$Xf_L7+$nRq!Z0n$BM+(j;PAe z@WR4j$4PjpNp?99p2-g7ZHt45stnOvdjVTH^Q1+l%Xfr`cA?>tRir1iBczDCvnD1X zL9j6`3Yqc<$`19~3=t2Z@;JeXVbOgQURy<|?k!-qW8bv};jO1=BN{GEp}ruhi@L-l zQyr}@`-M0Ol%oXo%_gBO1UE`>l-&ZFx-5aBD8nrrA9bn}YZ4_hT#nEw6pKg?(puOm zf}pT4g3V8_bbU%!WQ^jY7xEX{W1tlxr~{@SLQP%}x|UWE`o%yotfA~XP$;#dNSLWvX_HHII>TUtQ+Cr3%GKk>p-!e*n7u-!1g?L(sARIfF}V<%ggcM@i%zcJz*2<#zn5 Q^`CGW_rJ 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 literal 0 HcmV?d00001 diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 0854fe6f129edb87de99436d8db50e6466d4425e..d66f637397687d4382ca27b9891e494bcf1535c6 100644 GIT binary patch delta 3111 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 diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json deleted file mode 100644 index e048700d163..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json +++ /dev/null @@ -1 +0,0 @@ -acbfb39d5f22cd2f096af600d2f19d618fa9898fecd778393c777d1b1785ee5fbad857cf62b3b69ade96894bafe42c7c \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json new file mode 100644 index 00000000000..5992d970292 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json @@ -0,0 +1 @@ +b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 0854fe6f129edb87de99436d8db50e6466d4425e..4ca3e6ba6603a850b66ab825624349eb7b1fa43e 100644 GIT binary patch delta 3118 zcmYjTYjBk16`t>sO~NfJU_dA)T#Ar<-+u4zx4YyVcBUKUZ$^2UtS4tPvZ9Zh%`NUZH{F1h4Ha`n7M1aCTbP#bLsHXfP25}q-m^PKghLxw#V;JT1g&z+^!qxnLfwj!Y)hk zK(DQ@=JETnW31g?!7nVceE#%7{MlV+Wq4W>?s;{Z+4XMB3V7nYou-xajwaB>Ajl*`t}q>{c~dc=o&}S zSe?oE{L?sJ=yFP2ODbBcSq@p)G#@LdpcOEdBuSQ&ke&+>tCj8wD#`0N-}+~(21 zztfy+0X#b|CTXHuM@9z{Da!RKeJ3X_Am@DGvQuqsm*U3g(N>Rk*ZG{k7d8D`6CysG z4>XjgmjzU8aH+V&Ao)+h`TdJYR$H73@~aa(y~#;Y|3s2@%>ziNBvPWQ*OC!vrpl)J zK0P@#r16}o=EO`yy9l6kIw5;GC(GCNf=z)RP;IMAf1a;cwE!=nAE$Z&I+--9Iu#E$ zAP%W@vD@5M-yZV04UXcQM{S@v%M|RYWe2=^ElT)QA>`7#7P6^u>6La*4)fisaf>kV z-~yDp0{jr@gjGpCy3fi`VP=xs@{Y;&E4C6cCD!>o93Z4byW+9UI4D%%DIHGT;9Q_8Wuu?B1M9oNMx|LEc>H*zvJW;}iq;*1IKCJHJ4Ia^Lyos#@e5~tu(gbzX~ac0LV3GIm&Y~L z?w?am4=wZ|10i#oE;gbXWNGVQuK=Tn-igsCv&F1pe6$HsO#D%4LM^Mtn|l-~&&c&L zNgyI2Hk8we#iq^!LkQ^ETu7q}6pc22U3*W}JY+g0&~nBv9fZ7gy%^BRSenHa=)09k zKHG-(9)P1ALu@mz+h3#ohoZvnh?~oSq{f+sW=SZBpgYC~)>w6tK7DJdt_V1zJfR38 zzu;<1qMyZeSt@Sxxio2c;=kf{v61}x`WQ`o#TzNK++^`slO00cikq7ei&#|K$DVjj zf^u&Mv?Hc1QkbtewE@b@iGIhGUZz<+DN5WNc~s9n9kPyeA4Ds{?#d;o*kaZ%?=hL6 zAiTR8(w%=jO7`4*pU=n(#dB7S`_5R)#eIE#=Qv^(nT+Q^cq?zca;!RSSOvobBFIQT1A+>JA| z`}H*c;vPI9EBC^u#3BV^1Qivv)M&Znk7pNbFsp2)IAv9F6v)b(#ka z58+sfPQ@fzmtR|rej885=(UVD_@R}hcSNH|=ebo`aZT?=?TuX=U!0_P!KagG4uZf9 zGv*rcMX{o_a}`ofrkspOmLX(CD+@wk-gF1vg4{(cfi!v3OQF_Zw>b$e4M9urf9}mm zU#ZZf`D~U*Iv8UxnJnh7ZgD*Raf@>&KXt2><+00lO2&o+cdo@-VkOtAErfYwn+_4K zW@1Hu4j9Op+F>w&8GMkWk8cl5cl_@OydTylxoM+5QO-}>2zY4nbAn36bvksV6@0*8 z(|5=>^=)0604iXLbl~xhB-OrUf@xSM2up*|vyZEL747}fXSVN2P%ghbiK}x3pBq}i zy3=VuBnZPbQrz8PMSeZd?(?XN4Q*GU_Bi+xdWI?84N@o%(%nUCtr#?U>xoT$0R8!pp z?Y^bB?F3{n+H9KKu||()$bz)(PiChHLG##N6iphOCg8rgA)UU}5I7Ps&0nsoZuG); z0vD=64=O#Jrrnc@{?nwX2<(%E(y!Ssy^))d7 delta 3352 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 diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json deleted file mode 100644 index e048700d163..00000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json +++ /dev/null @@ -1 +0,0 @@ -acbfb39d5f22cd2f096af600d2f19d618fa9898fecd778393c777d1b1785ee5fbad857cf62b3b69ade96894bafe42c7c \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json new file mode 100644 index 00000000000..5992d970292 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json @@ -0,0 +1 @@ +b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/msg_GetDataContractRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json b/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/msg_GetDataContractRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json index 2c110c17ed1d2f0163a7d67713e841eee4696a2b..c48d9bd3101da05632d500c8f50879486a32623a 100644 GIT binary patch literal 29045 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 IW%KI40W3z0(*OVf delta 3720 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 VsJI3CLP;wg^D1W=Kk$&V>p$+;V6p%J diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json deleted file mode 100644 index e048700d163..00000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-1f0a25d463a2912cd31dd4f91b899a143d6ae990bb9bc89cb34f7c5db8b1b705.json +++ /dev/null @@ -1 +0,0 @@ -acbfb39d5f22cd2f096af600d2f19d618fa9898fecd778393c777d1b1785ee5fbad857cf62b3b69ade96894bafe42c7c \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json new file mode 100644 index 00000000000..5992d970292 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json @@ -0,0 +1 @@ +b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file From 6e1705124dcd8dfc73a164fc55829bbaf2138932 Mon Sep 17 00:00:00 2001 From: Paul DeLucia <69597248+pauldelucia@users.noreply.github.com> Date: Wed, 9 Apr 2025 22:47:14 +0800 Subject: [PATCH 20/46] feat: contract descriptions (#2533) --- .../rs-dpp/src/data_contract/accessors/mod.rs | 21 + .../src/data_contract/accessors/v1/mod.rs | 9 + .../token_configuration/accessors/mod.rs | 14 + .../token_configuration/accessors/v0/mod.rs | 16 +- .../token_configuration/v0/accessors.rs | 10 + .../token_configuration/v0/mod.rs | 3 + .../data_contract/serialized_version/mod.rs | 7 + .../serialized_version/v1/mod.rs | 7 + .../src/data_contract/v1/accessors/mod.rs | 15 + .../src/data_contract/v1/data_contract.rs | 3 + .../src/data_contract/v1/serialization/mod.rs | 3 + .../src/errors/consensus/basic/basic_error.rs | 7 +- .../invalid_description_length_error.rs | 44 +++ .../consensus/basic/data_contract/mod.rs | 2 + packages/rs-dpp/src/errors/consensus/codes.rs | 1 + .../src/execution/check_tx/v0/mod.rs | 10 +- .../create_genesis_state/test/tokens.rs | 13 +- .../batch/tests/document/creation.rs | 6 +- .../advanced_structure/v0/mod.rs | 25 +- .../data_contract_create/mod.rs | 365 ++++++++++++++++++ .../contract/insert/add_description/mod.rs | 134 +++++++ .../contract/insert/add_description/v0/mod.rs | 214 ++++++++++ .../insert/add_new_keywords/v0/mod.rs | 4 +- .../contract/insert/insert_contract/v1/mod.rs | 12 + .../rs-drive/src/drive/contract/insert/mod.rs | 2 + .../group/prove/prove_action_infos/v0/mod.rs | 2 + .../prove/prove_action_signers/v0/mod.rs | 3 + .../group/prove/prove_group_info/v0/mod.rs | 2 + .../group/prove/prove_group_infos/v0/mod.rs | 2 + .../prove_identities_token_balances/v0/mod.rs | 3 + .../prove_identity_token_balances/v0/mod.rs | 3 + .../prove_identities_token_infos/v0/mod.rs | 3 + .../info/prove_identity_token_infos/v0/mod.rs | 2 + .../status/prove_token_statuses/v0/mod.rs | 1 + .../v0/mod.rs | 2 + .../rs-drive/tests/deterministic_root_hash.rs | 2 +- packages/rs-drive/tests/query_tests.rs | 60 +-- .../rs-drive/tests/query_tests_history.rs | 8 +- ...cec7d11a37410433366315d1103f81859344b.json | Bin 0 -> 60302 bytes ...a9664c6f3704dadf217d5b236f608cb4dc8a1.json | Bin 60322 -> 0 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218933 -> 218972 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...e8920dea81c3f44b9549c238dcb82cccc9923.json | Bin 0 -> 60287 bytes ...4eacbb5ffa75f6cb27d3ee8a17b185852f102.json | Bin 60358 -> 0 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218969 -> 218957 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...cec7d11a37410433366315d1103f81859344b.json | Bin 0 -> 60341 bytes ...10a8556ecf1145e99c87071cc8998a97d7ccb.json | Bin 0 -> 60467 bytes ...a9664c6f3704dadf217d5b236f608cb4dc8a1.json | Bin 60316 -> 0 bytes ...337e03233ad6fd5c394dd4e6033f39e9447e8.json | Bin 60442 -> 0 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218927 -> 219011 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...501c1ba166a2dd8f6efb31b0289dc011da983.json | Bin 29015 -> 29024 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...086bcaf743e2fa8f6b8b143deb29b5265e971.json | Bin 55048 -> 0 bytes ...7ff33d2448d30f2527374349b9f507b44c5c1.json | Bin 0 -> 55034 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218927 -> 218957 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 218957 -> 219023 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...48c03122daf7ab2e77108f4bf44af1ad15eae.json | Bin 29045 -> 29036 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - ...067bd9ccc29eca3092a5664a5a9ba3bb7e967.json | Bin 225261 -> 225321 bytes ...f8339ad60debd43b3f430bd12d51eac268936.json | 1 + ...a891ce226199229e3031f71994d14dd32f088.json | 1 - .../schema/v1/search-contract-documents.json | 81 +++- packages/search-contract/src/v1/mod.rs | 20 +- .../src/errors/consensus/consensus_error.rs | 5 +- 75 files changed, 1099 insertions(+), 63 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs create mode 100644 packages/rs-drive/src/drive/contract/insert/add_description/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs create mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_9064a0dc37a9f6f767159a4325ba9664c6f3704dadf217d5b236f608cb4dc8a1.json create mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_2fd2f7aebe5686d4e4179323b49e8920dea81c3f44b9549c238dcb82cccc9923.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_c4bb9b2e03829c0926d347692bc4eacbb5ffa75f6cb27d3ee8a17b185852f102.json create mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json create mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_4816e45a0ba02d69c291f23322410a8556ecf1145e99c87071cc8998a97d7ccb.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9064a0dc37a9f6f767159a4325ba9664c6f3704dadf217d5b236f608cb4dc8a1.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9267cfc8e7a6f302a2a7d179bc9337e03233ad6fd5c394dd4e6033f39e9447e8.json create mode 100644 packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_96c4914304501c97094650f1da1086bcaf743e2fa8f6b8b143deb29b5265e971.json create mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_f531f69255dae40cef880290c177ff33d2448d30f2527374349b9f507b44c5c1.json create mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json create mode 100644 packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json delete mode 100644 packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json diff --git a/packages/rs-dpp/src/data_contract/accessors/mod.rs b/packages/rs-dpp/src/data_contract/accessors/mod.rs index 846b6752282..8557931c81e 100644 --- a/packages/rs-dpp/src/data_contract/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/accessors/mod.rs @@ -284,6 +284,20 @@ impl DataContractV1Getters for DataContract { } } + fn description(&self) -> Option<&String> { + match self { + DataContract::V0(_) => None, + DataContract::V1(v1) => v1.description.as_ref(), + } + } + + fn description_mut(&mut self) -> Option<&mut String> { + match self { + DataContract::V0(_) => None, + DataContract::V1(v1) => v1.description.as_mut(), + } + } + /// Returns the timestamp in milliseconds when the contract was created. fn created_at(&self) -> Option { match self { @@ -422,4 +436,11 @@ impl DataContractV1Setters for DataContract { v1.keywords = keywords; } } + + /// Sets the description for the contract. + fn set_description(&mut self, description: Option) { + if let DataContract::V1(v1) = self { + v1.description = description; + } + } } diff --git a/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs b/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs index b798c6e1f53..82a32be1b5f 100644 --- a/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/accessors/v1/mod.rs @@ -69,6 +69,12 @@ pub trait DataContractV1Getters: DataContractV0Getters { /// Returns a mutable reference to the keywords for the contract. fn keywords_mut(&mut self) -> Option<&mut Vec>; + + /// Returns the description for the contract. + fn description(&self) -> Option<&String>; + + /// Returns a mutable reference to the description for the contract. + fn description_mut(&mut self) -> Option<&mut String>; } pub trait DataContractV1Setters: DataContractV0Setters { @@ -104,4 +110,7 @@ pub trait DataContractV1Setters: DataContractV0Setters { /// Sets the keywords for the contract. fn set_keywords(&mut self, keywords: Vec); + + /// Sets the description for the contract. + fn set_description(&mut self, description: Option); } diff --git a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/mod.rs b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/mod.rs index 662ab19373f..31bc9009da0 100644 --- a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/mod.rs @@ -142,6 +142,13 @@ impl TokenConfigurationV0Getters for TokenConfiguration { TokenConfiguration::V0(v0) => v0.all_used_group_positions(), } } + + /// Returns the token description. + fn description(&self) -> &Option { + match self { + TokenConfiguration::V0(v0) => v0.description(), + } + } } /// Implementing TokenConfigurationV0Setters for TokenConfiguration @@ -240,4 +247,11 @@ impl TokenConfigurationV0Setters for TokenConfiguration { TokenConfiguration::V0(v0) => v0.set_main_control_group_can_be_modified(action_takers), } } + + /// Sets the token description. + fn set_description(&mut self, description: Option) { + match self { + TokenConfiguration::V0(v0) => v0.set_description(description), + } + } } diff --git a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/v0/mod.rs b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/v0/mod.rs index 59fa3d34b6c..093d4622ea9 100644 --- a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/accessors/v0/mod.rs @@ -14,13 +14,17 @@ pub trait TokenConfigurationV0Getters { /// Returns a mutable reference to the conventions. fn conventions_mut(&mut self) -> &mut TokenConfigurationConvention; + /// Returns the new tokens destination identity rules. fn conventions_change_rules(&self) -> &ChangeControlRules; /// Returns the base supply. fn base_supply(&self) -> TokenAmount; - /// Returns the base supply. + + /// Returns the KeepsHistory rules. fn keeps_history(&self) -> &TokenKeepsHistoryRules; + + /// Returns if we start as paused. fn start_as_paused(&self) -> bool; /// Returns the maximum supply. @@ -46,8 +50,10 @@ pub trait TokenConfigurationV0Getters { /// Returns the unfreeze rules. fn unfreeze_rules(&self) -> &ChangeControlRules; + /// Returns the destroy frozen funds rules. fn destroy_frozen_funds_rules(&self) -> &ChangeControlRules; + /// Returns the emergency action rules. fn emergency_action_rules(&self) -> &ChangeControlRules; @@ -59,6 +65,9 @@ pub trait TokenConfigurationV0Getters { /// Returns all group positions used in the token configuration fn all_used_group_positions(&self) -> BTreeSet; + + /// Returns the token description. + fn description(&self) -> &Option; } /// Accessor trait for setters of `TokenConfigurationV0` @@ -92,8 +101,10 @@ pub trait TokenConfigurationV0Setters { /// Sets the unfreeze rules. fn set_unfreeze_rules(&mut self, rules: ChangeControlRules); + /// Sets the `destroy frozen funds` rules. fn set_destroy_frozen_funds_rules(&mut self, rules: ChangeControlRules); + /// Sets the emergency action rules. fn set_emergency_action_rules(&mut self, rules: ChangeControlRules); @@ -102,4 +113,7 @@ pub trait TokenConfigurationV0Setters { /// Sets the main control group can be modified. fn set_main_control_group_can_be_modified(&mut self, action_takers: AuthorizedActionTakers); + + /// Sets the token description. + fn set_description(&mut self, description: Option); } diff --git a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/accessors.rs b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/accessors.rs index 2e7c1353ad4..889df4e4d0a 100644 --- a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/accessors.rs +++ b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/accessors.rs @@ -149,6 +149,11 @@ impl TokenConfigurationV0Getters for TokenConfigurationV0 { group_positions } + + /// Returns the token description. + fn description(&self) -> &Option { + &self.description + } } /// Implementing `TokenConfigurationV0Setters` for `TokenConfigurationV0` @@ -220,4 +225,9 @@ impl TokenConfigurationV0Setters for TokenConfigurationV0 { fn set_main_control_group_can_be_modified(&mut self, action_takers: AuthorizedActionTakers) { self.main_control_group_can_be_modified = action_takers; } + + /// Sets the token description. + fn set_description(&mut self, description: Option) { + self.description = description; + } } diff --git a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/mod.rs b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/mod.rs index 62cb3ba138b..4f56f36926f 100644 --- a/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/associated_token/token_configuration/v0/mod.rs @@ -57,6 +57,8 @@ pub struct TokenConfigurationV0 { pub main_control_group: Option, #[serde(default)] pub main_control_group_can_be_modified: AuthorizedActionTakers, + #[serde(default)] + pub description: Option, } // Default function for `keeps_history` @@ -265,6 +267,7 @@ impl TokenConfigurationV0 { .into(), main_control_group: None, main_control_group_can_be_modified: AuthorizedActionTakers::NoOne, + description: None, } } diff --git a/packages/rs-dpp/src/data_contract/serialized_version/mod.rs b/packages/rs-dpp/src/data_contract/serialized_version/mod.rs index cfc34db8115..71cdd23526b 100644 --- a/packages/rs-dpp/src/data_contract/serialized_version/mod.rs +++ b/packages/rs-dpp/src/data_contract/serialized_version/mod.rs @@ -106,6 +106,13 @@ impl DataContractInSerializationFormat { } } + pub fn description(&self) -> &Option { + match self { + DataContractInSerializationFormat::V0(_) => &None, + DataContractInSerializationFormat::V1(v1) => &v1.description, + } + } + pub fn eq_without_auto_fields(&self, other: &Self) -> bool { match (self, other) { ( diff --git a/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs b/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs index b79927dd307..c9144dfa7c7 100644 --- a/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/serialized_version/v1/mod.rs @@ -63,6 +63,10 @@ pub struct DataContractInSerializationFormatV1 { /// The contract's keywords for searching #[serde(default)] pub keywords: Vec, + + /// The contract's description + #[serde(default)] + pub description: Option, } fn deserialize_u16_group_map<'de, D>( @@ -129,6 +133,7 @@ impl From for DataContractInSerializationFormatV1 { groups: Default::default(), tokens: Default::default(), keywords: Default::default(), + description: None, } } DataContract::V1(v1) => { @@ -148,6 +153,7 @@ impl From for DataContractInSerializationFormatV1 { groups, tokens, keywords, + description, } = v1; DataContractInSerializationFormatV1 { @@ -169,6 +175,7 @@ impl From for DataContractInSerializationFormatV1 { groups, tokens, keywords, + description, } } } diff --git a/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs b/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs index f5991b3d72f..72bdb5069c4 100644 --- a/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/v1/accessors/mod.rs @@ -234,6 +234,16 @@ impl DataContractV1Getters for DataContractV1 { fn keywords_mut(&mut self) -> Option<&mut Vec> { Some(&mut self.keywords) } + + /// Returns the description of the contract. + fn description(&self) -> Option<&String> { + self.description.as_ref() + } + + /// Returns a mutable reference to the description of the contract. + fn description_mut(&mut self) -> Option<&mut String> { + self.description.as_mut() + } } impl DataContractV1Setters for DataContractV1 { @@ -287,4 +297,9 @@ impl DataContractV1Setters for DataContractV1 { fn set_keywords(&mut self, keywords: Vec) { self.keywords = keywords; } + + /// Sets the description for the contract. + fn set_description(&mut self, description: Option) { + self.description = description; + } } diff --git a/packages/rs-dpp/src/data_contract/v1/data_contract.rs b/packages/rs-dpp/src/data_contract/v1/data_contract.rs index 19d2e7b9325..37318e70ca5 100644 --- a/packages/rs-dpp/src/data_contract/v1/data_contract.rs +++ b/packages/rs-dpp/src/data_contract/v1/data_contract.rs @@ -110,4 +110,7 @@ pub struct DataContractV1 { /// The contract's keywords for searching pub keywords: Vec, + + /// The contract's description + pub description: Option, } diff --git a/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs b/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs index 05e40710b7b..332cf574d2a 100644 --- a/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs +++ b/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs @@ -112,6 +112,7 @@ impl DataContractV1 { groups: Default::default(), tokens: Default::default(), keywords: Default::default(), + description: None, }; Ok(data_contract) @@ -139,6 +140,7 @@ impl DataContractV1 { groups, tokens, keywords, + description, } = data_contract_data; let document_types = DocumentType::create_document_types_from_document_schemas( @@ -168,6 +170,7 @@ impl DataContractV1 { groups, tokens, keywords, + description, }; Ok(data_contract) diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index d727e14f865..b1743acfa86 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -76,8 +76,8 @@ use crate::consensus::basic::{ use crate::consensus::ConsensusError; use super::data_contract::{ - DuplicateKeywordsError, InvalidKeywordEncodingError, InvalidKeywordLengthError, - TooManyKeywordsError, + DuplicateKeywordsError, InvalidDescriptionLengthError, InvalidKeywordEncodingError, + InvalidKeywordLengthError, TooManyKeywordsError, }; use crate::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use crate::consensus::basic::overflow_error::OverflowError; @@ -531,6 +531,9 @@ pub enum BasicError { #[error(transparent)] InvalidKeywordEncodingError(InvalidKeywordEncodingError), + + #[error(transparent)] + InvalidDescriptionLengthError(InvalidDescriptionLengthError), } impl From for ConsensusError { diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs new file mode 100644 index 00000000000..7d8c04788a5 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs @@ -0,0 +1,44 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Data contract {} has description with invalid length: '{}'. Valid length is between 3 and 100 characters.", contract_id, description.len())] +#[platform_serialize(unversioned)] +pub struct InvalidDescriptionLengthError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + contract_id: String, + description: String, +} + +impl InvalidDescriptionLengthError { + pub fn new(contract_id: String, description: String) -> Self { + Self { + contract_id, + description, + } + } + + pub fn contract_id(&self) -> &str { + &self.contract_id + } + + pub fn description(&self) -> &str { + &self.description + } +} + +impl From for ConsensusError { + fn from(err: InvalidDescriptionLengthError) -> Self { + Self::BasicError(BasicError::InvalidDescriptionLengthError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs index c0610a52f0d..56ea0690eca 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -22,6 +22,7 @@ mod incompatible_re2_pattern_error; mod invalid_compound_index_error; mod invalid_data_contract_id_error; mod invalid_data_contract_version_error; +mod invalid_description_length_error; mod invalid_document_type_name_error; mod invalid_document_type_required_security_level; mod invalid_index_property_type_error; @@ -81,6 +82,7 @@ pub use group_non_unilateral_member_power_has_less_than_required_power_error::*; pub use group_position_does_not_exist_error::*; pub use group_total_power_has_less_than_required_power_error::*; pub use incompatible_document_type_schema_error::*; +pub use invalid_description_length_error::*; pub use invalid_document_type_name_error::*; pub use invalid_keyword_encoding_error::*; pub use invalid_keyword_length_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index aeef3882fcd..e974c30e5bc 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -110,6 +110,7 @@ impl ErrorWithCode for BasicError { Self::DuplicateKeywordsError(_) => 10263, Self::InvalidKeywordLengthError(_) => 10264, Self::InvalidKeywordEncodingError(_) => 10265, + Self::InvalidDescriptionLengthError(_) => 10266, // Group Errors: 10350-10399 Self::GroupPositionDoesNotExistError(_) => 10350, diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index d84943877b5..3e794714efd 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -630,7 +630,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2488810); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2489210); let check_result = platform .check_tx( @@ -1141,7 +1141,7 @@ mod tests { // The processing fees should be twice as much as a fee multiplier of 0, // since a fee multiplier of 100 means 100% more of 1 (gives 2) - assert_eq!(processing_result.aggregated_fees().processing_fee, 4977620); + assert_eq!(processing_result.aggregated_fees().processing_fee, 4978420); let check_result = platform .check_tx( @@ -1613,7 +1613,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2488810); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2489210); platform .drive @@ -1699,7 +1699,7 @@ mod tests { assert_eq!( update_processing_result.aggregated_fees().processing_fee, - 2503570 + 2504030 ); let check_result = platform @@ -2069,7 +2069,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2488810); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2489210); platform .drive diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs index 6eef53767ff..5b5aab870f6 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs @@ -224,8 +224,18 @@ impl Platform { emergency_action_rules: ChangeControlRulesV0::default().into(), main_control_group: None, main_control_group_can_be_modified: Default::default(), + description: Some("Some token description".to_string()), }); + token_configuration.conventions.localizations.insert( + "en".to_string(), + TokenConfigurationLocalization::V0(TokenConfigurationLocalizationV0 { + should_capitalize, + singular_form: "cat".to_string(), + plural_form: "cats".to_string(), + }), + ); + let tokens = [ (0, token_configuration.clone()), (1, token_configuration.clone()), @@ -248,7 +258,8 @@ impl Platform { updated_at_epoch: None, groups, tokens, - keywords: vec!["key1".into(), "key2".into()], + keywords: vec!["cat".into(), "white".into()], + description: Some("Some contract description".to_string()), }); self.drive.apply_contract( diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 422bd9c960b..0b3fb36f414 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -2504,8 +2504,8 @@ mod creation_tests { // Get the document type from the search contract. let doc_type = search_contract - .document_type_for_name("contract") - .expect("expected to find 'contract' in Search contract"); + .document_type_for_name("contractKeywords") + .expect("expected to find 'contractKeywords' in Search contract"); // Verify that the document type has the restrictive creation mode assert_eq!( @@ -2599,7 +2599,7 @@ mod creation_tests { format!( "Document Creation on {}:{} is not allowed because of the document type's creation restriction mode No Creation Allowed", search_contract.id().to_string(Encoding::Base58), - "contract" + "contractKeywords" ), "Mismatch in error message" ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs index 665b162e751..85aa0655e39 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs @@ -5,7 +5,9 @@ use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; -use dpp::consensus::basic::data_contract::{DuplicateKeywordsError, InvalidKeywordLengthError}; +use dpp::consensus::basic::data_contract::{ + DuplicateKeywordsError, InvalidDescriptionLengthError, InvalidKeywordLengthError, +}; use dpp::consensus::basic::data_contract::{ InvalidDataContractIdError, InvalidDataContractVersionError, InvalidTokenBaseSupplyError, NonContiguousContractTokenPositionsError, @@ -226,6 +228,27 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 } } + // Validate the description is between 3 and 100 characters + if let Some(description) = self.data_contract().description() { + if !(description.len() >= 3 && description.len() <= 100) { + let bump_action = StateTransitionAction::BumpIdentityNonceAction( + BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), + ); + + return Ok(ConsensusValidationResult::new_with_data_and_errors( + bump_action, + vec![ConsensusError::BasicError( + BasicError::InvalidDescriptionLengthError( + InvalidDescriptionLengthError::new( + self.data_contract().id().to_string(Encoding::Base58), + description.to_string(), + ), + ), + )], + )); + } + } + Ok(ConsensusValidationResult::default()) } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index 9aa0193e912..8c5a168089a 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2452,7 +2452,12 @@ mod tests { use super::*; use dpp::{ data_contract::conversion::value::v0::DataContractValueConversionMethodsV0, + data_contracts::SystemDataContract, document::DocumentV0Getters, platform_value::string_encoding::Encoding, + system_data_contracts::load_system_data_contract, + }; + use drive::{ + drive::document::query::QueryDocumentsOutcomeV0Methods, query::DriveDocumentQuery, }; #[test] @@ -2956,6 +2961,366 @@ mod tests { assert_eq!(keywords[0], "key1"); assert_eq!(keywords[1], "key2"); assert_eq!(keywords[2], "key3"); + + // Now check the Search Contract has the keyword documents + let search_contract = + load_system_data_contract(SystemDataContract::Search, PlatformVersion::latest()) + .expect("expected to load search contract"); + let document_type = search_contract + .document_type_for_name("contractKeywords") + .expect("expected to get document type"); + + let drive_query = + DriveDocumentQuery::all_items_query(&search_contract, document_type, None); + + let documents_result = platform + .drive + .query_documents(drive_query, None, false, None, None) + .expect("expected to query documents"); + + let documents = documents_result.documents(); + + assert_eq!(documents.len(), 3); + + let mut valid_keywords_for_verification = vec!["key1", "key2", "key3"]; + for document in documents { + let keyword = document + .get("keyword") + .expect("expected to get keyword") + .as_str() + .expect("expected to get string"); + + assert!(valid_keywords_for_verification.contains(&keyword)); + assert_eq!( + document + .get("contractId") + .expect("expected to get data contract id") + .clone() + .into_identifier() + .expect("expected to get identifier") + .to_string(Encoding::Base58), + data_contract_id_str + ); + valid_keywords_for_verification.retain(|&x| x != keyword); + } + } + } + + mod descriptions { + use dpp::{ + data_contract::conversion::value::v0::DataContractValueConversionMethodsV0, + data_contracts::SystemDataContract, document::DocumentV0Getters, + platform_value::string_encoding::Encoding, + system_data_contracts::load_system_data_contract, + }; + use drive::{ + drive::document::query::QueryDocumentsOutcomeV0Methods, query::DriveDocumentQuery, + }; + + use super::*; + + /// Returns a `DataContract` value that already contains at least one keyword + fn base_contract_value_with_keyword(platform_version: &PlatformVersion) -> Value { + let data_contract = json_document_to_contract_with_ids( + // Re‑use the same fixture you already have; it doesn’t need + // to contain a description field – we mutate it below. + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("expected to load contract"); + + let mut contract_value = data_contract + .to_value(PlatformVersion::latest()) + .expect("to_value failed"); + + // Ensure the `keywords` array is not empty so that Drive will attempt + // to create the description documents. + contract_value["keywords"] = Value::Array(vec![Value::Text("key1".to_string())]); + + contract_value + } + + #[test] + fn test_data_contract_creation_fails_with_description_too_short() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // --- mutate the contract --- + let mut contract_value = base_contract_value_with_keyword(platform_version); + contract_value["description"] = Value::Text("hi".to_string()); // < 3 chars + + let data_contract_invalid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract from Value"); + + let transition = DataContractCreateTransition::new_from_data_contract( + data_contract_invalid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expected to create transition"); + + let serialized = transition + .serialize_to_bytes() + .expect("expected to serialize"); + + let tx = platform.drive.grove.start_transaction(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("expected processing"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::InvalidDescriptionLengthError(_)), + _ + )] + ); + } + + #[test] + fn test_data_contract_creation_fails_with_description_too_long() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let mut contract_value = base_contract_value_with_keyword(platform_version); + // 101 chars – valid for the contract (max 10 000) but exceeds the + // 100‑char limit of the autogenerated **shortDescription** document. + let too_long = "x".repeat(101); + contract_value["description"] = Value::Text(too_long); + + let data_contract_invalid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract"); + + let transition = DataContractCreateTransition::new_from_data_contract( + data_contract_invalid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expected to create transition"); + + let serialized = transition + .serialize_to_bytes() + .expect("expected to serialize"); + + let tx = platform.drive.grove.start_transaction(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("expected processing"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError(BasicError::InvalidDescriptionLengthError(_)), + _ + )] + ); + } + + #[test] + fn test_data_contract_creation_succeeds_with_valid_description() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let mut contract_value = base_contract_value_with_keyword(platform_version); + contract_value["description"] = + Value::Text("A perfectly valid description.".to_string()); + + let data_contract_valid = + DataContract::from_value(contract_value, true, platform_version) + .expect("failed to create DataContract"); + + let transition = DataContractCreateTransition::new_from_data_contract( + data_contract_valid, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expected to create transition"); + + let serialized = transition + .serialize_to_bytes() + .expect("expected to serialize"); + + let tx = platform.drive.grove.start_transaction(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("expected processing"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + // Commit so we can query the state afterwards + platform + .drive + .grove + .commit_transaction(tx) + .unwrap() + .expect("expected commit"); + + // ---- Verify description persisted in the contract ---- + let unique_identifiers = transition.unique_identifiers(); + let unique_identifier = unique_identifiers + .first() + .expect("expected at least one unique identifier"); + let data_contract_id_str = unique_identifier + .as_str() + .split('-') + .last() + .expect("split contract id"); + let data_contract_id = Identifier::from_string(data_contract_id_str, Encoding::Base58) + .expect("identifier"); + + let contract = platform + .drive + .fetch_contract(data_contract_id.into(), None, None, None, platform_version) + .value + .expect("expected contract") + .expect("contract exists"); + + let desc = contract + .contract + .description() + .expect("description should exist"); + + assert_eq!(desc, "A perfectly valid description."); + + // Now check the Search Contract has the short and full description documents + let search_contract = + load_system_data_contract(SystemDataContract::Search, PlatformVersion::latest()) + .expect("expected to load search contract"); + let short_description_document_type = search_contract + .document_type_for_name("shortDescription") + .expect("expected to get document type"); + let full_description_document_type = search_contract + .document_type_for_name("fullDescription") + .expect("expected to get document type"); + + let drive_query_short_description = DriveDocumentQuery::all_items_query( + &search_contract, + short_description_document_type, + None, + ); + + let short_description_documents_result = platform + .drive + .query_documents(drive_query_short_description, None, false, None, None) + .expect("expected to query documents"); + + let short_description_documents = short_description_documents_result.documents(); + + assert_eq!(short_description_documents.len(), 1); + let short_description_document = short_description_documents + .first() + .expect("expected to get first document"); + let short_description = short_description_document + .get("description") + .expect("expected to get description") + .as_str() + .expect("expected to get string"); + assert_eq!(short_description, "A perfectly valid description."); + assert_eq!( + short_description_document + .get("contractId") + .expect("expected to get data contract id") + .clone() + .into_identifier() + .expect("expected to get identifier") + .to_string(Encoding::Base58), + data_contract_id_str + ); + + let drive_query_full_description = DriveDocumentQuery::all_items_query( + &search_contract, + full_description_document_type, + None, + ); + let full_description_documents_result = platform + .drive + .query_documents(drive_query_full_description, None, false, None, None) + .expect("expected to query documents"); + + let full_description_documents = full_description_documents_result.documents(); + + assert_eq!(full_description_documents.len(), 1); + let full_description_document = full_description_documents + .first() + .expect("expected to get first document"); + let full_description = full_description_document + .get("description") + .expect("expected to get description") + .as_str() + .expect("expected to get string"); + assert_eq!(full_description, "A perfectly valid description."); + assert_eq!( + full_description_document + .get("contractId") + .expect("expected to get data contract id") + .clone() + .into_identifier() + .expect("expected to get identifier") + .to_string(Encoding::Base58), + data_contract_id_str + ); } } } diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs new file mode 100644 index 00000000000..9931b56defb --- /dev/null +++ b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs @@ -0,0 +1,134 @@ +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::version::PlatformVersion; + +use dpp::prelude::Identifier; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use std::collections::HashMap; + +mod v0; + +impl Drive { + /// Adds contract description to the state. + pub fn add_new_contract_description( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract descriptions are not supported in this version", + ))), + 1 => self.add_new_contract_description_v0( + contract_id, + owner_id, + description, + block_info, + apply, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_new_contract_description".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } + + /// Adds contract description creation operations to drive operations + pub fn add_new_contract_description_add_to_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract descriptions are not supported in this version", + ))), + 1 => self.add_new_contract_description_add_to_operations_v0( + contract_id, + owner_id, + description, + block_info, + apply, + transaction, + drive_operations, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_new_contract_description_add_to_operations".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } + + /// The operations needed to create a description + pub fn add_new_contract_description_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract descriptions are not supported in this version", + ))), + 1 => self.add_new_contract_description_operations_v0( + contract_id, + owner_id, + description, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_new_contract_description_operations".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs new file mode 100644 index 00000000000..855724c9c8b --- /dev/null +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs @@ -0,0 +1,214 @@ +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::object_size_info::DocumentInfo::DocumentOwnedInfo; +use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::document::{Document, DocumentV0}; +use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use platform_version::version::PlatformVersion; +use std::collections::{BTreeMap, HashMap}; + +impl Drive { + /// Adds a contract description by inserting a new description subtree structure to the `Identities` subtree. + pub(super) fn add_new_contract_description_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let mut drive_operations: Vec = vec![]; + self.add_new_contract_description_add_to_operations_v0( + contract_id, + owner_id, + description, + block_info, + apply, + transaction, + &mut drive_operations, + platform_version, + )?; + let fees = Drive::calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + self.config.epochs_per_era, + platform_version, + None, + )?; + Ok(fees) + } + + /// Adds contract description creation operations to drive operations + pub(super) fn add_new_contract_description_add_to_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let mut estimated_costs_only_with_layer_info = if apply { + None::> + } else { + Some(HashMap::new()) + }; + + let batch_operations = self.add_new_contract_description_operations( + contract_id, + owner_id, + description, + block_info, + &mut estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + self.apply_batch_low_level_drive_operations( + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + drive_operations, + &platform_version.drive, + ) + } + + /// The operations needed to create a description + pub(super) fn add_new_contract_description_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut operations: Vec = vec![]; + + let contract = self.cache.system_data_contracts.load_search(); + + let short_description_document_type = + contract.document_type_for_name("shortDescription")?; + let full_description_document_type = contract.document_type_for_name("fullDescription")?; + + let short_description_document = self.build_contract_description_document_owned_v0( + contract_id, + owner_id, + description, + false, + block_info, + )?; + let full_description_document = self.build_contract_description_document_owned_v0( + contract_id, + owner_id, + description, + true, + block_info, + )?; + + let short_description_ops = self.add_document_for_contract_operations( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentOwnedInfo((short_description_document, None)), + owner_id: Some(owner_id.to_buffer()), + }, + contract: &contract, + document_type: short_description_document_type, + }, + true, + block_info, + &mut None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + let full_description_ops = self.add_document_for_contract_operations( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentOwnedInfo((full_description_document, None)), + owner_id: Some(owner_id.to_buffer()), + }, + contract: &contract, + document_type: full_description_document_type, + }, + true, + block_info, + &mut None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + operations.extend(short_description_ops); + operations.extend(full_description_ops); + + Ok(operations) + } + + pub(super) fn build_contract_description_document_owned_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + full_description: bool, + block_info: &BlockInfo, + ) -> Result { + let owner_nonce = + match self.fetch_identity_nonce(owner_id.into(), true, None, PlatformVersion::latest()) + { + Ok(maybe_nonce) => maybe_nonce.unwrap_or(1), + Err(e) => return Err(e), + }; + + let document_type_name = if full_description { + "fullDescription".to_string() + } else { + "shortDescription".to_string() + }; + + let document_id = Document::generate_document_id_v0( + &contract_id, + &owner_id, + &document_type_name, + &owner_nonce.to_be_bytes(), + ); + + let properties = BTreeMap::from([ + ("contractId".to_string(), contract_id.into()), + ("description".to_string(), description.into()), + ]); + + let document: Document = DocumentV0 { + id: document_id, + owner_id, + properties, + revision: None, + created_at: Some(block_info.time_ms), + updated_at: None, + transferred_at: None, + created_at_block_height: Some(block_info.height), + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + + Ok(document) + } +} diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 57c16d09351..a7daf634932 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -98,7 +98,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result, Error> { let contract = self.cache.system_data_contracts.load_search(); - let document_type = contract.document_type_for_name("contract")?; + let document_type = contract.document_type_for_name("contractKeywords")?; let mut operations: Vec = vec![]; @@ -145,7 +145,7 @@ impl Drive { let document_id = Document::generate_document_id_v0( &contract_id, &owner_id, - "contract", + "contractKeywords", keyword_index.to_be_bytes().as_slice(), ); 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 59a30e76062..1ed48c28095 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 @@ -319,6 +319,18 @@ impl Drive { )?); } + if let Some(description) = contract.description() { + batch_operations.extend(self.add_new_contract_description_operations( + contract.id(), + contract.owner_id(), + description, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + Ok(batch_operations) } } diff --git a/packages/rs-drive/src/drive/contract/insert/mod.rs b/packages/rs-drive/src/drive/contract/insert/mod.rs index ea57897be76..5822e243119 100644 --- a/packages/rs-drive/src/drive/contract/insert/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/mod.rs @@ -1,4 +1,6 @@ mod add_contract_to_storage; #[allow(clippy::too_many_arguments)] +mod add_description; +#[allow(clippy::too_many_arguments)] mod add_new_keywords; mod insert_contract; diff --git a/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs index cd66e430e60..b909d49d093 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_action_infos/v0/mod.rs @@ -154,6 +154,7 @@ mod tests { ), ]), keywords: Vec::new(), + description: None, }); drive @@ -382,6 +383,7 @@ mod tests { ), ]), keywords: Vec::new(), + description: None, }); drive diff --git a/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs index 5527662be18..c8602ac7dd4 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_action_signers/v0/mod.rs @@ -149,6 +149,7 @@ mod tests { ), ]), keywords: Vec::new(), + description: None, }); drive @@ -318,6 +319,7 @@ mod tests { )]), tokens: BTreeMap::new(), keywords: Vec::new(), + description: None, }); drive @@ -412,6 +414,7 @@ mod tests { )]), tokens: BTreeMap::new(), keywords: Vec::new(), + description: None, }); drive diff --git a/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs index 93772e6c4b7..bab7fbe6036 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_group_info/v0/mod.rs @@ -107,6 +107,7 @@ mod tests { )]), tokens: Default::default(), keywords: Vec::new(), + description: None, }); let contract_id = contract.id(); @@ -177,6 +178,7 @@ mod tests { groups: Default::default(), tokens: Default::default(), keywords: Vec::new(), + description: None, }); let contract_id = contract.id(); diff --git a/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs b/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs index 3b53aae4b05..68b20c7b812 100644 --- a/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/group/prove/prove_group_infos/v0/mod.rs @@ -135,6 +135,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let contract_id = contract.id(); @@ -280,6 +281,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let contract_id = contract.id(); diff --git a/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs index 5138aa8845d..b2a7667a713 100644 --- a/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/balance/prove_identities_token_balances/v0/mod.rs @@ -98,6 +98,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -199,6 +200,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -291,6 +293,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive diff --git a/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs index d0069901b8e..354251fe180 100644 --- a/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/balance/prove_identity_token_balances/v0/mod.rs @@ -103,6 +103,7 @@ mod tests { ), ]), keywords: Vec::new(), + description: None, }); let token_id_1 = contract.token_id(0).expect("expected token at position 0"); @@ -264,6 +265,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); @@ -352,6 +354,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs b/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs index 43e1886b2f2..edc445f0df3 100644 --- a/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/info/prove_identities_token_infos/v0/mod.rs @@ -98,6 +98,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -199,6 +200,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive @@ -289,6 +291,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); drive diff --git a/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs b/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs index 0a4ad4e064f..18e1a3e920f 100644 --- a/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/info/prove_identity_token_infos/v0/mod.rs @@ -106,6 +106,7 @@ mod tests { ), ]), keywords: Vec::new(), + description: None, }); let token_id_1 = contract.token_id(0).expect("expected token at position 0"); @@ -254,6 +255,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs b/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs index b4cbfd2a850..c7f6d5afdc8 100644 --- a/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/status/prove_token_statuses/v0/mod.rs @@ -95,6 +95,7 @@ mod tests { ), ]), keywords: Vec::new(), + description: None, }); let token_id_1 = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs index 83061d04d78..5d1858139bd 100644 --- a/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/prove_token_total_supply_and_aggregated_identity_balances/v0/mod.rs @@ -89,6 +89,7 @@ mod tests { TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); @@ -215,6 +216,7 @@ mod tests { ), )]), keywords: Vec::new(), + description: None, }); let token_id = contract.token_id(0).expect("expected token at position 0"); diff --git a/packages/rs-drive/tests/deterministic_root_hash.rs b/packages/rs-drive/tests/deterministic_root_hash.rs index 35b3d7e7b57..760ed03f3c9 100644 --- a/packages/rs-drive/tests/deterministic_root_hash.rs +++ b/packages/rs-drive/tests/deterministic_root_hash.rs @@ -302,7 +302,7 @@ mod tests { // We expect a different app hash because data contract is not serialized the same way let expected_app_hash = match platform_version.protocol_version { 0..=8 => "1b80f4a9f00597b3f1ddca904b3cee67576868adcdd802c0a3f91e14209bb402", - _ => "aa29a0d3dcdcb1dc1b446830931762e0b9c2e2d97d6f426f8dbe4e0eda8e6130", + _ => "76e3af331ff60aea3006671d048ce16871369da4ec562bdc9966837bb49ee92c", }; assert_eq!( diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index 8353aeecb0b..ac6c5d96250 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -2509,8 +2509,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 163, 83, 211, 88, 187, 57, 197, 189, 189, 39, 40, 150, 102, 186, 188, 111, 200, 230, - 134, 21, 72, 136, 135, 92, 102, 206, 72, 43, 127, 87, 26, 82, + 53, 9, 163, 92, 116, 134, 17, 186, 21, 68, 156, 162, 47, 181, 214, 162, 253, 4, 246, 8, + 41, 187, 151, 152, 216, 164, 206, 110, 230, 176, 124, 225, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -3823,8 +3823,8 @@ mod tests { assert_eq!( root_hash.as_slice(), vec![ - 243, 205, 195, 230, 73, 41, 217, 87, 42, 205, 142, 71, 144, 29, 239, 97, 174, 131, - 226, 122, 190, 78, 58, 99, 94, 106, 233, 185, 194, 198, 246, 205 + 144, 154, 147, 246, 236, 57, 41, 67, 21, 26, 212, 158, 68, 159, 206, 26, 158, 50, + 252, 62, 143, 176, 149, 50, 19, 226, 239, 65, 112, 243, 225, 64 ], ); } @@ -3974,8 +3974,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 163, 83, 211, 88, 187, 57, 197, 189, 189, 39, 40, 150, 102, 186, 188, 111, 200, 230, - 134, 21, 72, 136, 135, 92, 102, 206, 72, 43, 127, 87, 26, 82, + 53, 9, 163, 92, 116, 134, 17, 186, 21, 68, 156, 162, 47, 181, 214, 162, 253, 4, 246, 8, + 41, 187, 151, 152, 216, 164, 206, 110, 230, 176, 124, 225, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -4426,8 +4426,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 138, 110, 99, 80, 216, 232, 45, 246, 159, 207, 139, 253, 210, 64, 32, 114, 102, 107, - 21, 120, 163, 19, 189, 99, 109, 95, 56, 217, 134, 206, 160, 215, + 75, 38, 164, 96, 117, 46, 13, 23, 183, 41, 83, 163, 112, 55, 172, 37, 186, 36, 223, 39, + 106, 201, 46, 222, 167, 79, 236, 122, 12, 210, 29, 123, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -4549,8 +4549,8 @@ mod tests { // Make sure the state is deterministic let expected_app_hash = vec![ - 163, 83, 211, 88, 187, 57, 197, 189, 189, 39, 40, 150, 102, 186, 188, 111, 200, 230, - 134, 21, 72, 136, 135, 92, 102, 206, 72, 43, 127, 87, 26, 82, + 53, 9, 163, 92, 116, 134, 17, 186, 21, 68, 156, 162, 47, 181, 214, 162, 253, 4, 246, 8, + 41, 187, 151, 152, 216, 164, 206, 110, 230, 176, 124, 225, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5347,8 +5347,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, - 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, + 235, 23, 161, 209, 153, 68, 160, 57, 151, 170, 19, 99, 64, 48, 5, 114, 233, 154, 77, + 65, 104, 102, 128, 181, 159, 124, 54, 108, 229, 88, 185, 134, ]; assert_eq!(root_hash.as_slice(), expected_app_hash,); @@ -5443,8 +5443,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, - 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, + 235, 23, 161, 209, 153, 68, 160, 57, 151, 170, 19, 99, 64, 48, 5, 114, 233, 154, 77, + 65, 104, 102, 128, 181, 159, 124, 54, 108, 229, 88, 185, 134, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5539,8 +5539,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, - 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, + 235, 23, 161, 209, 153, 68, 160, 57, 151, 170, 19, 99, 64, 48, 5, 114, 233, 154, 77, + 65, 104, 102, 128, 181, 159, 124, 54, 108, 229, 88, 185, 134, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5635,8 +5635,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 252, 254, 89, 190, 119, 227, 29, 62, 78, 216, 77, 35, 178, 115, 23, 145, 237, 234, 159, - 60, 9, 83, 51, 174, 88, 255, 12, 116, 106, 202, 232, 29, + 235, 23, 161, 209, 153, 68, 160, 57, 151, 170, 19, 99, 64, 48, 5, 114, 233, 154, 77, + 65, 104, 102, 128, 181, 159, 124, 54, 108, 229, 88, 185, 134, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -5831,8 +5831,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 74, 31, 85, 116, 81, 139, 178, 90, 11, 123, 172, 93, 187, 25, 125, 35, 201, 210, - 64, 40, 43, 40, 68, 230, 228, 168, 46, 63, 219, 98, 240, + 233, 90, 110, 8, 43, 137, 139, 242, 8, 152, 175, 246, 177, 73, 49, 137, 61, 142, 2, 49, + 158, 134, 13, 222, 60, 223, 139, 41, 66, 131, 135, 38, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6038,8 +6038,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 74, 31, 85, 116, 81, 139, 178, 90, 11, 123, 172, 93, 187, 25, 125, 35, 201, 210, - 64, 40, 43, 40, 68, 230, 228, 168, 46, 63, 219, 98, 240, + 233, 90, 110, 8, 43, 137, 139, 242, 8, 152, 175, 246, 177, 73, 49, 137, 61, 142, 2, 49, + 158, 134, 13, 222, 60, 223, 139, 41, 66, 131, 135, 38, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6248,8 +6248,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 89, 74, 31, 85, 116, 81, 139, 178, 90, 11, 123, 172, 93, 187, 25, 125, 35, 201, 210, - 64, 40, 43, 40, 68, 230, 228, 168, 46, 63, 219, 98, 240, + 233, 90, 110, 8, 43, 137, 139, 242, 8, 152, 175, 246, 177, 73, 49, 137, 61, 142, 2, 49, + 158, 134, 13, 222, 60, 223, 139, 41, 66, 131, 135, 38, ]; assert_eq!(root_hash.as_slice(), expected_app_hash,); @@ -6462,8 +6462,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 244, 130, 169, 10, 90, 218, 48, 147, 73, 95, 89, 174, 234, 151, 228, 21, 155, 188, 165, - 185, 121, 77, 221, 236, 82, 228, 82, 133, 102, 214, 251, 40, + 112, 166, 177, 100, 209, 55, 7, 42, 111, 43, 77, 15, 40, 149, 26, 219, 121, 244, 83, 5, + 102, 253, 66, 122, 99, 217, 33, 173, 135, 17, 174, 115, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6542,8 +6542,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 244, 130, 169, 10, 90, 218, 48, 147, 73, 95, 89, 174, 234, 151, 228, 21, 155, 188, 165, - 185, 121, 77, 221, 236, 82, 228, 82, 133, 102, 214, 251, 40, + 112, 166, 177, 100, 209, 55, 7, 42, 111, 43, 77, 15, 40, 149, 26, 219, 121, 244, 83, 5, + 102, 253, 66, 122, 99, 217, 33, 173, 135, 17, 174, 115, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); @@ -6643,8 +6643,8 @@ mod tests { .expect("there is always a root hash"); let expected_app_hash = vec![ - 244, 130, 169, 10, 90, 218, 48, 147, 73, 95, 89, 174, 234, 151, 228, 21, 155, 188, 165, - 185, 121, 77, 221, 236, 82, 228, 82, 133, 102, 214, 251, 40, + 112, 166, 177, 100, 209, 55, 7, 42, 111, 43, 77, 15, 40, 149, 26, 219, 121, 244, 83, 5, + 102, 253, 66, 122, 99, 217, 33, 173, 135, 17, 174, 115, ]; assert_eq!(root_hash.as_slice(), expected_app_hash); diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index cb72796f888..3229c6fbbcd 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -1666,8 +1666,8 @@ fn test_query_historical_latest_platform_version() { assert_eq!( root_hash.as_slice(), vec![ - 198, 240, 42, 199, 134, 177, 186, 144, 191, 122, 14, 217, 209, 140, 131, 144, 63, 232, - 141, 193, 177, 136, 200, 150, 42, 110, 151, 216, 85, 161, 78, 44 + 161, 240, 182, 38, 13, 26, 246, 165, 76, 67, 252, 39, 203, 128, 225, 233, 70, 76, 30, + 228, 64, 40, 59, 240, 240, 135, 215, 135, 146, 2, 128, 65 ] ); @@ -3032,8 +3032,8 @@ fn test_query_historical_latest_platform_version() { assert_eq!( root_hash.as_slice(), vec![ - 244, 221, 68, 246, 214, 152, 18, 222, 186, 119, 187, 173, 119, 184, 146, 5, 27, 145, - 125, 63, 233, 17, 138, 99, 99, 177, 83, 145, 4, 8, 124, 155 + 82, 200, 76, 76, 113, 4, 94, 39, 105, 206, 63, 185, 209, 222, 13, 161, 194, 209, 156, + 251, 133, 192, 38, 65, 93, 196, 214, 198, 52, 196, 37, 208 ] ); } diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json new file mode 100644 index 0000000000000000000000000000000000000000..9adca368205e1fa61ebc0a52a7b0daff6522a8f9 GIT binary patch literal 60302 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®r`dVB7&!{{omO+6FXrjl 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 diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 78b6e2613b4d273230b522ffce68d8579f539098..d7eb96c1aa9e2b7f863e7a24a961d64eade237b4 100644 GIT binary patch delta 2888 zcmYjTZEO_R71hivv)I&N%%=4O|L}vsD#^AAvYRO`Ak5lqiXkmf*HP)e=PuQvO6#7$pVAjgp@C-q_^N zYIkSe{W$lWbKmdIlzeceWO&51g_8`NkY>)Wp}Xcz!>3n7E&bSfygYCcOPyqklW294 ze)O44;!paUxrEwc@5OO28RG1pMfy<@76|nay zipY%{2@JEX$$=IfX71!lMZ^F)GmTjN|q6>scXX_lN8yfpoWSchNHe z?Z*K*fmA!nKfe#-oBcj!1pq_Zw%VhA&kXs|PCOgPMMx6ECjY_{TFS^IAVir%H{>jEtj6E3@KCY zQA5*rI3tPtz!+c}A2I`~n5y#fN6Vsg4|&KEbuZ{ZgAVspku27i3b56fGsTEM=wSRd zeSBXNzqb)IIqU&SnO(mgV;TqUB8d{JpR_gQBv^IGf$4{Q?R5jBRWu0b+)crmwV1)k z_ymm{&f4I>$Si1K_7pB&23E*dc>2qx3uSq7o;38a9_QazTM4RtCgAL5*h2n$QhRs< z3EMVCB55ysL=||l22k!Zo3x}4T^Dq*PE3$qWwq%M??F2Ef}jE6alRc2?Y(X$=>0m6 z1h`%~&$*|_D2GQsOZc>=Dx?|h(5v*5Y}RZb?=emGHxghCv^Vgg6cDspyb%ony69zT zK6Ee{aB$50E)6e=(dV5If1ed7dCkr1J|F9|e17vIK>Kvg)RB*`&~tJ^Pj~UxKxo29 z*WejF&@Vgzok5Ccvz?wTwXf$qI#@3yt(28%hX33#9e770JPm0>H3A;>Q0WIbur%Ld z(-1(&?uVLg!!{s3Ro)#?ZkMC#;Iap#s35VjKC6ir_M4Gg{i{z8g2Cz#WcPSXMEbhn zfb|oDVsQsYu1IN0KDC$WuueBv7GH*cGpAx))rMfw)=q*IN%PwZu}jmGtdtx)Uf2e< z<0GV>E{vFXyk^@33dd|P)unu+3=^Yt|2O$h`_N*xGnCECF=x7V(AesU=k=1TKN8(P z5#7e`MYnnEx`Ht>M7X=AGQWEeypDE*ue5kAr;*!Riy3Zcrsth{X`TE~ujO!0rS4Pi z0KqBWYUa#NQ#o=gr{6Z3xOxbJl{-Tj3BU6#BcRtRe5k_ah8~<=SgP=*6DtJQZ9>24 z?J+v?M<>F>5E7;z%jVts^Ha>E6iMIY9kz(mKUo^dl%%APv<@u(gFw zXvyW&Ei=j4-KNU}7mWlzyh(c$-I^1sVP%>_t>ubJ0WEeEZ;$3Ez;ATlDvrvXhixgO zb%IG~M5KTP>Z<+s;pi=v&7s`MM$>G=F*KX!6oQ4J6D;Pfw+Sr2M% z<-1&dsSR{#m1bG}7wt1rfxSZsE|dZd`|BRouJ6DXvBc+ryWnN|iqSA>ZIc^9-owT~wR^rS zxg+;yoL{|bhFl0>l6t|d5~>3%7c{=P=sroVt90SjkQS8sRQl;xR-L?uoT!oap%~Bd z!Q=@m{>NfHxlD`T3IVdi6Ftss!6k4{d4jiJfrMAIBxrY?OT(WivD^HIb;=)Yx>4!# zwhmOQZgT1E`sN7!0F4;vCRa>gLQ20WpIrKSugd$}66pXXP;a(#>OFCs*lL~pKjRRCUciFb%r+*2VpVk-Rl;_Q5G05|h(u8(jHN0mZ$!fL%`ADvV7bAvms8yR}8+~?%Imcu{xt$_Ad z<7taIpB0&#DL>7od*-_I=r~1(GdAt$@b%~9Hjl>w%c0k*UA}n5jPbcUW}3fDTOK9H zJM?@_t(ncx3un{Rds%VSlZMY1<$OilnP5P6!R2V*~7W-&Eej&ykPnrQW2M%>T z;8EXdhjw-#K&{VvCtD$p++*oFxV{cgZ$4<{sP8k6rgx`HmGXzT4LK6y+ba;eFJ~dI zypiLcg;s{Tklcw)h$p=mON2DD(dUG+LONERp$#=@?t8|tsqkBmKY0jm)kZn$P=8B6 zf1Mc8$yq+Ve<{P)lo^%F?>>x-3N?y*KQL=KpR>@XE2hI67g;IYVa}aILTles@|2eP zY#w{va7*`cz701>rF+{IC+jW61M92>)S+A&m>A>#0usK8HuFz!86iJbhY0;kaO#sr z{H|kFjGD%|8h<*|kV5Nn{Ixp#XAH0j4xDcVg_6}C@7`r(c|TADXi@U>~xvXDBqdo+G-)V!PbE80Cxf9E4@Qgs0E zJ98oZ%>|?60o0-yw=?ucgO5Bzs@kFWsa-}!Y6$t|K{NXGvj`^;;r^vI=U+2CIy36< zfoITSVJ2m_G=2VRwUy!KBOoo1wfW2pz&qJs?{-Kj|NrUFKjxvp+eEfpsy)@;u{`) za4F<}G@?I3<@!$ac}BhJ|F@Cmy*WIzS4TM^gZVV0NkG<-Ya)P>_W~0TjC(Hu%JxUi zkP|M-ygdZcM`3JGMZ(!MdCr!SL_>aMr)G>z-BW!H6?EZ)^BW?zm0dPa*K{ea6*PY; zuDD^XDH_!1@jJkk>Xs||{(aGBa)-~oH&OME=74l!9$lf8l5%-N19}jz2%QpieCA_&PzYx>9diJgY(CrCaqF`&E(wedjYl#kaO?O595 zfSYiI=l^V^D7k$js5YveXLSN{yH=qhg2U2r!QOV+6F5;e5h7@OG={QL8a|a{6J8*DRIH0)03S37IgmQalT-z zJ00>PlG@l-4}JKP!|mq`SI8r;QdBq#C)tnkBC}SMUoYQ7&9}S%014y*Idn9c^PE!a zQaJv!Jm|af>o=6XAI-0?v81^veA{UX>8UUZp&YW0kMtQe1|;WmVXhH-@fWTp5&#Ie zkIl_I@`f@0_~Exq*VsS3`|0W3#_{Rh=C3a5J9bY?i`e+`IxUG9J&sv30HaKNr07&b z!0m8R9wd-UaU4N#~x{O}5ods?iVcx03w_k0Y0 zC`uJwIUFfSx2u0jjyJ&uxC1V%oe_)?Q=z|H7Eck1I=rV9;otfK0ct$7+vne9tyhbu zBj>OeLOoy|v=LBEr4|9-Sc44I0?1ZaNqdsQK!;|p%D{g$(vm)pT`|k}?WHD=7=p)c z!nE(5YZtA+hB-yZ%Ip)jD=gA%i9AAMyf8p|iD5kvc%%*12yUcAlxb?-X^Uz2k)?Mu z$>1xF<d9|ug_95aDsk@VUo4y*)IhX*sF3w8$My>8!YZLBof4k_C@S&nK0m)3+U1TO_dtfdb9tgP5U}fp0aRCqiz;q;3WT}0Z zKo<I)`(1(NC8nh=yTTXP>invSpZt>S>o#}tq zldul;WTSSCC5kiiiB~+4NioMQ+f2PTl*y*0Y28(>`z(tS_LWsoQba&c{1}ujZfDq! zWbbkK&JyG(nB7T-{GDx3olx=GB26H4O-Aau^PyOqcD#TuybgV8@9TQ7sN+```*dhh zNU1O^={RB?zl9U%qgZeqcP+)7s#~t}Q|;6q%!{vJy>tV!qPR~*D2r@wI2g#{z3x=SpDQ@D?5WYPo>d#z*vi9F8Lj+Y Hr?v0@EMyjZ diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json new file mode 100644 index 00000000000..e18b2a7deac --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json @@ -0,0 +1 @@ +b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json deleted file mode 100644 index 5992d970292..00000000000 --- a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json +++ /dev/null @@ -1 +0,0 @@ -b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_2fd2f7aebe5686d4e4179323b49e8920dea81c3f44b9549c238dcb82cccc9923.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_2fd2f7aebe5686d4e4179323b49e8920dea81c3f44b9549c238dcb82cccc9923.json new file mode 100644 index 0000000000000000000000000000000000000000..6ee022e9e57cfb4f41155da10c34fee246cd0ef1 GIT binary patch literal 60287 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 literal 0 HcmV?d00001 diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_c4bb9b2e03829c0926d347692bc4eacbb5ffa75f6cb27d3ee8a17b185852f102.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_c4bb9b2e03829c0926d347692bc4eacbb5ffa75f6cb27d3ee8a17b185852f102.json deleted file mode 100644 index 4890cb0a83921eb49ba1b3b268934309ff20fee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60358 zcmeI4TXP#%c7^loU(tn9m695g0eF!_=Si~cv0`h+v7AXNlA>w?O%fK+4FjMg+N1wI zYn{^ox&e^ruVtlXQglHUh(4FS*IN5>4ru@OMUr#|={$YYFY@^`?aw=3Cco)JeSGh{ zn2yu=n|IlCHY{>I==3^!@!4?TAOHAYKfZYUmv5f`{NEoQeLMM&Z_+>g`}1F({N>^E zCl}AZJ3gD9{O8v%W>1b^9QD5LFJ@|=^WnvEm)rNz(|(#i$)0ATY@T_~^K>-Jq7iyH z&C)@UkFGZ!yv?%7?AzgNUQ9P14vPNOILqg=?=-3$^i}Ep)9gIG8X1N9PRlvZujc95 zDBB!ApI)sDTMqxKV*ZXf)9jb4;WV2)8_2fd{QB#>KfRvJ1^tuaDj#Hn?=t(6UyVi; z0P1s|X1nLihQDTmXZbw4$fiGCPqLX7wef-3k0rq?(tG76#rr&)J`23}cKoy8de*

dRilAQzca{^i;ymXXn|}#A$Nr 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 delta 3065 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 diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9267cfc8e7a6f302a2a7d179bc9337e03233ad6fd5c394dd4e6033f39e9447e8.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_9267cfc8e7a6f302a2a7d179bc9337e03233ad6fd5c394dd4e6033f39e9447e8.json deleted file mode 100644 index f83ccb50780049b144ba750801f5100f2a707859..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60442 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 K9-r)ScK#1P{zvNo delta 3027 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 literal 29015 zcmeI5L2esI5Jj`rDGaT-;7Fuw`Vu*S;a#*a0>puncq8cU{;#V=4ISC+*O9UkK-;9) zJyrGV*RPtPJiNPj^XBsF?U%nkeg5O}{hPbITV8!=@9^$+^ZNApap;(S zd;s_I&o7_9-Uj%;zx;FC-n`G>_ZRmUzg*m1{`&jn`wz?2^=8>_uCLl-w^^2VdA;Oc zp6~NKe->V6(QdPU$GX!^>#e)I|Fc!cwcA5CbF(?T&C_lBXKAknj_`P#xQV;Cxg`|b zzIk+lV_k2`tsQG0LaigL|K4p5ajL~y2R-cDPjblSB0$7V3faa zWXy84|FMUJj~yT&U>E{nR;+xgfKI7+iX`ym{qvRe-9e~`V>)_a!_=ONb+W!Qap3ij zYh`5zG869D;^O~V@~@BoVvECTv_T%9T`6G|@(pD)zNH+qTdIzQmA5{S1a9E!2urM# z38GG2M52bRu-HVw;wFUSCh#iMk}lbdPXvO}N7siPBal$nz(qO?+cDAl&$w3!Ay&rM z_b8-Nk@Sfq{-iamWUVGH+N?1_Ad2eAwaQ(@&8EBQq0V@ASss>ehPoOqDeU76q$t$E z4OaucDhEX&$Df)OhjWxkPdUS4gA4>vus5l9Ay0%bj1Qh9UQ@z^9CU+Xp7LtWL`gRSLl3RY!2i%mMRcxLuX0V-Y@{fB{OP=p@25MsAvmjM=3lWt{2 ziY>W_SBgPq3D>3BhOx;vWWDlme{bdAFiuVM3-RNGsD#X|#vRcrs$)!iuR`sGI7rd5m5u zwj}9_ka5ZIgea1C>yjy0G{Nu?HIQQ%QOGMfqb zGqSQ}!i06wJenm(jA~|28T-4WsBiSw_>;W_8~f; zS9NAQgDs_DfSs8k7K}(D6fM`PGm6FGUQjg+ z1%FzFj$2_%a$&KRYK&JBTZ%}=PMecbL-^K8wpgkg698qaFa6hOCQ)aLOnR|voLXp3 zGGb!Kg#4Vk2(QGX0#Qk1i-l{vMMkM4Z;9Gw+_ZqiOYW3J$E7HVvCP}|jPE*N#I+ubX&;@PFw5Ane9Fix(@khxi z1d#HWEj;YBnZO5g-F^eS9J5wPqM5j;VyQ5_Dh*ZOiHRMrOcXtd%B7f4!jkpUD|ls1 z7?g-Qz#5?FiALuMIS&P_njHLy)$3yTG=cSDxbiB)g9^EZnPHa-RhNhm!w3#0l54Z2 zfDN6VwP(?s_(ShH-iWl?7?zgDJ1?qcWowJz(iv1%Q@a*F(+uN`62;1o=$sR^oV}o@P>md+ zmKF0LEKOLrdh8~TeT$97il;sGFg!3A_qjO;Heab{R(5F3fs^trn>0zdC*rXVeLNvPGhbi3u^6j-mgi z{V{i`TxW5juz?H@6>vix++MqCQs&f8N*UY>LzKYE0h{Azi(z0_8?&VXap}nMRp~{| zRJyATnJr+Iq+8jPpBNmiJnMC@lui4bhEHX-xzM%x;*?R?@(nC}ugJ+4;54}QOdP+#$8WRvJTvS70G||$1VoSVIog*ex6s^-Zjgv*& zNuv6t6|4zhZSGP{3fQ@RW>D&+l`U{o((2w;Rp7=e=-PU-IL!!Fasoqk%$AZJ6?=!* z@Pybi8d}E;ym-~v{;VzV$G@(?*Oy)K9bWmCto27g%NkNS)J H^YQ*0RQ_wV diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json new file mode 100644 index 00000000000..e18b2a7deac --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json @@ -0,0 +1 @@ +b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json deleted file mode 100644 index 5992d970292..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json +++ /dev/null @@ -1 +0,0 @@ -b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_96c4914304501c97094650f1da1086bcaf743e2fa8f6b8b143deb29b5265e971.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_96c4914304501c97094650f1da1086bcaf743e2fa8f6b8b143deb29b5265e971.json deleted file mode 100644 index af500c51b1e5c23affc04929ff8c9afd5940c2ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55048 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 diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_f531f69255dae40cef880290c177ff33d2448d30f2527374349b9f507b44c5c1.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_f531f69255dae40cef880290c177ff33d2448d30f2527374349b9f507b44c5c1.json new file mode 100644 index 0000000000000000000000000000000000000000..aa4d00e5ac00342bbe43f436e0d4e3b4b13c0bb0 GIT binary patch literal 55034 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�ZyUEMCWK`rkx8JeL&{*neLJqCL`kn*6e#G64I|+# z5h0-45vdU|%u|%gP>@U&Y8Vv^Sm-RP#H2PdslrHj;@GxORyjgSihDo;A5~)KlwK&d zEvSxuJ<$5Zo(KfS4qj}?B(#ME0f`%3UyF-@M046C1?7gutFRNsMlVoOc#1Y6zIzJQ z5FvFqe8|C(#s}H&cp_tz(W<=YvL~<_ zv7$@_B2D%pzL1QIe$*FDA<|(6LPptrw1s#s9UxO2E8&Qwqcx7i{Zju)ZS@q$$rj3B zP^dV=a#?QCg7!#qWfj5QUPA=UdBR4+p%*FyQQL|3I!EC6=64>(PD(A&yXnI9A-G=J44bk`%TF-efyOP^G;EVXUoEwi2v8Sd5|xjTh~0=HG4n`;C9C>FF9wKhG#s;nx~@(+GC`*7Ha+^+zk6o$2kv_#=>S+jP?we+2rx z--C>Ya*sk7q^*$?@fIvXNYvAYNqSI~l_P{D+QP5K-I%#fGSKOyq(wy3l#qnXDxzx+ zthPXbjgAoCy^HdkbgnM02oB=4xkP}lB}&tVnHot>>8+>|x*9dwwa|VdnuJh*sF@h> z*Uy*{tauA<#63D*+(S{KKNnJ@_FKCa1Wvle$uv9Z zWlqL-GJ%r`os3Y6X?=hX^jbEpu>TO%e?zL9kr-ZB@sdF;pStvms*sXT`G-8qqsb3! z{^u3b;ljswB3I>6F>TZQIZi1Rp%tGtQrBfyE!8IkHwb-#K5G-4Y_lTV*lD>q_f|(h zXEGigxQUxTv8i{ROWQAcG*D;rU)JML^6n@f8Z{lY(sZxoalF^C`LPX_LxnGWE}E7o zc@ge!v0R#HuAsHA`aHP9PzUIIRmjC=BcNQpO)Z|_B^{Qa$?bv%V`hWCYVRt`;kawL zoJ$yX>7awuQk*=Qf?Gd=nuY^If8m0LAD<(hzh-Ddd|-x%Sc5N8jxBkv^% zpC4Uig>R%v~B%Y)75OBUDbhG85{H1ibNKQ{0C4V5{YGd6QMai+hZalM9U$-*-1a zD|d(dqW}RN=+MO|L<$!0o7F~|$}b8Q^8rvI>8pz_H~C!pJ+dv&$_Wci+q)x_f$%nbjl8waJR%3xWs zHVrCBA`2yyRv3`DxjuY!jT1pAw&X@5 zjrP7F{ZsyK8lLQl8N;K!+w2i|Y|H>sE+3r>_Qj8Yhl6?Zmh2!<&l^!5ETEs9y$Z9F zKM(l^^n2dO@@UQqN0NUwZ&XYZ${!Is&1a0#t_LZ%8zi~{n}WUml#<;Zm#e`LNpmVZ zm8GF8Md^xM`<@waVG&m4%9O`%MZp7(e`4Gm$z3ozEES&WXp`GL-g}QxL;^WZ>(DWANry<9D39Ze|`I*!h!zoyN$(PV?KpQC&pdps-S^O^1r0=l1{&_%4f$ zTJOqn#B!Sp9R|!iLSNK6bU5EkU-_s}b%Gm<(RFV7+N~B8L^g%6QY4GpK3=s zeGMUm?ZaL}h4~}jLnDkYl4d#{<%6g6Frqpb)TjT*$MCWOZKzxO6a8#niVOXSRsKC+ z6_7hyx~JjG07L%fazu{#MUD_kIWBz}hTPf=GaH&=)1_I80VrxgNGeRZo^&+jf4E=J zp2gbiq{qwNCLfEUkIG;pvc0H|0K>q5qhzqPRnJEJz`eM!!pBf?0&Q_mAg7>SDMSQ2 z7Ax|oAtxY=MErO=dRc5eE|87kvo=ZPDIlgf&7=Ruypc_Xv{VRvYL*AyD5^^0su>O= z6PHdQMtN*i3?{H+8F;0sto)K6lXsA%`b9`v5}h z!Z0mo1hhWYVsTWfUyeFcL$zDlCrbMQ>g#Z)6}#n#p<5$&U4s{6(2CHh$~v9hhZ$=w JpXjxI{2#?3KF0t6 delta 2962 zcmYjTX>3&271mok6Tp_86dO4-*k&LAFxG zEmZ<0w2i26V)?Wj6=<2NZMp_VaZ42zd#Ec?+EmzORRqCpTB$!`IxVPFNI<`P?~L6) zv%GhgbH4L^-#LFeT6FAaQF_u01y1a7C!nh8D!OBCH+(X_SWVxwzPu#r#N$pJuN&lN zJR#S`@lecdc-;OVjMwUbsdM2`j|a zKQhF~MTau;ZJJ)}@$ly?o72K_b{Rr0F5r(oHY1!oW%~5bbuJAzhj}Pz zxzs-p;>+g@kNX=en~GZ1X?(oH5_BW%;pi}puXX8@kWZg3jPc+#Q=O+ScX=#k$u%~W zyx>w%M2A4*oq{LZ5#Y|K<#B4eVe`Z#)92oH!#yxz#JK;QAxN~rBSAkn8RIU2LI6dsZL)I7=fb1);{Pho{~8DSLwAjUuDgOxt_W!KfC9;( zl9eGk*Bnu}Q&&{b$Pz)7zYw$N@k`w(M)DKGrqk0tf7Ge(q>>tByx2A4F?yyqMm<+! zv}K`7*^YwISF08pI9LNPQY)w{>~psVk{xfsZU9ErLeSqF4}7v|e7Q%-cKbl1kq-y- zIuXb_MgC$zGYbRWeH4UKY{fwiPyWGN#gh$&Vk4Ce2yV5E+)dpQn{;V{k~IN^W18%l zi;9_ica7z0vbd`~>Om}$i*J|BNx|i7i%gF;Rz#I#h?^Z1>+p0PZ_5JBS)S4z05(`{ zf5*dx*`Et4D-$&AX?l;9tC|D&shCgCUG?Nj9+Xn+J&&gkPP&>U8OEB+oKWXC&AH%Q z2sT6&QJ0E+$&wIXdd-aT;1oF0`!k#0?2};h)8>MM$H zdKz0K&C=U8(2b@qP`Ve=Fadu5Ss_gZ0UrtT{bdN}81BpN)xhM9k&Y}95T~x^$dUvf z3XsS!RF`VhWahWat*!j-Ww1i3l-_t$3nsrmq56Gz2@^!NXq^7fM?p_6w*4R zx@Ag~S*e-n8J(}uyxqyz~fy8il z8cy_~8QI&v>5cwP#&7yJncWxi!hp;*N}KES_t#beX|x|WBP{<#SlZd%eoW3o&2&K|Hf*-V6@In5|66*zR z30qfN2~HnGznH8*%aQ_xp~>3omc=*QLD1P+FI%J39-^)LT-x6j@X{|CF`8@zDM65Q z-1@0n8(9O4FF;F@DpA@4erG+OU-^s`PFX+YAfJa*_F>=b``BFNW9buY$9VWFVik2m% zU~^wD*n|cQ%R@)@lo=IJwq7*@3-bX@&0EI1o2;)BN}vvhauLM4ur%2(nrA?-99KQ+ zYmDID1bx+qqzWa(o}lC=kDF!?eRriTJys?dqF1Zx=)?;6-M<69zxXj70jd$A&C3yr za^UYGKp;)~*J|x8JDs3U6}jAW2fBL+f=bVL%Gx>dEWA)!I^C?ttwq{`Av*Zl783=j z$?05Gud7rj8c+9v06tQx9L0gj)SQVQZINyn=8e!^&i*{2gR@!_x)E!4sg-EZSh-Jq zHEIPNdc>njWQ>Lm7w-^!z7@B0ZOaWAQqloEya(#a!QTy%!lDJZW7PVTLXxmN39}r4 z0+J1;FQO_#&(HVN7^6sEk@Tp;iK^*GHTN}5mLb5bfQ4zoL#bwPFZhyfaJl|j1p414xwjY#IGKj8_pZlCS9!v$&(9kL z{EaK%b$(J*-}v&r$~1ZIHy zKG0crYj&H@@d-0R<2mCQD-Vd?%A3z(IkwvTUIJAT6s`4b---KlX2DXO-MzT=D1Wft G+Vel|pBuLT diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json new file mode 100644 index 00000000000..e18b2a7deac --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json @@ -0,0 +1 @@ +b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json deleted file mode 100644 index 5992d970292..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json +++ /dev/null @@ -1 +0,0 @@ -b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 4ca3e6ba6603a850b66ab825624349eb7b1fa43e..6487de69be4444043802f1cb8b55c438fae16f92 100644 GIT binary patch delta 3175 zcmY*ce{fV+6`uFr=4}EbSyF9cC1DfV0O7rT_r15fA!#8?Q^+O|vygxtlu25&6K8B> zP^se&5@m!bR-5jzoYFcZ)*0H43ei}jnKD__DKmm(ouTSb32UXDI&I2!oPo9$>N)rB zX38H)cJI6I-gCb5ecw6x%Zc*GPnJ()byHZ;7R!gFE9>F9KB&3yt7Ib_G`?Er@q<{i z6Y$!RZ!9X?ur&h#qM^v}5e}hqiKTPX3 zM?D;X$H4z%OHXy=LMoA83|*eYC@Yd_xdUmGXBJa^VPu!a6O|eZQ;{xGt&r zcy5#7a^VK>^wO1yGe|$*y;pdG$KGjVpe$8`1j0oIQLH8|LrP3QWHIZH| zaWb*-w60Rn)6cb4*wF2IST#cz{G%~2gA^T&3w!^_0 zO|xOVEr_4Hmrha0$P^}@tG``?tQ|lxT|jb#kj(6)NIqYuBGh8|?m7zU{(Fg6nOZ## z1OF6I9d;KmOP`@2b2V|?)MkjZV?wG%08v2l=fEKkeo*JaiaP}~M|R`IIPo;MRiHUW zWk~D_z?s_>TD?gb6F%h7#aTN_bx{i^7ZYf?s}Zd1B@U0=bgBN5|JNEK_+*O=)5K>S zLzV&M_99*K^SZ#ghc$K5S*8`|pCj^7ZSk#X%_`DEK>kJ)hqv7d5#~FIQPZUYznq|# zNmKY=pU&(*M(SZq_j{BOQzCT5$AQ1;CzKtHNaU9-`{Sy z@O4kcC8K1CsH#ixr5+0~5ggd_jQ|e(i>~}&J5^vHsdNtKm)LZPkN0e%yhGberoIC5 zE1ys$$K~u!%VRt3ZosK9*aT!%fyN@fv@%&aT#V2eC(O0 z!sl<$87T)kDOXBSbJ1l7ppwFxlgfjRZM4#@0StGLPC`FZ`r2J9B%x^&Z(OipfmAIA zj@R$}cydjqOpPA@h6sP;106^e6qy6gd;yC)*8M55SO1X)smBDSPUvw=bm{|i zTSSI6kaZ!vm59l{u~!Ga{Xr?GWfyc0Q+JYyPyGAV{rMpeL;umPPbDtu9fk~?B6W!) zQrZXdLx=K1+Eji>e{F`+W1Y~CQtE<0@s<7Lb!@rcA^RbRNna0Oii*ajbAuY>GhNM4 z`9_nJ!?n9Kd%?u;y%s71tE8G51P%{Ueu@oQO*K0)1=!4zvRnnYxuE=B1v9+ zrJZ=aDx~~4)5$hLG`&sNn%7Py9}3cqDqx<9rPOnpVp`Rf|GjKc#=$O$9fYAKqQ&aO`HlbqR-UBa36?QcgSm_c074;4c zcS6=U(M&EL9w4qZM;x4`DUIa;or|2}z6aMCedI zbnro)2v8v3-!bVG;**5=X&>?81y2%%q-F7~G-s93yPugSU9dcRqdJcyIM_nPt9;ai zBWE2vv6!xxL*WZ63m-mQ=0d;8wBwBR8}RiDFx#5IbOsw`b6v`q#ap#KY+;dE((Qq}7*;|@Hx!}#w10XXoM AbN~PV delta 3082 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 literal 29045 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 G@BaZpTyaF`h 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 NWx@0{zWA(t>c1S~!$<%C diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json new file mode 100644 index 00000000000..e18b2a7deac --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json @@ -0,0 +1 @@ +b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json deleted file mode 100644 index 5992d970292..00000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-6b957c585f866e7d826afcd92d1a891ce226199229e3031f71994d14dd32f088.json +++ /dev/null @@ -1 +0,0 @@ -b4d9b2ac8940208c9b5a4182518b6792b89c7e08caa3f6b83a1f81526346d2be47f9c1d9c2b26a9d73103c8c2e525dd0 \ No newline at end of file diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/search-contract/schema/v1/search-contract-documents.json index 2f7be903882..444c1297f69 100644 --- a/packages/search-contract/schema/v1/search-contract-documents.json +++ b/packages/search-contract/schema/v1/search-contract-documents.json @@ -1,9 +1,8 @@ { - "contract": { + "contractKeywords": { "type": "object", "documentsMutable": false, "canBeDeleted": false, - "referenceType": "contract", "creationRestrictionMode": 2, "indices": [ { @@ -36,5 +35,83 @@ "keyword" ], "additionalProperties": false + }, + "shortDescription": { + "type": "object", + "documentsMutable": false, + "canBeDeleted": false, + "creationRestrictionMode": 2, + "indices": [ + { + "name": "byContractId", + "properties": [ + { + "contractId": "asc" + } + ], + "unique": true + } + ], + "properties": { + "contractId": { + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 0, + "contentMediaType": "application/x.dash.dpp.identifier" + }, + "description": { + "type": "string", + "minLength": 3, + "maxLength": 100, + "position": 1 + } + }, + "required": [ + "contractId", + "description" + ], + "description": "Short description of the contract. This document type is immutable and creation is not allowed. Creation occurs automatically internally on DataContractCreate and mirrors the contract's description field.", + "additionalProperties": false + }, + "fullDescription": { + "type": "object", + "documentsMutable": true, + "canBeDeleted": false, + "creationRestrictionMode": 2, + "indices": [ + { + "name": "byContractId", + "properties": [ + { + "contractId": "asc" + } + ], + "unique": true + } + ], + "properties": { + "contractId": { + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 0, + "contentMediaType": "application/x.dash.dpp.identifier" + }, + "description": { + "type": "string", + "minLength": 3, + "maxLength": 10000, + "position": 1 + } + }, + "required": [ + "contractId", + "description" + ], + "description": "Full description of the contract. This document type is mutable by contract owner but creation is not allowed. Creation occurs automatically internally on DataContractCreate and mirrors the contract's description field initially.", + "additionalProperties": false } } \ No newline at end of file diff --git a/packages/search-contract/src/v1/mod.rs b/packages/search-contract/src/v1/mod.rs index c237ea3343d..200a4523c97 100644 --- a/packages/search-contract/src/v1/mod.rs +++ b/packages/search-contract/src/v1/mod.rs @@ -2,13 +2,29 @@ use crate::Error; use serde_json::Value; pub mod document_types { - pub mod contract { - pub const NAME: &str = "contract"; + pub mod contract_keywords { + pub const NAME: &str = "contractKeywords"; pub mod properties { pub const KEY_INDEX: &str = "byKeyword"; } } + + pub mod short_description { + pub const NAME: &str = "shortDescription"; + + pub mod properties { + pub const KEY_INDEX: &str = "byContractId"; + } + } + + pub mod full_description { + pub const NAME: &str = "fullDescription"; + + pub mod properties { + pub const KEY_INDEX: &str = "byContractId"; + } + } } pub fn load_documents_schemas() -> Result { diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 244b233fc66..f609620bd63 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError, }; use wasm_bindgen::{JsError, JsValue}; -use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordEncodingError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; +use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDescriptionLengthError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordEncodingError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; @@ -773,6 +773,9 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::InvalidKeywordEncodingError(e) => { generic_consensus_error!(InvalidKeywordEncodingError, e).into() } + BasicError::InvalidDescriptionLengthError(e) => { + generic_consensus_error!(InvalidDescriptionLengthError, e).into() + } } } From 2a542a01c013b96295c1dff44dcad7d64a937b14 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 9 Apr 2025 22:00:57 +0700 Subject: [PATCH 21/46] fix: create genesis state error --- .../initialization/create_genesis_state/test/tokens.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs index 5b5aab870f6..625f38ceb2e 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs @@ -230,7 +230,7 @@ impl Platform { token_configuration.conventions.localizations.insert( "en".to_string(), TokenConfigurationLocalization::V0(TokenConfigurationLocalizationV0 { - should_capitalize, + should_capitalize: false, singular_form: "cat".to_string(), plural_form: "cats".to_string(), }), From d994cef7a96eace6c1a971bcabb3998b6a003f61 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 10 Apr 2025 15:29:38 +0700 Subject: [PATCH 22/46] fix: remove ascii requirement for contract keywords --- .../src/errors/consensus/basic/basic_error.rs | 5 +- .../invalid_keyword_encoding_error.rs | 44 ------------ .../consensus/basic/data_contract/mod.rs | 2 - packages/rs-dpp/src/errors/consensus/codes.rs | 3 +- .../advanced_structure/v0/mod.rs | 28 ++------ .../data_contract_create/mod.rs | 69 ------------------- .../src/errors/consensus/consensus_error.rs | 5 +- 7 files changed, 7 insertions(+), 149 deletions(-) delete mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index b1743acfa86..be54eed91c9 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -76,7 +76,7 @@ use crate::consensus::basic::{ use crate::consensus::ConsensusError; use super::data_contract::{ - DuplicateKeywordsError, InvalidDescriptionLengthError, InvalidKeywordEncodingError, + DuplicateKeywordsError, InvalidDescriptionLengthError, InvalidKeywordLengthError, TooManyKeywordsError, }; use crate::consensus::basic::group::GroupActionNotAllowedOnTransitionError; @@ -529,9 +529,6 @@ pub enum BasicError { #[error(transparent)] InvalidKeywordLengthError(InvalidKeywordLengthError), - #[error(transparent)] - InvalidKeywordEncodingError(InvalidKeywordEncodingError), - #[error(transparent)] InvalidDescriptionLengthError(InvalidDescriptionLengthError), } diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs deleted file mode 100644 index 57657d6c3d6..00000000000 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_encoding_error.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::consensus::basic::BasicError; -use crate::consensus::ConsensusError; -use crate::errors::ProtocolError; -use bincode::{Decode, Encode}; -use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; -use thiserror::Error; - -#[derive( - Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, -)] -#[error("Data contract {contract_id} has invalid keyword '{keyword}'. Keywords must be ASCII.")] -#[platform_serialize(unversioned)] -pub struct InvalidKeywordEncodingError { - /* - - DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION - - */ - contract_id: String, - keyword: String, -} - -impl InvalidKeywordEncodingError { - pub fn new(contract_id: String, keyword: String) -> Self { - Self { - contract_id, - keyword, - } - } - - pub fn contract_id(&self) -> &str { - &self.contract_id - } - - pub fn keyword(&self) -> &str { - &self.keyword - } -} - -impl From for ConsensusError { - fn from(err: InvalidKeywordEncodingError) -> Self { - Self::BasicError(BasicError::InvalidKeywordEncodingError(err)) - } -} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs index 56ea0690eca..a3d985596b9 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -28,7 +28,6 @@ mod invalid_document_type_required_security_level; mod invalid_index_property_type_error; mod invalid_indexed_property_constraint_error; mod invalid_json_schema_ref_error; -mod invalid_keyword_encoding_error; mod invalid_keyword_length_error; mod invalid_token_base_supply_error; mod invalid_token_distribution_function_divide_by_zero_error; @@ -84,7 +83,6 @@ pub use group_total_power_has_less_than_required_power_error::*; pub use incompatible_document_type_schema_error::*; pub use invalid_description_length_error::*; pub use invalid_document_type_name_error::*; -pub use invalid_keyword_encoding_error::*; pub use invalid_keyword_length_error::*; pub use invalid_token_base_supply_error::*; pub use invalid_token_distribution_function_divide_by_zero_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index e974c30e5bc..7f7dba78f84 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -109,8 +109,7 @@ impl ErrorWithCode for BasicError { Self::TooManyKeywordsError(_) => 10262, Self::DuplicateKeywordsError(_) => 10263, Self::InvalidKeywordLengthError(_) => 10264, - Self::InvalidKeywordEncodingError(_) => 10265, - Self::InvalidDescriptionLengthError(_) => 10266, + Self::InvalidDescriptionLengthError(_) => 10265, // Group Errors: 10350-10399 Self::GroupPositionDoesNotExistError(_) => 10350, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs index 85aa0655e39..60029040eee 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs @@ -6,13 +6,10 @@ use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; use dpp::consensus::basic::data_contract::{ - DuplicateKeywordsError, InvalidDescriptionLengthError, InvalidKeywordLengthError, + DuplicateKeywordsError, InvalidDataContractIdError, InvalidDataContractVersionError, + InvalidDescriptionLengthError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, + NonContiguousContractTokenPositionsError, TooManyKeywordsError, }; -use dpp::consensus::basic::data_contract::{ - InvalidDataContractIdError, InvalidDataContractVersionError, InvalidTokenBaseSupplyError, - NonContiguousContractTokenPositionsError, -}; -use dpp::consensus::basic::data_contract::{InvalidKeywordEncodingError, TooManyKeywordsError}; use dpp::consensus::basic::BasicError; use dpp::consensus::ConsensusError; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; @@ -173,7 +170,7 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 )); } - // Validate the keywords are all unique, between 3 and 50 characters, and all ASCII + // Validate the keywords are all unique and between 3 and 50 characters let mut seen_keywords = HashSet::new(); for keyword in self.data_contract().keywords() { // First check keyword length @@ -193,23 +190,6 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 )); } - // Then check keyword is ASCII - if !keyword.is_ascii() { - let bump_action = StateTransitionAction::BumpIdentityNonceAction( - BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), - ); - - return Ok(ConsensusValidationResult::new_with_data_and_errors( - bump_action, - vec![ConsensusError::BasicError( - BasicError::InvalidKeywordEncodingError(InvalidKeywordEncodingError::new( - self.data_contract().id().to_string(Encoding::Base58), - keyword.to_string(), - )), - )], - )); - } - // Then check uniqueness if !seen_keywords.insert(keyword) { let bump_action = StateTransitionAction::BumpIdentityNonceAction( diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index 8c5a168089a..2a019870fd8 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2775,75 +2775,6 @@ mod tests { ); } - #[test] - fn test_data_contract_creation_fails_with_non_ascii_keyword() { - let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() - .build_with_mock_rpc() - .set_genesis_state(); - - let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", - None, - None, - false, - platform_version, - ) - .expect("expected to load contract"); - - let mut contract_value = data_contract - .to_value(platform_version) - .expect("to_value failed"); - - // Insert a keyword with a non-ASCII char, e.g. ü - contract_value["keywords"] = Value::Array(vec![Value::Text("keü".to_string())]); - - let data_contract_invalid = - DataContract::from_value(contract_value, true, platform_version) - .expect("failed to create DataContract"); - - let data_contract_create_transition = - DataContractCreateTransition::new_from_data_contract( - data_contract_invalid, - 1, - &identity.into_partial_identity_info(), - key.id(), - &signer, - platform_version, - None, - ) - .expect("expect to create transition"); - - let data_contract_create_serialized_transition = data_contract_create_transition - .serialize_to_bytes() - .expect("expected to serialize"); - - let transaction = platform.drive.grove.start_transaction(); - let processing_result = platform - .platform - .process_raw_state_transitions( - &[data_contract_create_serialized_transition], - &platform_state, - &BlockInfo::default(), - &transaction, - platform_version, - false, - None, - ) - .expect("expected to process state transition"); - - assert_matches!( - processing_result.execution_results().as_slice(), - [StateTransitionExecutionResult::PaidConsensusError( - ConsensusError::BasicError(BasicError::InvalidKeywordEncodingError(_)), - _ - )] - ); - } - #[test] fn test_data_contract_creation_succeeds_with_valid_keywords() { let platform_version = PlatformVersion::latest(); diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index f609620bd63..acb92e74bc1 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError, }; use wasm_bindgen::{JsError, JsValue}; -use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDescriptionLengthError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordEncodingError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; +use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDescriptionLengthError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; @@ -770,9 +770,6 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::InvalidKeywordLengthError(e) => { generic_consensus_error!(InvalidKeywordLengthError, e).into() } - BasicError::InvalidKeywordEncodingError(e) => { - generic_consensus_error!(InvalidKeywordEncodingError, e).into() - } BasicError::InvalidDescriptionLengthError(e) => { generic_consensus_error!(InvalidDescriptionLengthError, e).into() } From 043a7190c2f94ac8e267e2616924c5b9ece3536d Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 10 Apr 2025 15:41:03 +0700 Subject: [PATCH 23/46] update DataContractV1 description with description field --- packages/rs-dpp/src/data_contract/v1/data_contract.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/rs-dpp/src/data_contract/v1/data_contract.rs b/packages/rs-dpp/src/data_contract/v1/data_contract.rs index 37318e70ca5..e9c247f2373 100644 --- a/packages/rs-dpp/src/data_contract/v1/data_contract.rs +++ b/packages/rs-dpp/src/data_contract/v1/data_contract.rs @@ -66,6 +66,11 @@ use platform_value::Value; /// - This vector can be left empty, but if populated, it must contain unique keywords. /// - The maximum number of keywords is limited to 20. /// +/// ## 5. **Description** (`description: Option`) +/// - A human-readable description of the contract. +/// - This field is optional but if provided, must be between 3 and 100 characters. +/// - The description is automatically added to the new `search` system contract as well. +/// /// These additions ensure that data contracts are not only more flexible and governed but also /// fully auditable in terms of when and how they evolve over time. #[derive(Debug, Clone, PartialEq)] From 0382954307dbe4e4fdecc4b8b5f2cd8bc117907f Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 10 Apr 2025 20:26:13 +0700 Subject: [PATCH 24/46] handle keywords and descriptions in contract update --- .../src/errors/consensus/basic/basic_error.rs | 4 +- .../data_contract_update/mod.rs | 730 ++++++++++++++++++ .../contract/insert/add_description/mod.rs | 1 + .../contract/insert/add_description/v0/mod.rs | 58 +- .../insert/add_new_keywords/v0/mod.rs | 6 +- .../contract/update/update_contract/v1/mod.rs | 27 + .../v1/update_description/mod.rs | 134 ++++ .../v1/update_description/v1/mod.rs | 173 +++++ .../update_contract/v1/update_keywords/mod.rs | 134 ++++ .../v1/update_keywords/v1/mod.rs | 152 ++++ .../schema/v1/search-contract-documents.json | 18 +- 11 files changed, 1400 insertions(+), 37 deletions(-) create mode 100644 packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index be54eed91c9..015d27e506a 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -76,8 +76,8 @@ use crate::consensus::basic::{ use crate::consensus::ConsensusError; use super::data_contract::{ - DuplicateKeywordsError, InvalidDescriptionLengthError, - InvalidKeywordLengthError, TooManyKeywordsError, + DuplicateKeywordsError, InvalidDescriptionLengthError, InvalidKeywordLengthError, + TooManyKeywordsError, }; use crate::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use crate::consensus::basic::overflow_error::OverflowError; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index ab99794aeb2..5b7165e185e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -1526,4 +1526,734 @@ mod tests { .expect("expected to commit transaction"); } } + + mod keyword_updates { + use super::*; + use dpp::{ + data_contract::conversion::value::v0::DataContractValueConversionMethodsV0, + data_contracts::SystemDataContract, + document::DocumentV0Getters, + platform_value::{string_encoding::Encoding, Value}, + state_transition::{ + data_contract_create_transition::{ + methods::DataContractCreateTransitionMethodsV0, DataContractCreateTransition, + }, + StateTransition, + }, + system_data_contracts::load_system_data_contract, + tests::json_document::json_document_to_contract_with_ids, + }; + use drive::{ + drive::document::query::QueryDocumentsOutcomeV0Methods, + query::{DriveDocumentQuery, WhereClause, WhereOperator}, + }; + + // ──────────────────────────────────────────────────────────────────────── + // helpers + // ──────────────────────────────────────────────────────────────────────── + + /// Creates a contract with the supplied keywords and commits it to Drive. + /// Returns `(contract_id, create_transition)`. + fn create_contract_with_keywords( + platform: &mut TempPlatform, + identity: &Identity, + signer: &SimpleSigner, + key: &IdentityPublicKey, + keywords: &[&str], + platform_version: &PlatformVersion, + ) -> (Identifier, StateTransition) { + let base = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("load base contract"); + + let mut val = base.to_value(platform_version).expect("to_value"); + + val["keywords"] = Value::Array( + keywords + .iter() + .map(|k| Value::Text(k.to_string())) + .collect(), + ); + + let contract = + DataContract::from_value(val, true, platform_version).expect("from_value"); + + let create = DataContractCreateTransition::new_from_data_contract( + contract, + 2, + &identity.clone().into_partial_identity_info(), + key.id(), + signer, + platform_version, + None, + ) + .expect("create transition"); + + let tx_bytes = create.serialize_to_bytes().expect("serialize"); + + let tx = platform.drive.grove.start_transaction(); + let platform_state = platform.state.load(); + + let res = platform + .platform + .process_raw_state_transitions( + &[tx_bytes], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("process create"); + + assert_matches!( + res.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(tx) + .unwrap() + .expect("commit create"); + + // pull id from unique_identifiers + let contract_id = Identifier::from_string( + create + .unique_identifiers() + .first() + .unwrap() + .as_str() + .split('-') + .last() + .unwrap(), + Encoding::Base58, + ) + .unwrap(); + + (contract_id, create) + } + + /// Convenience for building and applying an **update** transition that + /// only changes the `keywords` array. + fn apply_keyword_update( + platform: &mut TempPlatform, + contract_id: Identifier, + identity: &Identity, + signer: &SimpleSigner, + key: &IdentityPublicKey, + new_keywords: &[&str], + platform_version: &PlatformVersion, + ) -> Result<(), Vec> { + // fetch existing contract + let fetched = platform + .drive + .fetch_contract(contract_id.into(), None, None, None, platform_version) + .value + .unwrap() + .unwrap(); + + let mut val = fetched.contract.to_value(platform_version).unwrap(); + + val["keywords"] = Value::Array( + new_keywords + .iter() + .map(|k| Value::Text(k.to_string())) + .collect(), + ); + + let mut updated_contract = + DataContract::from_value(val, true, platform_version).unwrap(); + updated_contract.set_version(2); + + let update = DataContractUpdateTransition::new_from_data_contract( + updated_contract, + &identity.clone().into_partial_identity_info(), + key.id(), + 2, + 0, + signer, + platform_version, + None, + ) + .expect("build update"); + + let bytes = update.serialize_to_bytes().unwrap(); + + let tx = platform.drive.grove.start_transaction(); + let platform_state = platform.state.load(); + + let outcome = platform + .platform + .process_raw_state_transitions( + &[bytes], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("process update"); + + if matches!( + outcome.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ) { + platform + .drive + .grove + .commit_transaction(tx) + .unwrap() + .expect("commit update"); + Ok(()) + } else { + Err(outcome.execution_results().to_vec()) + } + } + + /// Helper to read all keyword docs for a contract id. + fn keyword_docs_for_contract( + platform: &TempPlatform, + contract_id: Identifier, + platform_version: &PlatformVersion, + ) -> Vec { + let search_contract = + load_system_data_contract(SystemDataContract::Search, platform_version).unwrap(); + let doc_type = search_contract + .document_type_for_name("contractKeywords") + .unwrap(); + + let mut query = DriveDocumentQuery { + contract: &search_contract, + document_type: doc_type, + internal_clauses: Default::default(), + offset: None, + limit: None, + order_by: Default::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + query.internal_clauses.equal_clauses.insert( + "contractId".to_string(), + WhereClause { + field: "contractId".to_string(), + operator: WhereOperator::Equal, + value: contract_id.into(), + }, + ); + + let res = platform + .drive + .query_documents(query, None, false, None, None) + .unwrap(); + + res.documents() + .iter() + .map(|d| d.get("keyword").unwrap().as_str().unwrap().to_owned()) + .collect() + } + + // ──────────────────────────────────────────────────────────────────────── + // negative cases – same validation as create + // ──────────────────────────────────────────────────────────────────────── + + macro_rules! invalid_update_test { + ($name:ident, $keywords:expr, $error:pat_param) => { + #[test] + fn $name() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // create initial contract with one keyword so update is allowed + let (cid, _) = create_contract_with_keywords( + &mut platform, + &identity, + &signer, + &key, + &["orig"], + &platform_version, + ); + + // try invalid update + let err = apply_keyword_update( + &mut platform, + cid, + &identity, + &signer, + &key, + &$keywords, + &platform_version, + ) + .unwrap_err(); + + assert_matches!( + err.as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError($error), + _ + )] + ); + + // original keyword docs must still be there + let docs = keyword_docs_for_contract(&platform, cid, &platform_version); + assert_eq!(docs, vec!["orig"]); + } + }; + } + + invalid_update_test!( + update_fails_too_many_keywords, + [ + "kw0", "kw1", "kw2", "kw3", "kw4", "kw5", "kw6", "kw7", "kw8", "kw9", "kw10", + "kw11", "kw12", "kw13", "kw14", "kw15", "kw16", "kw17", "kw18", "kw19", "kw20", + ], + BasicError::TooManyKeywordsError(_) + ); + + invalid_update_test!( + update_fails_duplicate_keywords, + ["dup", "dup"], + BasicError::DuplicateKeywordsError(_) + ); + + invalid_update_test!( + update_fails_keyword_too_short, + ["hi"], + BasicError::InvalidKeywordLengthError(_) + ); + + invalid_update_test!( + update_fails_keyword_too_long, + [&"x".repeat(51)], + BasicError::InvalidKeywordLengthError(_) + ); + + // ──────────────────────────────────────────────────────────────────────── + // positive case – old docs removed, new docs inserted + // ──────────────────────────────────────────────────────────────────────── + + #[test] + fn update_keywords_replaces_search_docs() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // initial contract with two keywords + let (cid, _) = create_contract_with_keywords( + &mut platform, + &identity, + &signer, + &key, + &["old1", "old2"], + &platform_version, + ); + + // verify initial docs + let initial_docs = keyword_docs_for_contract(&platform, cid, &platform_version); + assert_eq!(initial_docs.len(), 2); + + // apply update to ["newA", "newB", "newC"] + apply_keyword_update( + &mut platform, + cid, + &identity, + &signer, + &key, + &["newA", "newB", "newC"], + &platform_version, + ) + .expect("update should succeed"); + + // fetch contract – keywords updated? + let fetched = platform + .drive + .fetch_contract(cid.into(), None, None, None, &platform_version) + .value + .unwrap() + .unwrap(); + assert_eq!( + *fetched.contract.keywords(), + vec!["newA", "newB", "newC"] + .iter() + .map(|&s| s.to_string()) + .collect::>() + ); + + // search‑contract docs updated? + let docs_after = keyword_docs_for_contract(&platform, cid, &platform_version); + assert_eq!(docs_after.len(), 3); + assert!(docs_after.contains(&"newA".to_string())); + assert!(docs_after.contains(&"newB".to_string())); + assert!(docs_after.contains(&"newC".to_string())); + // old docs gone + assert!(!docs_after.contains(&"old1".to_string())); + assert!(!docs_after.contains(&"old2".to_string())); + } + } + + mod description_updates { + use super::*; + use dpp::{ + data_contract::conversion::value::v0::DataContractValueConversionMethodsV0, + data_contracts::SystemDataContract, + document::DocumentV0Getters, + platform_value::{string_encoding::Encoding, Value}, + state_transition::{ + data_contract_create_transition::{ + methods::DataContractCreateTransitionMethodsV0, DataContractCreateTransition, + }, + StateTransition, + }, + system_data_contracts::load_system_data_contract, + tests::json_document::json_document_to_contract_with_ids, + }; + use drive::{ + drive::document::query::QueryDocumentsOutcomeV0Methods, + query::{DriveDocumentQuery, WhereClause, WhereOperator}, + }; + + // ──────────────────────────────────────────────────────────────────────── + // helpers + // ──────────────────────────────────────────────────────────────────────── + + /// Creates a contract with the supplied description and commits it to Drive. + /// Returns `(contract_id, create_transition)`. + fn create_contract_with_description( + platform: &mut TempPlatform, + identity: &Identity, + signer: &SimpleSigner, + key: &IdentityPublicKey, + description: &str, + platform_version: &PlatformVersion, + ) -> (Identifier, StateTransition) { + let base = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + None, + None, + false, + platform_version, + ) + .expect("load base contract"); + + let mut val = base.to_value(platform_version).expect("to_value"); + + val["description"] = Value::Text(description.to_string()); + + let contract = + DataContract::from_value(val, true, platform_version).expect("from_value"); + + let create = DataContractCreateTransition::new_from_data_contract( + contract, + 2, + &identity.clone().into_partial_identity_info(), + key.id(), + signer, + platform_version, + None, + ) + .expect("create transition"); + + let tx_bytes = create.serialize_to_bytes().expect("serialize"); + + let tx = platform.drive.grove.start_transaction(); + let platform_state = platform.state.load(); + + let res = platform + .platform + .process_raw_state_transitions( + &[tx_bytes], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("process create"); + + assert_matches!( + res.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(tx) + .unwrap() + .expect("commit create"); + + // pull id from unique_identifiers + let contract_id = Identifier::from_string( + create + .unique_identifiers() + .first() + .unwrap() + .as_str() + .split('-') + .last() + .unwrap(), + Encoding::Base58, + ) + .unwrap(); + + (contract_id, create) + } + + /// Convenience for building and applying an **update** transition that + /// only changes the `description` string. + fn apply_description_update( + platform: &mut TempPlatform, + contract_id: Identifier, + identity: &Identity, + signer: &SimpleSigner, + key: &IdentityPublicKey, + new_description: &str, + platform_version: &PlatformVersion, + ) -> Result<(), Vec> { + // fetch existing contract + let fetched = platform + .drive + .fetch_contract(contract_id.into(), None, None, None, platform_version) + .value + .unwrap() + .unwrap(); + + let mut val = fetched.contract.to_value(platform_version).unwrap(); + + val["description"] = Value::Text(new_description.to_string()); + + let mut updated_contract = + DataContract::from_value(val, true, platform_version).unwrap(); + updated_contract.set_version(2); + + let update = DataContractUpdateTransition::new_from_data_contract( + updated_contract, + &identity.clone().into_partial_identity_info(), + key.id(), + 2, + 0, + signer, + platform_version, + None, + ) + .expect("build update"); + + let bytes = update.serialize_to_bytes().unwrap(); + + let tx = platform.drive.grove.start_transaction(); + let platform_state = platform.state.load(); + + let outcome = platform + .platform + .process_raw_state_transitions( + &[bytes], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("process update"); + + if matches!( + outcome.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ) { + platform + .drive + .grove + .commit_transaction(tx) + .unwrap() + .expect("commit update"); + Ok(()) + } else { + Err(outcome.execution_results().to_vec()) + } + } + + /// Helper to read all description docs for a contract id. + fn description_docs_for_contract( + platform: &TempPlatform, + contract_id: Identifier, + platform_version: &PlatformVersion, + ) -> String { + let search_contract = + load_system_data_contract(SystemDataContract::Search, platform_version).unwrap(); + let doc_type = search_contract + .document_type_for_name("shortDescription") + .unwrap(); + + let mut query = DriveDocumentQuery { + contract: &search_contract, + document_type: doc_type, + internal_clauses: Default::default(), + offset: None, + limit: None, + order_by: Default::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + query.internal_clauses.equal_clauses.insert( + "contractId".to_string(), + WhereClause { + field: "contractId".to_string(), + operator: WhereOperator::Equal, + value: contract_id.into(), + }, + ); + + let res = platform + .drive + .query_documents(query, None, false, None, None) + .unwrap(); + + res.documents() + .iter() + .map(|d| d.get("description").unwrap().as_str().unwrap().to_owned()) + .collect() + } + + // ──────────────────────────────────────────────────────────────────────── + // negative cases – same validation as create + // ──────────────────────────────────────────────────────────────────────── + + macro_rules! invalid_update_test { + ($name:ident, $description:expr, $error:pat_param) => { + #[test] + fn $name() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // create initial contract with description so update is allowed + let (cid, _) = create_contract_with_description( + &mut platform, + &identity, + &signer, + &key, + &"orig", + &platform_version, + ); + + // try invalid update + let err = apply_description_update( + &mut platform, + cid, + &identity, + &signer, + &key, + &$description, + &platform_version, + ) + .unwrap_err(); + + assert_matches!( + err.as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError($error), + _ + )] + ); + + // original description docs must still be there + let docs = description_docs_for_contract(&platform, cid, &platform_version); + assert_eq!(docs, "orig".to_string()); + } + }; + } + + invalid_update_test!( + update_fails_description_too_short, + "hi", + BasicError::InvalidDescriptionLengthError(_) + ); + + invalid_update_test!( + update_fails_description_too_long, + &"x".repeat(51), + BasicError::InvalidDescriptionLengthError(_) + ); + + // ──────────────────────────────────────────────────────────────────────── + // positive case – old docs removed, new docs inserted + // ──────────────────────────────────────────────────────────────────────── + + #[test] + fn update_description_replaces_search_docs() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + // initial contract with description + let (cid, _) = create_contract_with_description( + &mut platform, + &identity, + &signer, + &key, + &"old1", + &platform_version, + ); + + // verify initial docs + let initial_docs = description_docs_for_contract(&platform, cid, &platform_version); + assert_eq!(initial_docs, "old1".to_string()); + + // apply update to "newA" + apply_description_update( + &mut platform, + cid, + &identity, + &signer, + &key, + &"newA", + &platform_version, + ) + .expect("update should succeed"); + + // fetch contract – description updated? + let fetched = platform + .drive + .fetch_contract(cid.into(), None, None, None, &platform_version) + .value + .unwrap() + .unwrap(); + assert_eq!( + fetched.contract.description(), + Some("newA".to_string()).as_ref() + ); + + // search‑contract docs updated? + let docs_after = description_docs_for_contract(&platform, cid, &platform_version); + assert_eq!(docs_after, "newA".to_string()); + // old docs gone + assert!(!docs_after.contains(&"old1".to_string())); + } + } } diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs index 9931b56defb..c1719b389e8 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs @@ -119,6 +119,7 @@ impl Drive { contract_id, owner_id, description, + false, block_info, estimated_costs_only_with_layer_info, transaction, diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs index 855724c9c8b..c289b462411 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs @@ -85,11 +85,12 @@ impl Drive { } /// The operations needed to create a description - pub(super) fn add_new_contract_description_operations_v0( + pub(crate) fn add_new_contract_description_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, description: &String, + short_only: bool, block_info: &BlockInfo, estimated_costs_only_with_layer_info: &mut Option< HashMap, @@ -100,10 +101,8 @@ impl Drive { let mut operations: Vec = vec![]; let contract = self.cache.system_data_contracts.load_search(); - let short_description_document_type = contract.document_type_for_name("shortDescription")?; - let full_description_document_type = contract.document_type_for_name("fullDescription")?; let short_description_document = self.build_contract_description_document_owned_v0( contract_id, @@ -112,13 +111,6 @@ impl Drive { false, block_info, )?; - let full_description_document = self.build_contract_description_document_owned_v0( - contract_id, - owner_id, - description, - true, - block_info, - )?; let short_description_ops = self.add_document_for_contract_operations( DocumentAndContractInfo { @@ -136,25 +128,37 @@ impl Drive { transaction, platform_version, )?; - let full_description_ops = self.add_document_for_contract_operations( - DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentOwnedInfo((full_description_document, None)), - owner_id: Some(owner_id.to_buffer()), - }, - contract: &contract, - document_type: full_description_document_type, - }, - true, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - )?; operations.extend(short_description_ops); - operations.extend(full_description_ops); + + if !short_only { + let full_description_document_type = + contract.document_type_for_name("fullDescription")?; + let full_description_document = self.build_contract_description_document_owned_v0( + contract_id, + owner_id, + description, + true, + block_info, + )?; + let full_description_ops = self.add_document_for_contract_operations( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentOwnedInfo((full_description_document, None)), + owner_id: Some(owner_id.to_buffer()), + }, + contract: &contract, + document_type: full_description_document_type, + }, + true, + block_info, + &mut None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + operations.extend(full_description_ops); + } Ok(operations) } diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index a7daf634932..6ba29acdabb 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -85,7 +85,7 @@ impl Drive { } /// The operations needed to create a keyword - pub(super) fn add_new_contract_keywords_operations_v0( + pub(crate) fn add_new_contract_keywords_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -97,11 +97,11 @@ impl Drive { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { + let mut operations: Vec = vec![]; + let contract = self.cache.system_data_contracts.load_search(); let document_type = contract.document_type_for_name("contractKeywords")?; - let mut operations: Vec = vec![]; - for (i, keyword) in keywords.iter().enumerate() { let document = self.build_contract_keyword_document_owned_v0( contract_id, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs index d350369026f..f439d126547 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs @@ -20,6 +20,9 @@ use grovedb::batch::KeyInfoPath; use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; +mod update_description; +mod update_keywords; + impl Drive { /// Updates a data contract. /// @@ -251,6 +254,30 @@ impl Drive { )?); } + if !contract.keywords().is_empty() { + batch_operations.extend(self.update_contract_keywords_operations( + contract.id(), + contract.owner_id(), + contract.keywords(), + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + + if let Some(description) = contract.description() { + batch_operations.extend(self.update_contract_description_operations( + contract.id(), + contract.owner_id(), + description, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + Ok(batch_operations) } } diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs new file mode 100644 index 00000000000..951628bd2ca --- /dev/null +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs @@ -0,0 +1,134 @@ +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::version::PlatformVersion; + +use dpp::prelude::Identifier; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use std::collections::HashMap; + +mod v1; + +impl Drive { + /// Updates contract description in the state. + pub fn update_contract_description( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract descriptions are not supported in this version", + ))), + 1 => self.update_contract_description_v0( + contract_id, + owner_id, + description, + block_info, + apply, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "update_contract_description".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } + + /// Adds contract description update operations to drive operations + pub fn update_contract_description_add_to_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract descriptions are not supported in this version", + ))), + 1 => self.update_contract_description_add_to_operations_v0( + contract_id, + owner_id, + description, + block_info, + apply, + transaction, + drive_operations, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "update_contract_description_add_to_operations".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } + + /// The operations needed to update a description + pub fn update_contract_description_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract descriptions are not supported in this version", + ))), + 1 => self.update_contract_description_operations_v0( + contract_id, + owner_id, + description, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "update_contract_description_operations".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs new file mode 100644 index 00000000000..12343d27793 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs @@ -0,0 +1,173 @@ +use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::query::{DriveDocumentQuery, WhereClause, WhereOperator}; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::document::DocumentV0Setters; +use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; +use dpp::platform_value::Value; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use platform_version::version::PlatformVersion; +use std::collections::HashMap; + +impl Drive { + /// Adds operations for updating a contract description and returns the fee result. + pub(super) fn update_contract_description_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let mut drive_operations: Vec = vec![]; + self.update_contract_description_add_to_operations_v0( + contract_id, + owner_id, + description, + block_info, + apply, + transaction, + &mut drive_operations, + platform_version, + )?; + let fees = Drive::calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + self.config.epochs_per_era, + platform_version, + None, + )?; + Ok(fees) + } + + /// Adds contract description update operations to drive operations + pub(super) fn update_contract_description_add_to_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let mut estimated_costs_only_with_layer_info = if apply { + None::> + } else { + Some(HashMap::new()) + }; + + let batch_operations = self.update_contract_description_operations( + contract_id, + owner_id, + description, + block_info, + &mut estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + self.apply_batch_low_level_drive_operations( + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + drive_operations, + &platform_version.drive, + ) + } + + /// The operations needed to update a contract description + pub(super) fn update_contract_description_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + description: &String, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut operations: Vec = vec![]; + + let contract = self.cache.system_data_contracts.load_search().clone(); + let document_type = contract.document_type_for_name("shortDescription")?; + + let mut query = DriveDocumentQuery::all_items_query(&contract, document_type, None); + query.internal_clauses.equal_clauses.insert( + "contractId".to_string(), + WhereClause { + field: "contractId".to_string(), + operator: WhereOperator::Equal, + value: Value::Identifier(contract_id.to_buffer()), + }, + ); + + let query_outcome = self.query_documents( + query, + Some(&block_info.epoch), + false, + transaction, + Some(platform_version.protocol_version), + )?; + + let existing_documents = query_outcome.documents(); + + if existing_documents.len() > 1 { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "There should be only one `shortDescription` document per contract in the Keyword Search contract".to_string(), + ))); + } + + if existing_documents.is_empty() { + // Add the new one + operations.extend(self.add_new_contract_description_operations_v0( + contract_id, + owner_id, + description, + true, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } else { + // Replace the existing one + let document = existing_documents.first().expect("Document should exist"); + let mut new_document = document.clone(); + new_document.set("description", Value::Text(description.clone())); + + let info = DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentOwnedInfo((new_document, None)), + owner_id: Some(owner_id.to_buffer()), + }, + contract: &contract.clone(), + document_type, + }; + + operations.extend(self.update_document_for_contract_operations( + info, + block_info, + &mut None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + + Ok(operations) + } +} diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs new file mode 100644 index 00000000000..b0da89d7ee6 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs @@ -0,0 +1,134 @@ +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::version::PlatformVersion; + +use dpp::prelude::Identifier; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use std::collections::HashMap; + +mod v1; + +impl Drive { + /// Updates keywords in the state. + pub fn update_contract_keywords( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &[String], + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract keywords are not supported in this version", + ))), + 1 => self.update_contract_keywords_v0( + contract_id, + owner_id, + keywords, + block_info, + apply, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "update_keywords".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } + + /// Adds keywords creation operations to drive operations + pub fn update_contract_keywords_add_to_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &[String], + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive + .methods + .contract + .insert + .insert_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract keywords are not supported in this version", + ))), + 1 => self.update_contract_keywords_add_to_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + apply, + transaction, + drive_operations, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "update_keywords_add_to_operations".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } + + /// The operations needed to update keywords + pub fn update_contract_keywords_operations( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &[String], + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .update + .update_contract + { + 0 => Err(Error::Drive(DriveError::NotSupported( + "Contract keywords are not supported in this version", + ))), + 1 => self.update_contract_keywords_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "update_keywords_operations".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs new file mode 100644 index 00000000000..5dab58aab35 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs @@ -0,0 +1,152 @@ +use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::query::{DriveDocumentQuery, WhereClause, WhereOperator}; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::document::DocumentV0Getters; +use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; +use dpp::platform_value::Value; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use platform_version::version::PlatformVersion; +use std::collections::{BTreeMap, HashMap}; + +impl Drive { + /// Adds operations for updating keywords and returns the fee result. + pub(super) fn update_contract_keywords_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &[String], + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let mut drive_operations: Vec = vec![]; + self.update_contract_keywords_add_to_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + apply, + transaction, + &mut drive_operations, + platform_version, + )?; + let fees = Drive::calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + self.config.epochs_per_era, + platform_version, + None, + )?; + Ok(fees) + } + + /// Adds keyword update operations to drive operations + pub(super) fn update_contract_keywords_add_to_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &[String], + block_info: &BlockInfo, + apply: bool, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let mut estimated_costs_only_with_layer_info = if apply { + None::> + } else { + Some(HashMap::new()) + }; + + let batch_operations = self.update_contract_keywords_operations( + contract_id, + owner_id, + keywords, + block_info, + &mut estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + + self.apply_batch_low_level_drive_operations( + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + drive_operations, + &platform_version.drive, + ) + } + + /// The operations needed to update the keywords search contract documents + /// First we delete the existing keywords then we add the new ones + pub(super) fn update_contract_keywords_operations_v0( + &self, + contract_id: Identifier, + owner_id: Identifier, + keywords: &[String], + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut operations: Vec = vec![]; + + // First delete the existing keywords + let contract = self.cache.system_data_contracts.load_search().clone(); + let document_type = contract.document_type_for_name("contractKeywords")?; + + let mut query = DriveDocumentQuery::all_items_query(&contract, document_type, None); + query.internal_clauses.equal_clauses.insert( + "contractId".to_string(), + WhereClause { + field: "contractId".to_string(), + operator: WhereOperator::Equal, + value: Value::Identifier(contract_id.to_buffer()), + }, + ); + + let query_outcome = self.query_documents( + query, + Some(&block_info.epoch), + false, + transaction, + Some(platform_version.protocol_version), + )?; + + let existing_documents = query_outcome.documents(); + for document in existing_documents { + operations.extend(self.delete_document_for_contract_operations( + document.id(), + &contract, + document_type, + None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + + // Then add the new ones + operations.extend(self.add_new_contract_keywords_operations_v0( + contract_id, + owner_id, + keywords, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + + Ok(operations) + } +} diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/search-contract/schema/v1/search-contract-documents.json index 444c1297f69..be74e7cbe6c 100644 --- a/packages/search-contract/schema/v1/search-contract-documents.json +++ b/packages/search-contract/schema/v1/search-contract-documents.json @@ -1,8 +1,8 @@ { "contractKeywords": { "type": "object", - "documentsMutable": false, - "canBeDeleted": false, + "documentsMutable": true, + "canBeDeleted": true, "creationRestrictionMode": 2, "indices": [ { @@ -12,6 +12,14 @@ "keyword": "asc" } ] + }, + { + "name": "byContractId", + "properties": [ + { + "contractId": "asc" + } + ] } ], "properties": { @@ -38,8 +46,8 @@ }, "shortDescription": { "type": "object", - "documentsMutable": false, - "canBeDeleted": false, + "documentsMutable": true, + "canBeDeleted": true, "creationRestrictionMode": 2, "indices": [ { @@ -78,7 +86,7 @@ "fullDescription": { "type": "object", "documentsMutable": true, - "canBeDeleted": false, + "canBeDeleted": true, "creationRestrictionMode": 2, "indices": [ { From ae564373bfde07ac84278d3eafde7b169f3c3b15 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 10 Apr 2025 20:39:01 +0700 Subject: [PATCH 25/46] rename to v1 --- .../drive/contract/insert/add_description/mod.rs | 8 ++++---- .../insert/add_description/{v0 => v1}/mod.rs | 14 +++++++------- .../drive/contract/insert/add_new_keywords/mod.rs | 8 ++++---- .../insert/add_new_keywords/{v0 => v1}/mod.rs | 12 ++++++------ .../contract/update/update_contract/v1/mod.rs | 2 ++ .../update_contract/v1/update_description/mod.rs | 6 +++--- .../v1/update_description/v1/mod.rs | 10 +++++----- .../update_contract/v1/update_keywords/mod.rs | 6 +++--- .../update_contract/v1/update_keywords/v1/mod.rs | 12 ++++++------ 9 files changed, 40 insertions(+), 38 deletions(-) rename packages/rs-drive/src/drive/contract/insert/add_description/{v0 => v1}/mod.rs (95%) rename packages/rs-drive/src/drive/contract/insert/add_new_keywords/{v0 => v1}/mod.rs (94%) diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs index c1719b389e8..9839fb75285 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs @@ -11,7 +11,7 @@ use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -mod v0; +mod v1; impl Drive { /// Adds contract description to the state. @@ -35,7 +35,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", ))), - 1 => self.add_new_contract_description_v0( + 1 => self.add_new_contract_description_v1( contract_id, owner_id, description, @@ -74,7 +74,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", ))), - 1 => self.add_new_contract_description_add_to_operations_v0( + 1 => self.add_new_contract_description_add_to_operations_v1( contract_id, owner_id, description, @@ -115,7 +115,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", ))), - 1 => self.add_new_contract_description_operations_v0( + 1 => self.add_new_contract_description_operations_v1( contract_id, owner_id, description, diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs similarity index 95% rename from packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs rename to packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs index c289b462411..1832d900218 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs @@ -15,7 +15,7 @@ use std::collections::{BTreeMap, HashMap}; impl Drive { /// Adds a contract description by inserting a new description subtree structure to the `Identities` subtree. - pub(super) fn add_new_contract_description_v0( + pub(super) fn add_new_contract_description_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -26,7 +26,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.add_new_contract_description_add_to_operations_v0( + self.add_new_contract_description_add_to_operations_v1( contract_id, owner_id, description, @@ -48,7 +48,7 @@ impl Drive { } /// Adds contract description creation operations to drive operations - pub(super) fn add_new_contract_description_add_to_operations_v0( + pub(super) fn add_new_contract_description_add_to_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -85,7 +85,7 @@ impl Drive { } /// The operations needed to create a description - pub(crate) fn add_new_contract_description_operations_v0( + pub(crate) fn add_new_contract_description_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -104,7 +104,7 @@ impl Drive { let short_description_document_type = contract.document_type_for_name("shortDescription")?; - let short_description_document = self.build_contract_description_document_owned_v0( + let short_description_document = self.build_contract_description_document_owned_v1( contract_id, owner_id, description, @@ -134,7 +134,7 @@ impl Drive { if !short_only { let full_description_document_type = contract.document_type_for_name("fullDescription")?; - let full_description_document = self.build_contract_description_document_owned_v0( + let full_description_document = self.build_contract_description_document_owned_v1( contract_id, owner_id, description, @@ -163,7 +163,7 @@ impl Drive { Ok(operations) } - pub(super) fn build_contract_description_document_owned_v0( + pub(super) fn build_contract_description_document_owned_v1( &self, contract_id: Identifier, owner_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index 1e0aad9be1c..b1dfba41474 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -11,7 +11,7 @@ use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -mod v0; +mod v1; impl Drive { /// Adds keywords to the state. @@ -35,7 +35,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 1 => self.add_new_contract_keywords_v0( + 1 => self.add_new_contract_keywords_v1( contract_id, owner_id, keywords, @@ -74,7 +74,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 1 => self.add_new_contract_keywords_add_to_operations_v0( + 1 => self.add_new_contract_keywords_add_to_operations_v1( contract_id, owner_id, keywords, @@ -115,7 +115,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 1 => self.add_new_contract_keywords_operations_v0( + 1 => self.add_new_contract_keywords_operations_v1( contract_id, owner_id, keywords, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs similarity index 94% rename from packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs rename to packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs index 6ba29acdabb..40506ed99dc 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs @@ -15,7 +15,7 @@ use std::collections::{BTreeMap, HashMap}; impl Drive { /// Adds a keyword by inserting a new keyword subtree structure to the `Identities` subtree. - pub(super) fn add_new_contract_keywords_v0( + pub(super) fn add_new_contract_keywords_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -26,7 +26,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.add_new_contract_keywords_add_to_operations_v0( + self.add_new_contract_keywords_add_to_operations_v1( contract_id, owner_id, keywords, @@ -48,7 +48,7 @@ impl Drive { } /// Adds keyword creation operations to drive operations - pub(super) fn add_new_contract_keywords_add_to_operations_v0( + pub(super) fn add_new_contract_keywords_add_to_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -85,7 +85,7 @@ impl Drive { } /// The operations needed to create a keyword - pub(crate) fn add_new_contract_keywords_operations_v0( + pub(crate) fn add_new_contract_keywords_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -103,7 +103,7 @@ impl Drive { let document_type = contract.document_type_for_name("contractKeywords")?; for (i, keyword) in keywords.iter().enumerate() { - let document = self.build_contract_keyword_document_owned_v0( + let document = self.build_contract_keyword_document_owned_v1( contract_id, owner_id, keyword, @@ -134,7 +134,7 @@ impl Drive { Ok(operations) } - pub(super) fn build_contract_keyword_document_owned_v0( + pub(super) fn build_contract_keyword_document_owned_v1( &self, contract_id: Identifier, owner_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs index f439d126547..57263f111b2 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs @@ -20,7 +20,9 @@ use grovedb::batch::KeyInfoPath; use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; +#[allow(clippy::too_many_arguments)] mod update_description; +#[allow(clippy::too_many_arguments)] mod update_keywords; impl Drive { diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs index 951628bd2ca..1067f12923f 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs @@ -35,7 +35,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", ))), - 1 => self.update_contract_description_v0( + 1 => self.update_contract_description_v1( contract_id, owner_id, description, @@ -74,7 +74,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", ))), - 1 => self.update_contract_description_add_to_operations_v0( + 1 => self.update_contract_description_add_to_operations_v1( contract_id, owner_id, description, @@ -115,7 +115,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", ))), - 1 => self.update_contract_description_operations_v0( + 1 => self.update_contract_description_operations_v1( contract_id, owner_id, description, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs index 12343d27793..7a1f060b70b 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; impl Drive { /// Adds operations for updating a contract description and returns the fee result. - pub(super) fn update_contract_description_v0( + pub(super) fn update_contract_description_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -29,7 +29,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.update_contract_description_add_to_operations_v0( + self.update_contract_description_add_to_operations_v1( contract_id, owner_id, description, @@ -51,7 +51,7 @@ impl Drive { } /// Adds contract description update operations to drive operations - pub(super) fn update_contract_description_add_to_operations_v0( + pub(super) fn update_contract_description_add_to_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -88,7 +88,7 @@ impl Drive { } /// The operations needed to update a contract description - pub(super) fn update_contract_description_operations_v0( + pub(super) fn update_contract_description_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -133,7 +133,7 @@ impl Drive { if existing_documents.is_empty() { // Add the new one - operations.extend(self.add_new_contract_description_operations_v0( + operations.extend(self.add_new_contract_description_operations_v1( contract_id, owner_id, description, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs index b0da89d7ee6..389695e2bc6 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs @@ -35,7 +35,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 1 => self.update_contract_keywords_v0( + 1 => self.update_contract_keywords_v1( contract_id, owner_id, keywords, @@ -74,7 +74,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 1 => self.update_contract_keywords_add_to_operations_v0( + 1 => self.update_contract_keywords_add_to_operations_v1( contract_id, owner_id, keywords, @@ -115,7 +115,7 @@ impl Drive { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", ))), - 1 => self.update_contract_keywords_operations_v0( + 1 => self.update_contract_keywords_operations_v1( contract_id, owner_id, keywords, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs index 5dab58aab35..47b7e03c41a 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs @@ -12,11 +12,11 @@ use dpp::platform_value::Value; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use platform_version::version::PlatformVersion; -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; impl Drive { /// Adds operations for updating keywords and returns the fee result. - pub(super) fn update_contract_keywords_v0( + pub(super) fn update_contract_keywords_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -27,7 +27,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.update_contract_keywords_add_to_operations_v0( + self.update_contract_keywords_add_to_operations_v1( contract_id, owner_id, keywords, @@ -49,7 +49,7 @@ impl Drive { } /// Adds keyword update operations to drive operations - pub(super) fn update_contract_keywords_add_to_operations_v0( + pub(super) fn update_contract_keywords_add_to_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -87,7 +87,7 @@ impl Drive { /// The operations needed to update the keywords search contract documents /// First we delete the existing keywords then we add the new ones - pub(super) fn update_contract_keywords_operations_v0( + pub(super) fn update_contract_keywords_operations_v1( &self, contract_id: Identifier, owner_id: Identifier, @@ -137,7 +137,7 @@ impl Drive { } // Then add the new ones - operations.extend(self.add_new_contract_keywords_operations_v0( + operations.extend(self.add_new_contract_keywords_operations_v1( contract_id, owner_id, keywords, From 830d892d4a525b7476ec219523f5065be6a0587a Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 15:00:53 +0700 Subject: [PATCH 26/46] add validation for update --- .../methods/validate_update/v0/mod.rs | 152 +++++++++++------- .../data_contract/duplicate_keywords_error.rs | 13 +- .../invalid_description_length_error.rs | 13 +- .../invalid_keyword_length_error.rs | 13 +- .../data_contract/keywords_over_limit.rs | 15 +- .../state_transition/processor/v0/mod.rs | 4 +- .../advanced_structure/v0/mod.rs | 9 +- .../data_contract_update/mod.rs | 2 +- 8 files changed, 134 insertions(+), 87 deletions(-) diff --git a/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs b/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs index d49f0a9e89e..ddd0ff66da5 100644 --- a/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs @@ -1,7 +1,10 @@ +use std::collections::HashSet; + use crate::data_contract::accessors::v0::DataContractV0Getters; use crate::consensus::basic::data_contract::{ - IncompatibleDataContractSchemaError, InvalidDataContractVersionError, + DuplicateKeywordsError, IncompatibleDataContractSchemaError, InvalidDataContractVersionError, + InvalidDescriptionLengthError, InvalidKeywordLengthError, TooManyKeywordsError, }; use crate::consensus::state::data_contract::data_contract_update_action_not_allowed_error::DataContractUpdateActionNotAllowedError; use crate::consensus::state::data_contract::data_contract_update_permission_error::DataContractUpdatePermissionError; @@ -166,84 +169,123 @@ impl DataContract { return Ok(SimpleConsensusValidationResult::new_with_errors(errors)); } } + } + + if self.groups() != new_data_contract.groups() { + // No groups can have been removed + for old_group_position in self.groups().keys() { + if !new_data_contract.groups().contains_key(old_group_position) { + return Ok(SimpleConsensusValidationResult::new_with_error( + DataContractUpdateActionNotAllowedError::new( + self.id(), + "remove group".to_string(), + ) + .into(), + )); + } + } - if self.groups() != new_data_contract.groups() { - // No groups can have been removed - for old_group_position in self.groups().keys() { - if !new_data_contract.groups().contains_key(old_group_position) { + // Ensure no group has been changed + for (old_group_position, old_group) in self.groups() { + if let Some(new_group) = new_data_contract.groups().get(old_group_position) { + if old_group != new_group { return Ok(SimpleConsensusValidationResult::new_with_error( DataContractUpdateActionNotAllowedError::new( self.id(), - "remove group".to_string(), + format!( + "change group at position {} is not allowed", + old_group_position + ), ) .into(), )); } } + } - // Ensure no group has been changed - for (old_group_position, old_group) in self.groups() { - if let Some(new_group) = new_data_contract.groups().get(old_group_position) { - if old_group != new_group { - return Ok(SimpleConsensusValidationResult::new_with_error( - DataContractUpdateActionNotAllowedError::new( - self.id(), - format!( - "change group at position {} is not allowed", - old_group_position - ), - ) - .into(), - )); - } - } - } + let valid = + DataContract::validate_groups(new_data_contract.groups(), platform_version)?; + if !valid.is_valid() { + return Ok(valid); + } + } - let valid = - DataContract::validate_groups(new_data_contract.groups(), platform_version)?; - if !valid.is_valid() { - return Ok(valid); + if self.tokens() != new_data_contract.tokens() { + for (token_position, old_token_config) in self.tokens() { + // Check if a token has been removed + if !new_data_contract.tokens().contains_key(token_position) { + return Ok(SimpleConsensusValidationResult::new_with_error( + DataContractUpdateActionNotAllowedError::new( + self.id(), + format!("remove token at position {}", token_position), + ) + .into(), + )); } - } - if self.tokens() != new_data_contract.tokens() { - for (token_position, old_token_config) in self.tokens() { - // Check if a token has been removed - if !new_data_contract.tokens().contains_key(token_position) { + // Check if a token configuration has been changed + if let Some(new_token_config) = new_data_contract.tokens().get(token_position) { + if old_token_config != new_token_config { return Ok(SimpleConsensusValidationResult::new_with_error( DataContractUpdateActionNotAllowedError::new( self.id(), - format!("remove token at position {}", token_position), + format!("update token at position {}", token_position), ) .into(), )); } + } + } - // Check if a token configuration has been changed - if let Some(new_token_config) = new_data_contract.tokens().get(token_position) { - if old_token_config != new_token_config { - return Ok(SimpleConsensusValidationResult::new_with_error( - DataContractUpdateActionNotAllowedError::new( - self.id(), - format!("update token at position {}", token_position), - ) - .into(), - )); - } - } + // Check if a token has been added + for token_position in new_data_contract.tokens().keys() { + if !self.tokens().contains_key(token_position) { + return Ok(SimpleConsensusValidationResult::new_with_error( + DataContractUpdateActionNotAllowedError::new( + self.id(), + format!("add token at position {}", token_position), + ) + .into(), + )); + } + } + } + + if self.keywords() != new_data_contract.keywords() { + // Validate there are no more than 20 keywords + if new_data_contract.keywords().len() > 20 { + return Ok(SimpleConsensusValidationResult::new_with_error( + TooManyKeywordsError::new(self.id(), self.keywords().len() as u8).into(), + )); + } + + // Validate the keywords are all unique and between 3 and 50 characters + let mut seen_keywords = HashSet::new(); + for keyword in new_data_contract.keywords() { + // First check keyword length + if keyword.len() < 3 || keyword.len() > 50 { + return Ok(SimpleConsensusValidationResult::new_with_error( + InvalidKeywordLengthError::new(self.id(), keyword.to_string()).into(), + )); } - // Check if a token has been added - for token_position in new_data_contract.tokens().keys() { - if !self.tokens().contains_key(token_position) { - return Ok(SimpleConsensusValidationResult::new_with_error( - DataContractUpdateActionNotAllowedError::new( - self.id(), - format!("add token at position {}", token_position), - ) + // Then check uniqueness + if !seen_keywords.insert(keyword) { + return Ok(SimpleConsensusValidationResult::new_with_error( + DuplicateKeywordsError::new(self.id(), keyword.to_string()).into(), + )); + } + } + } + + if self.description() != new_data_contract.description() { + // Validate the description is between 3 and 100 characters + if let Some(description) = new_data_contract.description() { + if !(description.len() >= 3 && description.len() <= 100) { + return Ok(SimpleConsensusValidationResult::new_with_error( + InvalidDescriptionLengthError::new(self.id(), description.to_string()) .into(), - )); - } + )); } } } diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs index d35591a6fc6..c84d918cf36 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_keywords_error.rs @@ -3,12 +3,13 @@ use crate::consensus::ConsensusError; use crate::errors::ProtocolError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; use thiserror::Error; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Data contract {contract_id} has duplicated keyword '{keyword}'.")] +#[error("Data contract {data_contract_id} has duplicated keyword '{keyword}'.")] #[platform_serialize(unversioned)] pub struct DuplicateKeywordsError { /* @@ -16,20 +17,20 @@ pub struct DuplicateKeywordsError { DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION */ - contract_id: String, + data_contract_id: Identifier, keyword: String, } impl DuplicateKeywordsError { - pub fn new(contract_id: String, keyword: String) -> Self { + pub fn new(data_contract_id: Identifier, keyword: String) -> Self { Self { - contract_id, + data_contract_id, keyword, } } - pub fn contract_id(&self) -> &str { - &self.contract_id + pub fn data_contract_id(&self) -> &Identifier { + &self.data_contract_id } pub fn keyword(&self) -> &str { diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs index 7d8c04788a5..5554da1ac4e 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_description_length_error.rs @@ -3,12 +3,13 @@ use crate::consensus::ConsensusError; use crate::errors::ProtocolError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; use thiserror::Error; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Data contract {} has description with invalid length: '{}'. Valid length is between 3 and 100 characters.", contract_id, description.len())] +#[error("Data contract {} has description with invalid length: '{}'. Valid length is between 3 and 100 characters.", data_contract_id, description.len())] #[platform_serialize(unversioned)] pub struct InvalidDescriptionLengthError { /* @@ -16,20 +17,20 @@ pub struct InvalidDescriptionLengthError { DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION */ - contract_id: String, + data_contract_id: Identifier, description: String, } impl InvalidDescriptionLengthError { - pub fn new(contract_id: String, description: String) -> Self { + pub fn new(data_contract_id: Identifier, description: String) -> Self { Self { - contract_id, + data_contract_id, description, } } - pub fn contract_id(&self) -> &str { - &self.contract_id + pub fn data_contract_id(&self) -> &Identifier { + &self.data_contract_id } pub fn description(&self) -> &str { diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs index 9c9c8b8c52c..40988ef52ce 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_keyword_length_error.rs @@ -3,12 +3,13 @@ use crate::consensus::ConsensusError; use crate::errors::ProtocolError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; use thiserror::Error; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Data contract {contract_id} has keyword with invalid length: '{keyword}'. Valid length is between 3 and 50 characters.")] +#[error("Data contract {data_contract_id} has keyword with invalid length: '{keyword}'. Valid length is between 3 and 50 characters.")] #[platform_serialize(unversioned)] pub struct InvalidKeywordLengthError { /* @@ -16,20 +17,20 @@ pub struct InvalidKeywordLengthError { DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION */ - contract_id: String, + data_contract_id: Identifier, keyword: String, } impl InvalidKeywordLengthError { - pub fn new(contract_id: String, keyword: String) -> Self { + pub fn new(data_contract_id: Identifier, keyword: String) -> Self { Self { - contract_id, + data_contract_id, keyword, } } - pub fn contract_id(&self) -> &str { - &self.contract_id + pub fn data_contract_id(&self) -> &Identifier { + &self.data_contract_id } pub fn keyword(&self) -> &str { diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs index 36b069f7cbb..9fd590bc3c4 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/keywords_over_limit.rs @@ -3,12 +3,15 @@ use crate::consensus::ConsensusError; use crate::errors::ProtocolError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; use thiserror::Error; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Data contract {contract_id} has too many keywords: '{keywords_len}'. The maximum is 20.")] +#[error( + "Data contract {data_contract_id} has too many keywords: '{keywords_len}'. The maximum is 20." +)] #[platform_serialize(unversioned)] pub struct TooManyKeywordsError { /* @@ -16,20 +19,20 @@ pub struct TooManyKeywordsError { DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION */ - contract_id: String, + data_contract_id: Identifier, keywords_len: u8, } impl TooManyKeywordsError { - pub fn new(contract_id: String, keywords_len: u8) -> Self { + pub fn new(data_contract_id: Identifier, keywords_len: u8) -> Self { Self { - contract_id, + data_contract_id, keywords_len, } } - pub fn contract_id(&self) -> &str { - &self.contract_id + pub fn data_contract_id(&self) -> &Identifier { + &self.data_contract_id } pub fn keywords_len(&self) -> &u8 { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs index 12d7bdd4e06..80758a1b095 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs @@ -21,9 +21,9 @@ use drive::grovedb::TransactionArg; use drive::state_transition_action::StateTransitionAction; use std::collections::BTreeMap; -use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext}; +use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext; use crate::execution::validation::state_transition::common::validate_simple_pre_check_balance::ValidateSimplePreCheckBalance; -use crate::execution::validation::state_transition::common::validate_state_transition_identity_signed::{ValidateStateTransitionIdentitySignature}; +use crate::execution::validation::state_transition::common::validate_state_transition_identity_signed::ValidateStateTransitionIdentitySignature; use crate::execution::validation::state_transition::identity_create::{StateTransitionStateValidationForIdentityCreateTransitionV0, StateTransitionStructureKnownInStateValidationForIdentityCreateTransitionV0}; use crate::execution::validation::state_transition::identity_top_up::StateTransitionIdentityTopUpTransitionActionTransformer; use crate::execution::validation::state_transition::state_transitions::identity_update::advanced_structure::v0::IdentityUpdateStateTransitionIdentityAndSignaturesValidationV0; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs index 60029040eee..ca2f6c23dac 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs @@ -14,7 +14,6 @@ use dpp::consensus::basic::BasicError; use dpp::consensus::ConsensusError; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; use dpp::data_contract::{TokenContractPosition, INITIAL_DATA_CONTRACT_VERSION}; -use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::DataContract; use dpp::state_transition::data_contract_create_transition::accessors::DataContractCreateTransitionAccessorsV0; use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; @@ -163,7 +162,7 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 bump_action, vec![ConsensusError::BasicError( BasicError::TooManyKeywordsError(TooManyKeywordsError::new( - self.data_contract().id().to_string(Encoding::Base58), + self.data_contract().id(), self.data_contract().keywords().len() as u8, )), )], @@ -183,7 +182,7 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 bump_action, vec![ConsensusError::BasicError( BasicError::InvalidKeywordLengthError(InvalidKeywordLengthError::new( - self.data_contract().id().to_string(Encoding::Base58), + self.data_contract().id(), keyword.to_string(), )), )], @@ -200,7 +199,7 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 bump_action, vec![ConsensusError::BasicError( BasicError::DuplicateKeywordsError(DuplicateKeywordsError::new( - self.data_contract().id().to_string(Encoding::Base58), + self.data_contract().id(), keyword.to_string(), )), )], @@ -220,7 +219,7 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 vec![ConsensusError::BasicError( BasicError::InvalidDescriptionLengthError( InvalidDescriptionLengthError::new( - self.data_contract().id().to_string(Encoding::Base58), + self.data_contract().id(), description.to_string(), ), ), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index 5b7165e185e..3f8ebacf130 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -2194,7 +2194,7 @@ mod tests { invalid_update_test!( update_fails_description_too_long, - &"x".repeat(51), + &"x".repeat(101), BasicError::InvalidDescriptionLengthError(_) ); From 74522c0c3edc217fc6508e06c05f35d92cd19816 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 15:46:11 +0700 Subject: [PATCH 27/46] add unit tests for validate_update --- .../methods/validate_update/v0/mod.rs | 281 ++++++++++++++++++ 1 file changed, 281 insertions(+) diff --git a/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs b/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs index ddd0ff66da5..bdb31621753 100644 --- a/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs @@ -308,9 +308,22 @@ mod tests { use platform_value::Identifier; mod validate_update { + use std::collections::BTreeMap; + use super::*; use crate::data_contract::accessors::v0::DataContractV0Setters; + use crate::data_contract::accessors::v1::DataContractV1Setters; + use crate::data_contract::associated_token::token_configuration::accessors::v0::{ + TokenConfigurationV0Getters, TokenConfigurationV0Setters, + }; + use crate::data_contract::associated_token::token_configuration::v0::TokenConfigurationV0; use crate::data_contract::document_type::DocumentTypeMutRef; + use crate::data_contract::group::accessors::v0::{GroupV0Getters, GroupV0Setters}; + use crate::data_contract::group::v0::GroupV0; + use crate::data_contract::group::Group; + use crate::data_contract::TokenConfiguration; + use crate::identity::accessors::IdentityGettersV0; + use crate::prelude::Identity; #[test] fn should_return_invalid_result_if_owner_id_is_not_the_same() { @@ -527,5 +540,273 @@ mod tests { assert!(result.is_valid()); } + + // + // ────────────────────────────────────────────────────────────────────────── + // Group‑related rules + // ────────────────────────────────────────────────────────────────────────── + // + + #[test] + fn should_return_invalid_result_when_group_is_removed() { + let platform_version = PlatformVersion::latest(); + + let identity_1 = Identity::random_identity(3, Some(14), platform_version) + .expect("expected a platform identity"); + let identity_1_id = identity_1.id(); + let identity_2 = Identity::random_identity(3, Some(506), platform_version) + .expect("expected a platform identity"); + let identity_2_id = identity_2.id(); + + let mut old_data_contract = + get_data_contract_fixture(None, IdentityNonce::default(), 9).data_contract_owned(); + old_data_contract.set_groups(BTreeMap::from([( + 0, + Group::V0(GroupV0 { + members: [(identity_1_id, 1), (identity_2_id, 1)].into(), + required_power: 2, + }), + )])); + + // Clone & bump version + let mut new_data_contract = old_data_contract.clone(); + new_data_contract.set_version(old_data_contract.version() + 1); + + // Remove the first (and normally only) group + let first_group_pos = *old_data_contract + .groups() + .keys() + .next() + .expect("fixture must have at least one group"); + new_data_contract + .groups_mut() + .unwrap() + .remove(&first_group_pos); + + let result = old_data_contract + .validate_update_v0(&new_data_contract, platform_version) + .expect("failed validate update"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::StateError( + StateError::DataContractUpdateActionNotAllowedError(e) + )] if e.action() == "remove group" + ); + } + + #[test] + fn should_return_invalid_result_when_group_is_changed() { + let platform_version = PlatformVersion::latest(); + + let identity_1 = Identity::random_identity(3, Some(14), platform_version) + .expect("expected a platform identity"); + let identity_1_id = identity_1.id(); + let identity_2 = Identity::random_identity(3, Some(506), platform_version) + .expect("expected a platform identity"); + let identity_2_id = identity_2.id(); + + let mut old_data_contract = + get_data_contract_fixture(None, IdentityNonce::default(), 9).data_contract_owned(); + old_data_contract.set_groups(BTreeMap::from([( + 0, + Group::V0(GroupV0 { + members: [(identity_1_id, 1), (identity_2_id, 1)].into(), + required_power: 2, + }), + )])); + + // Clone & bump version + let mut new_data_contract = old_data_contract.clone(); + new_data_contract.set_version(old_data_contract.version() + 1); + + // Mutate the first group in some trivial way so that + // `old_group != new_group` evaluates to true. + let first_group_pos = *new_data_contract + .groups() + .keys() + .next() + .expect("fixture must have at least one group"); + let mut altered_group = new_data_contract + .groups() + .get(&first_group_pos) + .cloned() + .expect("group must exist"); + // Tweak required power + altered_group.set_required_power(altered_group.required_power() + 1); + new_data_contract + .groups_mut() + .unwrap() + .insert(first_group_pos, altered_group); + + let result = old_data_contract + .validate_update_v0(&new_data_contract, platform_version) + .expect("failed validate update"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::StateError( + StateError::DataContractUpdateActionNotAllowedError(e) + )] if e.action() == format!( + "change group at position {} is not allowed", + first_group_pos + ) + ); + } + + // + // ────────────────────────────────────────────────────────────────────────── + // Token‑related rules + // ────────────────────────────────────────────────────────────────────────── + // + + #[test] + fn should_return_invalid_result_when_token_is_removed() { + let platform_version = PlatformVersion::latest(); + + let mut old_data_contract = + get_data_contract_fixture(None, IdentityNonce::default(), 9).data_contract_owned(); + old_data_contract.set_tokens(BTreeMap::from([( + 0, + TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), + )])); + + let mut new_data_contract = old_data_contract.clone(); + new_data_contract.set_version(old_data_contract.version() + 1); + + // Remove an existing token + let first_token_pos = *old_data_contract + .tokens() + .keys() + .next() + .expect("fixture must have at least one token"); + new_data_contract + .tokens_mut() + .unwrap() + .remove(&first_token_pos); + + let result = old_data_contract + .validate_update_v0(&new_data_contract, platform_version) + .expect("failed validate update"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::StateError( + StateError::DataContractUpdateActionNotAllowedError(e) + )] if e.action() == format!("remove token at position {}", first_token_pos) + ); + } + + #[test] + fn should_return_invalid_result_when_token_is_updated() { + let platform_version = PlatformVersion::latest(); + + let mut old_data_contract = + get_data_contract_fixture(None, IdentityNonce::default(), 9).data_contract_owned(); + old_data_contract.set_tokens(BTreeMap::from([( + 0, + TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), + )])); + + let mut new_data_contract = old_data_contract.clone(); + new_data_contract.set_version(old_data_contract.version() + 1); + + // Modify an existing token configuration + let first_token_pos = *new_data_contract + .tokens() + .keys() + .next() + .expect("fixture must have at least one token"); + let mut altered_token_cfg = new_data_contract + .tokens() + .get(&first_token_pos) + .cloned() + .expect("token must exist"); + // Tweak base supply + altered_token_cfg.set_base_supply(altered_token_cfg.base_supply() + 1); + new_data_contract + .tokens_mut() + .unwrap() + .insert(first_token_pos, altered_token_cfg); + + let result = old_data_contract + .validate_update_v0(&new_data_contract, platform_version) + .expect("failed validate update"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::StateError( + StateError::DataContractUpdateActionNotAllowedError(e) + )] if e.action() == format!("update token at position {}", first_token_pos) + ); + } + + #[test] + fn should_return_invalid_result_when_new_token_is_added() { + let platform_version = PlatformVersion::latest(); + + let mut old_data_contract = + get_data_contract_fixture(None, IdentityNonce::default(), 9).data_contract_owned(); + old_data_contract.set_tokens(BTreeMap::from([( + 0, + TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()), + )])); + + let mut new_data_contract = old_data_contract.clone(); + new_data_contract.set_version(old_data_contract.version() + 1); + + // Create a new token by cloning an existing config but + // inserting it at an unused position. + let existing_cfg = new_data_contract + .tokens() + .values() + .next() + .expect("fixture must have at least one token") + .clone(); + let new_position = old_data_contract + .tokens() + .keys() + .max() + .expect("fixture must have at least one token") + + 1; + new_data_contract + .tokens_mut() + .unwrap() + .insert(new_position, existing_cfg); + + let result = old_data_contract + .validate_update_v0(&new_data_contract, platform_version) + .expect("failed validate update"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::StateError( + StateError::DataContractUpdateActionNotAllowedError(e) + )] if e.action() == format!("add token at position {}", new_position) + ); + } + + // + // ────────────────────────────────────────────────────────────────────────── + // Happy‑path check: no token / group changes + // ────────────────────────────────────────────────────────────────────────── + // + + #[test] + fn should_pass_when_groups_and_tokens_unchanged() { + let platform_version = PlatformVersion::latest(); + + let old_data_contract = + get_data_contract_fixture(None, IdentityNonce::default(), 9).data_contract_owned(); + + let mut new_data_contract = old_data_contract.clone(); + new_data_contract.set_version(old_data_contract.version() + 1); + + let result = old_data_contract + .validate_update_v0(&new_data_contract, platform_version) + .expect("failed validate update"); + + assert!(result.is_valid()); + } } } From 97d2889b7aa70d5d5c65fa6bb7efcea003c1f028 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 15:56:37 +0700 Subject: [PATCH 28/46] fix: remove dist timestamp validation for contract updates --- .../data_contract_update/state/v0/mod.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs index 7f97d3a8f4b..cf08f7b0d8b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs @@ -73,25 +73,6 @@ impl DataContractUpdateStateTransitionStateValidationV0 for DataContractUpdateTr return Ok(action); } - // Validate token distribution rules - for (position, config) in self.data_contract().tokens() { - if let Some(distribution) = config.distribution_rules().pre_programmed_distribution() { - if let Some((timestamp, _)) = distribution.distributions().iter().next() { - if timestamp < &block_info.time_ms { - return Ok(ConsensusValidationResult::new_with_data_and_errors( - StateTransitionAction::BumpIdentityDataContractNonceAction( - BumpIdentityDataContractNonceAction::from_borrowed_data_contract_update_transition(self), - ), - vec![StateError::PreProgrammedDistributionTimestampInPastError( - PreProgrammedDistributionTimestampInPastError::new(self.data_contract().id(), *position, *timestamp, block_info.time_ms), - ) - .into()], - )); - } - } - } - } - let state_transition_action = action.data.as_mut().ok_or(Error::Execution( ExecutionError::CorruptedCodeExecution( "we should always have an action at this point in data contract update", From 272ef8a0df91c92c91b8edb73367f7be4197f8b6 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 16:03:58 +0700 Subject: [PATCH 29/46] fix version --- .../update/update_contract/v1/update_description/mod.rs | 4 ++-- .../contract/update/update_contract/v1/update_keywords/mod.rs | 4 ++-- packages/rs-platform-version/src/version/v9.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs index 1067f12923f..6e381902bda 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs @@ -29,8 +29,8 @@ impl Drive { .drive .methods .contract - .insert - .insert_contract + .update + .update_contract { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract descriptions are not supported in this version", diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs index 389695e2bc6..cfb6624e55a 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs @@ -68,8 +68,8 @@ impl Drive { .drive .methods .contract - .insert - .insert_contract + .update + .update_contract { 0 => Err(Error::Drive(DriveError::NotSupported( "Contract keywords are not supported in this version", diff --git a/packages/rs-platform-version/src/version/v9.rs b/packages/rs-platform-version/src/version/v9.rs index e8713306d2f..e6fa79d2656 100644 --- a/packages/rs-platform-version/src/version/v9.rs +++ b/packages/rs-platform-version/src/version/v9.rs @@ -33,7 +33,7 @@ pub const PROTOCOL_VERSION_9: ProtocolVersion = 9; //todo: make changes pub const PLATFORM_V9: PlatformVersion = PlatformVersion { protocol_version: PROTOCOL_VERSION_9, - drive: DRIVE_VERSION_V4, // changed (for data contract insert) + drive: DRIVE_VERSION_V4, // changed (for data contract insert and update) drive_abci: DriveAbciVersion { structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, methods: DRIVE_ABCI_METHOD_VERSIONS_V6, // changed because of the genesis state From 8547e499fe058a3fa62b1b9a3cb454381bf997d0 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 16:07:24 +0700 Subject: [PATCH 30/46] remove unused imports --- .../state_transitions/data_contract_update/state/v0/mod.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs index cf08f7b0d8b..888e7135fca 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs @@ -5,17 +5,11 @@ use dpp::block::block_info::BlockInfo; use dpp::consensus::basic::document::DataContractNotPresentError; use dpp::consensus::basic::BasicError; -use dpp::consensus::state::state_error::StateError; -use dpp::consensus::state::token::PreProgrammedDistributionTimestampInPastError; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::accessors::v1::{DataContractV1Getters, DataContractV1Setters}; -use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; -use dpp::data_contract::associated_token::token_distribution_rules::accessors::v0::TokenDistributionRulesV0Getters; -use dpp::data_contract::associated_token::token_pre_programmed_distribution::accessors::v0::TokenPreProgrammedDistributionV0Methods; use dpp::data_contract::validate_update::DataContractUpdateValidationMethodsV0; use dpp::prelude::ConsensusValidationResult; -use dpp::state_transition::data_contract_update_transition::accessors::DataContractUpdateTransitionAccessorsV0; use dpp::state_transition::data_contract_update_transition::DataContractUpdateTransition; use dpp::version::PlatformVersion; use dpp::ProtocolError; From 8d25e071954434a877cf11d7a1c590bea4866873 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 17:23:38 +0700 Subject: [PATCH 31/46] function descriptions --- .../src/drive/contract/insert/add_description/mod.rs | 9 ++++++--- .../drive/contract/insert/add_description/v1/mod.rs | 12 ++++++++---- .../drive/contract/insert/add_new_keywords/mod.rs | 9 ++++++--- .../drive/contract/insert/add_new_keywords/v1/mod.rs | 12 ++++++++---- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs index 9839fb75285..5b179a9fa35 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs @@ -14,7 +14,8 @@ use std::collections::HashMap; mod v1; impl Drive { - /// Adds contract description to the state. + /// Creates the documents in the Keyword Search contract for the contract description and + /// returns the fee result pub fn add_new_contract_description( &self, contract_id: Identifier, @@ -52,7 +53,8 @@ impl Drive { } } - /// Adds contract description creation operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract description pub fn add_new_contract_description_add_to_operations( &self, contract_id: Identifier, @@ -92,7 +94,8 @@ impl Drive { } } - /// The operations needed to create a description + /// Creates and returns the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract description pub fn add_new_contract_description_operations( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs index 1832d900218..65181745dbd 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs @@ -14,7 +14,8 @@ use platform_version::version::PlatformVersion; use std::collections::{BTreeMap, HashMap}; impl Drive { - /// Adds a contract description by inserting a new description subtree structure to the `Identities` subtree. + /// Creates the documents in the Keyword Search contract for the contract description and + /// returns the fee result pub(super) fn add_new_contract_description_v1( &self, contract_id: Identifier, @@ -47,7 +48,8 @@ impl Drive { Ok(fees) } - /// Adds contract description creation operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract description pub(super) fn add_new_contract_description_add_to_operations_v1( &self, contract_id: Identifier, @@ -84,7 +86,8 @@ impl Drive { ) } - /// The operations needed to create a description + /// Creates and returns the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract description pub(crate) fn add_new_contract_description_operations_v1( &self, contract_id: Identifier, @@ -100,7 +103,7 @@ impl Drive { ) -> Result, Error> { let mut operations: Vec = vec![]; - let contract = self.cache.system_data_contracts.load_search(); + let contract = self.cache.system_data_contracts.load_keyword_search(); let short_description_document_type = contract.document_type_for_name("shortDescription")?; @@ -163,6 +166,7 @@ impl Drive { Ok(operations) } + /// Creates and returns a contract `description` document for the Keyword Search contract pub(super) fn build_contract_description_document_owned_v1( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index b1dfba41474..26425f07479 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -14,7 +14,8 @@ use std::collections::HashMap; mod v1; impl Drive { - /// Adds keywords to the state. + /// Creates the documents in the Keyword Search contract for the contract keywords and + /// returns the fee result pub fn add_new_contract_keywords( &self, contract_id: Identifier, @@ -52,7 +53,8 @@ impl Drive { } } - /// Adds keywords creation operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract keywords pub fn add_new_contract_keywords_add_to_operations( &self, contract_id: Identifier, @@ -92,7 +94,8 @@ impl Drive { } } - /// The operations needed to create keywords + /// Creates and returns the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract keywords pub fn add_new_contract_keywords_operations( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs index 40506ed99dc..6abea56a76e 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs @@ -14,7 +14,8 @@ use platform_version::version::PlatformVersion; use std::collections::{BTreeMap, HashMap}; impl Drive { - /// Adds a keyword by inserting a new keyword subtree structure to the `Identities` subtree. + /// Creates the documents in the Keyword Search contract for the contract keywords and + /// returns the fee result pub(super) fn add_new_contract_keywords_v1( &self, contract_id: Identifier, @@ -47,7 +48,8 @@ impl Drive { Ok(fees) } - /// Adds keyword creation operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract keywords pub(super) fn add_new_contract_keywords_add_to_operations_v1( &self, contract_id: Identifier, @@ -84,7 +86,8 @@ impl Drive { ) } - /// The operations needed to create a keyword + /// Creates and returns the LowLeveLDriveOperations needed to create + /// the documents in the Keyword Search contract for the contract keywords pub(crate) fn add_new_contract_keywords_operations_v1( &self, contract_id: Identifier, @@ -99,7 +102,7 @@ impl Drive { ) -> Result, Error> { let mut operations: Vec = vec![]; - let contract = self.cache.system_data_contracts.load_search(); + let contract = self.cache.system_data_contracts.load_keyword_search(); let document_type = contract.document_type_for_name("contractKeywords")?; for (i, keyword) in keywords.iter().enumerate() { @@ -134,6 +137,7 @@ impl Drive { Ok(operations) } + /// Creates and returns a `contractKeyword` document for the Keyword Search contract pub(super) fn build_contract_keyword_document_owned_v1( &self, contract_id: Identifier, From bc28170cd61691b0601f4a6acd0081cde2d146a6 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 17:30:16 +0700 Subject: [PATCH 32/46] rename to keyword search contract --- Cargo.lock | 22 +++++++++---------- Cargo.toml | 2 +- packages/data-contracts/Cargo.toml | 2 +- packages/data-contracts/src/error.rs | 8 +++---- packages/data-contracts/src/lib.rs | 20 +++++++++-------- .../.eslintrc | 0 .../.mocharc.yml | 0 .../Cargo.toml | 4 ++-- .../LICENSE | 0 .../README.md | 0 .../lib/systemIds.js | 0 .../package.json | 0 .../schema/v1/search-contract-documents.json | 0 .../src/error.rs | 0 .../src/lib.rs | 8 +++---- .../src/v1/mod.rs | 0 .../test/.eslintrc | 0 .../test/bootstrap.js | 0 .../test/unit/searchContract.spec.js | 0 .../create_genesis_state/v1/mod.rs | 4 ++-- .../v0/mod.rs | 2 +- .../batch/tests/document/creation.rs | 2 +- .../data_contract_create/mod.rs | 4 ++-- .../data_contract_update/mod.rs | 6 +++-- .../rs-drive/src/cache/system_contracts.rs | 10 ++++----- .../v1/update_description/v1/mod.rs | 6 ++++- .../v1/update_keywords/v1/mod.rs | 6 ++++- .../system_data_contract_versions/mod.rs | 2 +- .../system_data_contract_versions/v1.rs | 2 +- 29 files changed, 61 insertions(+), 49 deletions(-) rename packages/{search-contract => keyword-search-contract}/.eslintrc (100%) rename packages/{search-contract => keyword-search-contract}/.mocharc.yml (100%) rename packages/{search-contract => keyword-search-contract}/Cargo.toml (63%) rename packages/{search-contract => keyword-search-contract}/LICENSE (100%) rename packages/{search-contract => keyword-search-contract}/README.md (100%) rename packages/{search-contract => keyword-search-contract}/lib/systemIds.js (100%) rename packages/{search-contract => keyword-search-contract}/package.json (100%) rename packages/{search-contract => keyword-search-contract}/schema/v1/search-contract-documents.json (100%) rename packages/{search-contract => keyword-search-contract}/src/error.rs (100%) rename packages/{search-contract => keyword-search-contract}/src/lib.rs (79%) rename packages/{search-contract => keyword-search-contract}/src/v1/mod.rs (100%) rename packages/{search-contract => keyword-search-contract}/test/.eslintrc (100%) rename packages/{search-contract => keyword-search-contract}/test/bootstrap.js (100%) rename packages/{search-contract => keyword-search-contract}/test/unit/searchContract.spec.js (100%) diff --git a/Cargo.lock b/Cargo.lock index d24b2091467..82a07328f1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1323,10 +1323,10 @@ dependencies = [ "dashpay-contract", "dpns-contract", "feature-flags-contract", + "keyword-search-contract", "masternode-reward-shares-contract", "platform-value", "platform-version", - "search-contract", "serde_json", "thiserror 1.0.64", "token-history-contract", @@ -2833,6 +2833,16 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keyword-search-contract" +version = "2.0.0-dev.1" +dependencies = [ + "platform-value", + "platform-version", + "serde_json", + "thiserror 1.0.64", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -4297,16 +4307,6 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "search-contract" -version = "2.0.0-dev.1" -dependencies = [ - "platform-value", - "platform-version", - "serde_json", - "thiserror 1.0.64", -] - [[package]] name = "sec1" version = "0.7.3" diff --git a/Cargo.toml b/Cargo.toml index 92dca6d948d..067c42b542c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ members = [ "packages/check-features", "packages/wallet-utils-contract", "packages/token-history-contract", - "packages/search-contract" + "packages/keyword-search-contract" ] exclude = ["packages/wasm-sdk"] # This one is experimental and not ready for use diff --git a/packages/data-contracts/Cargo.toml b/packages/data-contracts/Cargo.toml index a7fbd72d40b..0c7818e4b91 100644 --- a/packages/data-contracts/Cargo.toml +++ b/packages/data-contracts/Cargo.toml @@ -18,4 +18,4 @@ feature-flags-contract = { path = "../feature-flags-contract" } platform-value = { path = "../rs-platform-value" } wallet-utils-contract = { path = "../wallet-utils-contract" } token-history-contract = { path = "../token-history-contract" } -search-contract = { path = "../search-contract" } +keyword-search-contract = { path = "../keyword-search-contract" } diff --git a/packages/data-contracts/src/error.rs b/packages/data-contracts/src/error.rs index 107823ab96c..9f82617bc18 100644 --- a/packages/data-contracts/src/error.rs +++ b/packages/data-contracts/src/error.rs @@ -137,10 +137,10 @@ impl From for Error { } } -impl From for Error { - fn from(e: search_contract::Error) -> Self { +impl From for Error { + fn from(e: keyword_search_contract::Error) -> Self { match e { - search_contract::Error::UnknownVersionMismatch { + keyword_search_contract::Error::UnknownVersionMismatch { method, known_versions, received, @@ -149,7 +149,7 @@ impl From for Error { known_versions, received, }, - search_contract::Error::InvalidSchemaJson(e) => Error::InvalidSchemaJson(e), + keyword_search_contract::Error::InvalidSchemaJson(e) => Error::InvalidSchemaJson(e), } } } diff --git a/packages/data-contracts/src/lib.rs b/packages/data-contracts/src/lib.rs index a95ab7340cc..bd7754cfef3 100644 --- a/packages/data-contracts/src/lib.rs +++ b/packages/data-contracts/src/lib.rs @@ -6,10 +6,10 @@ use crate::error::Error; pub use dashpay_contract; pub use dpns_contract; pub use feature_flags_contract; +pub use keyword_search_contract; pub use masternode_reward_shares_contract; use platform_value::Identifier; use platform_version::version::PlatformVersion; -pub use search_contract; pub use token_history_contract; pub use wallet_utils_contract; pub use withdrawals_contract; @@ -24,7 +24,7 @@ pub enum SystemDataContract { Dashpay = 4, WalletUtils = 5, TokenHistory = 6, - Search = 7, + KeywordSearch = 7, } pub struct DataContractSource { @@ -45,7 +45,7 @@ impl SystemDataContract { SystemDataContract::Dashpay => dashpay_contract::ID_BYTES, SystemDataContract::WalletUtils => wallet_utils_contract::ID_BYTES, SystemDataContract::TokenHistory => token_history_contract::ID_BYTES, - SystemDataContract::Search => search_contract::ID_BYTES, + SystemDataContract::KeywordSearch => keyword_search_contract::ID_BYTES, }; Identifier::new(bytes) } @@ -105,12 +105,14 @@ impl SystemDataContract { definitions: token_history_contract::load_definitions(platform_version)?, document_schemas: token_history_contract::load_documents_schemas(platform_version)?, }, - SystemDataContract::Search => DataContractSource { - id_bytes: search_contract::ID_BYTES, - owner_id_bytes: search_contract::OWNER_ID_BYTES, - version: platform_version.system_data_contracts.search as u32, - definitions: search_contract::load_definitions(platform_version)?, - document_schemas: search_contract::load_documents_schemas(platform_version)?, + SystemDataContract::KeywordSearch => DataContractSource { + id_bytes: keyword_search_contract::ID_BYTES, + owner_id_bytes: keyword_search_contract::OWNER_ID_BYTES, + version: platform_version.system_data_contracts.keyword_search as u32, + definitions: keyword_search_contract::load_definitions(platform_version)?, + document_schemas: keyword_search_contract::load_documents_schemas( + platform_version, + )?, }, }; diff --git a/packages/search-contract/.eslintrc b/packages/keyword-search-contract/.eslintrc similarity index 100% rename from packages/search-contract/.eslintrc rename to packages/keyword-search-contract/.eslintrc diff --git a/packages/search-contract/.mocharc.yml b/packages/keyword-search-contract/.mocharc.yml similarity index 100% rename from packages/search-contract/.mocharc.yml rename to packages/keyword-search-contract/.mocharc.yml diff --git a/packages/search-contract/Cargo.toml b/packages/keyword-search-contract/Cargo.toml similarity index 63% rename from packages/search-contract/Cargo.toml rename to packages/keyword-search-contract/Cargo.toml index 5d33b3db642..0f36f9b17ac 100644 --- a/packages/search-contract/Cargo.toml +++ b/packages/keyword-search-contract/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "search-contract" -description = "Search data contract schema and tools. Search contract is used to find other contracts and tokens" +name = "keyword-search-contract" +description = "Search data contract schema and tools. Keyword Search contract is used to find other contracts and tokens" version = "2.0.0-dev.1" edition = "2021" rust-version.workspace = true diff --git a/packages/search-contract/LICENSE b/packages/keyword-search-contract/LICENSE similarity index 100% rename from packages/search-contract/LICENSE rename to packages/keyword-search-contract/LICENSE diff --git a/packages/search-contract/README.md b/packages/keyword-search-contract/README.md similarity index 100% rename from packages/search-contract/README.md rename to packages/keyword-search-contract/README.md diff --git a/packages/search-contract/lib/systemIds.js b/packages/keyword-search-contract/lib/systemIds.js similarity index 100% rename from packages/search-contract/lib/systemIds.js rename to packages/keyword-search-contract/lib/systemIds.js diff --git a/packages/search-contract/package.json b/packages/keyword-search-contract/package.json similarity index 100% rename from packages/search-contract/package.json rename to packages/keyword-search-contract/package.json diff --git a/packages/search-contract/schema/v1/search-contract-documents.json b/packages/keyword-search-contract/schema/v1/search-contract-documents.json similarity index 100% rename from packages/search-contract/schema/v1/search-contract-documents.json rename to packages/keyword-search-contract/schema/v1/search-contract-documents.json diff --git a/packages/search-contract/src/error.rs b/packages/keyword-search-contract/src/error.rs similarity index 100% rename from packages/search-contract/src/error.rs rename to packages/keyword-search-contract/src/error.rs diff --git a/packages/search-contract/src/lib.rs b/packages/keyword-search-contract/src/lib.rs similarity index 79% rename from packages/search-contract/src/lib.rs rename to packages/keyword-search-contract/src/lib.rs index 47c5cb9816f..e074d139c7f 100644 --- a/packages/search-contract/src/lib.rs +++ b/packages/keyword-search-contract/src/lib.rs @@ -16,20 +16,20 @@ pub const OWNER_ID_BYTES: [u8; 32] = [0; 32]; pub const ID: Identifier = Identifier(IdentifierBytes32(ID_BYTES)); pub const OWNER_ID: Identifier = Identifier(IdentifierBytes32(OWNER_ID_BYTES)); pub fn load_definitions(platform_version: &PlatformVersion) -> Result, Error> { - match platform_version.system_data_contracts.search { + match platform_version.system_data_contracts.keyword_search { 1 => Ok(None), version => Err(Error::UnknownVersionMismatch { - method: "search_contract::load_definitions".to_string(), + method: "keyword_search_contract::load_definitions".to_string(), known_versions: vec![1], received: version, }), } } pub fn load_documents_schemas(platform_version: &PlatformVersion) -> Result { - match platform_version.system_data_contracts.search { + match platform_version.system_data_contracts.keyword_search { 1 => v1::load_documents_schemas(), version => Err(Error::UnknownVersionMismatch { - method: "search_contract::load_documents_schemas".to_string(), + method: "keyword_search_contract::load_documents_schemas".to_string(), known_versions: vec![1], received: version, }), diff --git a/packages/search-contract/src/v1/mod.rs b/packages/keyword-search-contract/src/v1/mod.rs similarity index 100% rename from packages/search-contract/src/v1/mod.rs rename to packages/keyword-search-contract/src/v1/mod.rs diff --git a/packages/search-contract/test/.eslintrc b/packages/keyword-search-contract/test/.eslintrc similarity index 100% rename from packages/search-contract/test/.eslintrc rename to packages/keyword-search-contract/test/.eslintrc diff --git a/packages/search-contract/test/bootstrap.js b/packages/keyword-search-contract/test/bootstrap.js similarity index 100% rename from packages/search-contract/test/bootstrap.js rename to packages/keyword-search-contract/test/bootstrap.js diff --git a/packages/search-contract/test/unit/searchContract.spec.js b/packages/keyword-search-contract/test/unit/searchContract.spec.js similarity index 100% rename from packages/search-contract/test/unit/searchContract.spec.js rename to packages/keyword-search-contract/test/unit/searchContract.spec.js diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs index 725cef56a44..56083655c28 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs @@ -52,8 +52,8 @@ impl Platform { system_data_contracts.load_token_history(), ), ( - SystemDataContract::Search, - system_data_contracts.load_search(), + SystemDataContract::KeywordSearch, + system_data_contracts.load_keyword_search(), ), ]); //todo add Wallet Utils (maybe) 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 6422b858408..2f4791ccba3 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 @@ -487,7 +487,7 @@ impl Platform { )?; let search_contract = - load_system_data_contract(SystemDataContract::Search, platform_version)?; + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version)?; self.drive.insert_contract( &search_contract, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 0b3fb36f414..b2fdedf31bc 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -2488,7 +2488,7 @@ mod creation_tests { .expect("expected to get current platform version"); // Load the system Search contract - let search_contract = platform.drive.cache.system_data_contracts.load_search(); + let search_contract = platform.drive.cache.system_data_contracts.load_keyword_search(); platform .drive diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index 2a019870fd8..23c577931b0 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2895,7 +2895,7 @@ mod tests { // Now check the Search Contract has the keyword documents let search_contract = - load_system_data_contract(SystemDataContract::Search, PlatformVersion::latest()) + load_system_data_contract(SystemDataContract::KeywordSearch, PlatformVersion::latest()) .expect("expected to load search contract"); let document_type = search_contract .document_type_for_name("contractKeywords") @@ -3177,7 +3177,7 @@ mod tests { // Now check the Search Contract has the short and full description documents let search_contract = - load_system_data_contract(SystemDataContract::Search, PlatformVersion::latest()) + load_system_data_contract(SystemDataContract::KeywordSearch, PlatformVersion::latest()) .expect("expected to load search contract"); let short_description_document_type = search_contract .document_type_for_name("shortDescription") diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index 3f8ebacf130..a5f75636b9a 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -1726,7 +1726,8 @@ mod tests { platform_version: &PlatformVersion, ) -> Vec { let search_contract = - load_system_data_contract(SystemDataContract::Search, platform_version).unwrap(); + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .unwrap(); let doc_type = search_contract .document_type_for_name("contractKeywords") .unwrap(); @@ -2097,7 +2098,8 @@ mod tests { platform_version: &PlatformVersion, ) -> String { let search_contract = - load_system_data_contract(SystemDataContract::Search, platform_version).unwrap(); + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .unwrap(); let doc_type = search_contract .document_type_for_name("shortDescription") .unwrap(); diff --git a/packages/rs-drive/src/cache/system_contracts.rs b/packages/rs-drive/src/cache/system_contracts.rs index 3c1fd170143..870d757c47c 100644 --- a/packages/rs-drive/src/cache/system_contracts.rs +++ b/packages/rs-drive/src/cache/system_contracts.rs @@ -18,7 +18,7 @@ pub struct SystemDataContracts { /// Token history contract token_history: ArcSwap, /// Search contract - search: ArcSwap, + keyword_search: ArcSwap, } impl SystemDataContracts { @@ -47,8 +47,8 @@ impl SystemDataContracts { SystemDataContract::TokenHistory, platform_version, )?), - search: ArcSwap::from_pointee(load_system_data_contract( - SystemDataContract::Search, + keyword_search: ArcSwap::from_pointee(load_system_data_contract( + SystemDataContract::KeywordSearch, platform_version, )?), }) @@ -80,7 +80,7 @@ impl SystemDataContracts { } /// Returns the search contract - pub fn load_search(&self) -> Guard> { - self.search.load() + pub fn load_keyword_search(&self) -> Guard> { + self.keyword_search.load() } } diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs index 7a1f060b70b..0dfcf5fb2c4 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs @@ -102,7 +102,11 @@ impl Drive { ) -> Result, Error> { let mut operations: Vec = vec![]; - let contract = self.cache.system_data_contracts.load_search().clone(); + let contract = self + .cache + .system_data_contracts + .load_keyword_search() + .clone(); let document_type = contract.document_type_for_name("shortDescription")?; let mut query = DriveDocumentQuery::all_items_query(&contract, document_type, None); diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs index 47b7e03c41a..0de7077f3ca 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs @@ -102,7 +102,11 @@ impl Drive { let mut operations: Vec = vec![]; // First delete the existing keywords - let contract = self.cache.system_data_contracts.load_search().clone(); + let contract = self + .cache + .system_data_contracts + .load_keyword_search() + .clone(); let document_type = contract.document_type_for_name("contractKeywords")?; let mut query = DriveDocumentQuery::all_items_query(&contract, document_type, None); diff --git a/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs b/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs index 6da698cea2e..1630d740a4b 100644 --- a/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs +++ b/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs @@ -11,5 +11,5 @@ pub struct SystemDataContractVersions { pub feature_flags: FeatureVersion, pub wallet: FeatureVersion, pub token_history: FeatureVersion, - pub search: FeatureVersion, + pub keyword_search: FeatureVersion, } diff --git a/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs b/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs index 375ebe521b5..d136fd8e53e 100644 --- a/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs +++ b/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs @@ -9,5 +9,5 @@ pub const SYSTEM_DATA_CONTRACT_VERSIONS_V1: SystemDataContractVersions = feature_flags: 1, wallet: 1, token_history: 1, - search: 1, + keyword_search: 1, }; From e4003232493542b333635f5a51f6510d1088ba1d Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 17:51:24 +0700 Subject: [PATCH 33/46] fix rename --- Dockerfile | 10 +++++----- ...nts.json => keyword-search-contract-documents.json} | 0 packages/keyword-search-contract/src/v1/mod.rs | 2 +- .../test/unit/searchContract.spec.js | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) rename packages/keyword-search-contract/schema/v1/{search-contract-documents.json => keyword-search-contract-documents.json} (100%) diff --git a/Dockerfile b/Dockerfile index b5fb55bfd85..c0411248e73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -380,7 +380,7 @@ COPY --parents \ packages/dpns-contract \ packages/wallet-utils-contract \ packages/token-history-contract \ - packages/search-contract \ + packages/keyword-search-contract \ packages/data-contracts \ packages/strategy-tests \ packages/simple-signer \ @@ -456,7 +456,7 @@ COPY --parents \ packages/dashpay-contract \ packages/wallet-utils-contract \ packages/token-history-contract \ - packages/search-contract \ + packages/keyword-search-contract \ packages/withdrawals-contract \ packages/masternode-reward-shares-contract \ packages/feature-flags-contract \ @@ -553,7 +553,7 @@ COPY --parents \ packages/withdrawals-contract \ packages/wallet-utils-contract \ packages/token-history-contract \ - packages/search-contract \ + packages/keyword-search-contract \ packages/masternode-reward-shares-contract \ packages/feature-flags-contract \ packages/dpns-contract \ @@ -677,7 +677,7 @@ COPY --from=build-dashmate-helper /platform/packages/dapi-grpc packages/dapi-grp COPY --from=build-dashmate-helper /platform/packages/dash-spv packages/dash-spv COPY --from=build-dashmate-helper /platform/packages/wallet-utils-contract packages/wallet-utils-contract COPY --from=build-dashmate-helper /platform/packages/token-history-contract packages/token-history-contract -COPY --from=build-dashmate-helper /platform/packages/search-contract packages/search-contract +COPY --from=build-dashmate-helper /platform/packages/keyword-search-contract packages/keyword-search-contract COPY --from=build-dashmate-helper /platform/packages/withdrawals-contract packages/withdrawals-contract COPY --from=build-dashmate-helper /platform/packages/masternode-reward-shares-contract packages/masternode-reward-shares-contract COPY --from=build-dashmate-helper /platform/packages/feature-flags-contract packages/feature-flags-contract @@ -754,7 +754,7 @@ COPY --from=build-dapi /platform/packages/dapi-grpc /platform/packages/dapi-grpc COPY --from=build-dapi /platform/packages/js-grpc-common /platform/packages/js-grpc-common COPY --from=build-dapi /platform/packages/wasm-dpp /platform/packages/wasm-dpp COPY --from=build-dapi /platform/packages/token-history-contract /platform/packages/token-history-contract -COPY --from=build-dapi /platform/packages/search-contract /platform/packages/search-contract +COPY --from=build-dapi /platform/packages/keyword-search-contract /platform/packages/keyword-search-contract RUN cp /platform/packages/dapi/.env.example /platform/packages/dapi/.env diff --git a/packages/keyword-search-contract/schema/v1/search-contract-documents.json b/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json similarity index 100% rename from packages/keyword-search-contract/schema/v1/search-contract-documents.json rename to packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json diff --git a/packages/keyword-search-contract/src/v1/mod.rs b/packages/keyword-search-contract/src/v1/mod.rs index 200a4523c97..cf69e071d33 100644 --- a/packages/keyword-search-contract/src/v1/mod.rs +++ b/packages/keyword-search-contract/src/v1/mod.rs @@ -29,7 +29,7 @@ pub mod document_types { pub fn load_documents_schemas() -> Result { serde_json::from_str(include_str!( - "../../schema/v1/search-contract-documents.json" + "../../schema/v1/keyword-search-contract-documents.json" )) .map_err(Error::InvalidSchemaJson) } diff --git a/packages/keyword-search-contract/test/unit/searchContract.spec.js b/packages/keyword-search-contract/test/unit/searchContract.spec.js index 2fd94a879b7..c13d4d6d681 100644 --- a/packages/keyword-search-contract/test/unit/searchContract.spec.js +++ b/packages/keyword-search-contract/test/unit/searchContract.spec.js @@ -7,7 +7,7 @@ const { const generateRandomIdentifier = require('@dashevo/wasm-dpp/lib/test/utils/generateRandomIdentifierAsync'); const { expect } = require('chai'); -const walletContractDocumentsSchema = require('../../schema/v1/search-contract-documents.json'); +const keywordSearchContractDocumentsSchema = require('../../schema/v1/keyword-search-contract-documents.json'); const expectJsonSchemaError = (validationResult, errorCount = 1) => { const errors = validationResult.getErrors(); @@ -37,11 +37,11 @@ describe('Search Contract', () => { identityId = await generateRandomIdentifier(); - dataContract = dpp.dataContract.create(identityId, BigInt(1), walletContractDocumentsSchema); + dataContract = dpp.dataContract.create(identityId, BigInt(1), keywordSearchContractDocumentsSchema); }); it('should have a valid contract definition', async () => { - expect(() => dpp.dataContract.create(identityId, BigInt(1), walletContractDocumentsSchema)) + expect(() => dpp.dataContract.create(identityId, BigInt(1), keywordSearchContractDocumentsSchema)) .to .not .throw(); From d3daebd567e2b595f1dd488506b491b616376ae0 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 18:23:06 +0700 Subject: [PATCH 34/46] fmt and yarn install --- .pnp.cjs | 23 ------------------- .../batch/tests/document/creation.rs | 6 ++++- .../data_contract_create/mod.rs | 16 ++++++++----- yarn.lock | 16 ------------- 4 files changed, 15 insertions(+), 46 deletions(-) diff --git a/.pnp.cjs b/.pnp.cjs index 473a9c1079f..c92c2a3a410 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -65,10 +65,6 @@ const RAW_RUNTIME_STATE = "name": "@dashevo/platform-test-suite",\ "reference": "workspace:packages/platform-test-suite"\ },\ - {\ - "name": "@dashevo/search-contract",\ - "reference": "workspace:packages/search-contract"\ - },\ {\ "name": "@dashevo/token-history-contract",\ "reference": "workspace:packages/token-history-contract"\ @@ -105,7 +101,6 @@ const RAW_RUNTIME_STATE = ["@dashevo/masternode-reward-shares-contract", ["workspace:packages/masternode-reward-shares-contract"]],\ ["@dashevo/platform", ["workspace:."]],\ ["@dashevo/platform-test-suite", ["workspace:packages/platform-test-suite"]],\ - ["@dashevo/search-contract", ["workspace:packages/search-contract"]],\ ["@dashevo/token-history-contract", ["workspace:packages/token-history-contract"]],\ ["@dashevo/wallet-lib", ["workspace:packages/wallet-lib"]],\ ["@dashevo/wallet-utils-contract", ["workspace:packages/wallet-utils-contract"]],\ @@ -2884,24 +2879,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@dashevo/search-contract", [\ - ["workspace:packages/search-contract", {\ - "packageLocation": "./packages/search-contract/",\ - "packageDependencies": [\ - ["@dashevo/search-contract", "workspace:packages/search-contract"],\ - ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ - ["chai", "npm:4.3.10"],\ - ["dirty-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.0.1"],\ - ["eslint", "npm:8.53.0"],\ - ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ - ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ - ["mocha", "npm:11.1.0"],\ - ["sinon", "npm:17.0.1"],\ - ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"]\ - ],\ - "linkType": "SOFT"\ - }]\ - ]],\ ["@dashevo/token-history-contract", [\ ["workspace:packages/token-history-contract", {\ "packageLocation": "./packages/token-history-contract/",\ diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index b2fdedf31bc..0ba6788a588 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -2488,7 +2488,11 @@ mod creation_tests { .expect("expected to get current platform version"); // Load the system Search contract - let search_contract = platform.drive.cache.system_data_contracts.load_keyword_search(); + let search_contract = platform + .drive + .cache + .system_data_contracts + .load_keyword_search(); platform .drive diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index 23c577931b0..64964ec94a5 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -2894,9 +2894,11 @@ mod tests { assert_eq!(keywords[2], "key3"); // Now check the Search Contract has the keyword documents - let search_contract = - load_system_data_contract(SystemDataContract::KeywordSearch, PlatformVersion::latest()) - .expect("expected to load search contract"); + let search_contract = load_system_data_contract( + SystemDataContract::KeywordSearch, + PlatformVersion::latest(), + ) + .expect("expected to load search contract"); let document_type = search_contract .document_type_for_name("contractKeywords") .expect("expected to get document type"); @@ -3176,9 +3178,11 @@ mod tests { assert_eq!(desc, "A perfectly valid description."); // Now check the Search Contract has the short and full description documents - let search_contract = - load_system_data_contract(SystemDataContract::KeywordSearch, PlatformVersion::latest()) - .expect("expected to load search contract"); + let search_contract = load_system_data_contract( + SystemDataContract::KeywordSearch, + PlatformVersion::latest(), + ) + .expect("expected to load search contract"); let short_description_document_type = search_contract .document_type_for_name("shortDescription") .expect("expected to get document type"); diff --git a/yarn.lock b/yarn.lock index 7597309d082..9c01abcf7d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1854,22 +1854,6 @@ __metadata: languageName: node linkType: hard -"@dashevo/search-contract@workspace:packages/search-contract": - version: 0.0.0-use.local - resolution: "@dashevo/search-contract@workspace:packages/search-contract" - dependencies: - "@dashevo/wasm-dpp": "workspace:*" - chai: "npm:^4.3.10" - dirty-chai: "npm:^2.0.1" - eslint: "npm:^8.53.0" - eslint-config-airbnb-base: "npm:^15.0.0" - eslint-plugin-import: "npm:^2.29.0" - mocha: "npm:^11.1.0" - sinon: "npm:^17.0.1" - sinon-chai: "npm:^3.7.0" - languageName: unknown - linkType: soft - "@dashevo/token-history-contract@workspace:*, @dashevo/token-history-contract@workspace:packages/token-history-contract": version: 0.0.0-use.local resolution: "@dashevo/token-history-contract@workspace:packages/token-history-contract" From 7c644b315c26cbef1695defd864740a1d3f867af Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Fri, 11 Apr 2025 20:11:18 +0700 Subject: [PATCH 35/46] add tests --- .../state_transition/state_transitions/mod.rs | 456 +++++++++++++++++- 1 file changed, 455 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 868de9b9e3b..99431593cdd 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -53,11 +53,19 @@ impl ValidationMode { #[cfg(test)] pub(in crate::execution) mod tests { use crate::rpc::core::MockCoreRPCLike; - use crate::test::helpers::setup::TempPlatform; + use crate::test::helpers::setup::{TempPlatform, TestPlatformBuilder}; use dpp::block::block_info::BlockInfo; + use dpp::data_contracts::SystemDataContract; use dpp::fee::Credits; + use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dpp::identity::{Identity, IdentityPublicKey, IdentityV0, KeyID, KeyType, Purpose, SecurityLevel, TimestampMillis}; use dpp::prelude::{Identifier, IdentityNonce}; + use dpp::state_transition::data_contract_create_transition::methods::DataContractCreateTransitionMethodsV0; + use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; + use dpp::system_data_contracts::load_system_data_contract; + use dpp::tests::json_document::json_document_to_contract_with_ids; + use drive::drive::document::query::QueryDocumentsOutcomeV0Methods; + use drive::query::DriveDocumentQuery; use platform_version::version::PlatformVersion; use rand::prelude::StdRng; use rand::{Rng, SeedableRng}; @@ -2469,4 +2477,450 @@ pub(in crate::execution) mod tests { basic_token_contract } + + mod keyword_search_contract { + use super::*; + // + // ────────────────────────────────────────────────────────────────────────── + // Keyword‑Search contract – creation is forbidden + // ────────────────────────────────────────────────────────────────────────── + // + + /// Return `(document, entropy)` so we can reuse the exact entropy when + /// we build the transition. **No rng.clone()** (that caused the ID mismatch). + fn build_random_doc_of_type( + rng: &mut StdRng, + doc_type_name: &str, + identity_id: Identifier, + contract: &DataContract, + platform_version: &PlatformVersion, + ) -> (Document, Bytes32) { + let doc_type = contract + .document_type_for_name(doc_type_name) + .expect("doc type exists"); + + let entropy = Bytes32::random_with_rng(rng); + + let doc = doc_type + .random_document_with_identifier_and_entropy( + rng, + identity_id, + entropy, + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("random doc"); + + (doc, entropy) + } + + #[test] + fn should_err_when_creating_contract_keywords_document() { + let platform_version = PlatformVersion::latest(); + + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = setup_identity(&mut platform, 42, dash_to_credits!(1.0)); + + let contract = load_system_data_contract( + SystemDataContract::KeywordSearch, + PlatformVersion::latest(), + ) + .expect("expected to load search contract"); + + let mut rng = StdRng::seed_from_u64(1); + let (doc, entropy) = build_random_doc_of_type( + &mut rng, + "contractKeywords", + identity.id(), + &contract, + platform_version, + ); + + let transition = BatchTransition::new_document_creation_transition_from_document( + doc, + contract.document_type_for_name("contractKeywords").unwrap(), + entropy.0, // same entropy → no ID mismatch + &key, + 1, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("batch transition"); + + let serialized = transition.serialize_to_bytes().unwrap(); + + let platform_state = platform.state.load(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &platform.drive.grove.start_transaction(), + platform_version, + false, + None, + ) + .expect("processing failed"); + + let execution_result = processing_result.into_execution_results().remove(0); + assert_matches!( + execution_result, + StateTransitionExecutionResult::PaidConsensusError(err, _) + if err.to_string().contains("not allowed because of the document type's creation restriction mode") + ); + } + + #[test] + fn should_err_when_creating_short_description_document() { + let platform_version = PlatformVersion::latest(); + + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = setup_identity(&mut platform, 43, dash_to_credits!(1.0)); + + let contract = load_system_data_contract( + SystemDataContract::KeywordSearch, + PlatformVersion::latest(), + ) + .expect("expected to load search contract"); + + let mut rng = StdRng::seed_from_u64(2); + let (doc, entropy) = build_random_doc_of_type( + &mut rng, + "shortDescription", + identity.id(), + &contract, + platform_version, + ); + + let transition = BatchTransition::new_document_creation_transition_from_document( + doc, + contract.document_type_for_name("shortDescription").unwrap(), + entropy.0, + &key, + 1, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("batch transition"); + + let serialized = transition.serialize_to_bytes().unwrap(); + + let platform_state = platform.state.load(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &platform.drive.grove.start_transaction(), + platform_version, + false, + None, + ) + .expect("processing failed"); + + let execution_result = processing_result.into_execution_results().remove(0); + assert_matches!( + execution_result, + StateTransitionExecutionResult::PaidConsensusError(err, _) + if err.to_string().contains("not allowed because of the document type's creation restriction mode") + ); + } + + #[test] + fn should_err_when_creating_full_description_document() { + let platform_version = PlatformVersion::latest(); + + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = setup_identity(&mut platform, 44, dash_to_credits!(1.0)); + + let contract = load_system_data_contract( + SystemDataContract::KeywordSearch, + PlatformVersion::latest(), + ) + .expect("expected to load search contract"); + + let mut rng = StdRng::seed_from_u64(3); + let (doc, entropy) = build_random_doc_of_type( + &mut rng, + "fullDescription", + identity.id(), + &contract, + platform_version, + ); + + let transition = BatchTransition::new_document_creation_transition_from_document( + doc, + contract.document_type_for_name("fullDescription").unwrap(), + entropy.0, + &key, + 1, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("batch transition"); + + let serialized = transition.serialize_to_bytes().unwrap(); + + let platform_state = platform.state.load(); + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &platform.drive.grove.start_transaction(), + platform_version, + false, + None, + ) + .expect("processing failed"); + + let execution_result = processing_result.into_execution_results().remove(0); + assert_matches!( + execution_result, + StateTransitionExecutionResult::PaidConsensusError(err, _) + if err.to_string().contains("not allowed because of the document type's creation restriction mode") + ); + } + + // + // ────────────────────────────────────────────────────────────────────────── + // Keyword‑Search contract – owner can update / delete + // ────────────────────────────────────────────────────────────────────────── + // + + fn create_contract_with_keywords_and_description( + platform: &mut TempPlatform, + ) -> (Identity, SimpleSigner, IdentityPublicKey) { + let platform_version = PlatformVersion::latest(); + + // Owner identity + let (owner_identity, signer, key) = + setup_identity(platform, 777, dash_to_credits!(1.0)); + + // Load the keyword‑test fixture + let mut contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", + Some(owner_identity.id()), + None, + false, + platform_version, + ) + .expect("load contract"); + + // Inject description + keywords + contract.set_description(Some("A short description".to_string())); + contract.set_keywords(vec!["graph".into(), "indexing".into()]); + + // Create transition inside GroveDB tx + let create_transition = DataContractCreateTransition::new_from_data_contract( + contract, + 1, + &owner_identity.clone().into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("build transition"); + + let serialized = create_transition.serialize_to_bytes().unwrap(); + let platform_state = platform.state.load(); + let tx = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &tx, + platform_version, + false, + None, + ) + .expect("process"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(tx) + .unwrap() + .expect("commit"); + + (owner_identity, signer, key) + } + + #[test] + fn owner_can_update_short_description_document() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (_owner, signer, key) = + create_contract_with_keywords_and_description(&mut platform); + + // 🔎 fetch shortDescription doc through query + let search_contract = + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .expect("load search contract"); + + let doc_type = search_contract + .document_type_for_name("shortDescription") + .unwrap(); + + let query = DriveDocumentQuery::all_items_query(&search_contract, doc_type, None); + let existing_docs = platform + .drive + .query_documents( + query, + None, + false, + None, + Some(platform_version.protocol_version), + ) + .expect("query failed"); + + let mut doc = existing_docs.documents().first().expect("doc").clone(); + doc.set_revision(Some(doc.revision().unwrap_or_default() + 1)); + doc.set("description", "updated description".into()); + + let transition = BatchTransition::new_document_replacement_transition_from_document( + doc, + doc_type, + &key, + 2, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("replace"); + + let serialized = transition.serialize_to_bytes().unwrap(); + let platform_state = platform.state.load(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &platform.drive.grove.start_transaction(), + platform_version, + false, + None, + ) + .expect("process"); + + assert_matches!( + processing_result.into_execution_results().remove(0), + SuccessfulExecution(..) + ); + } + + #[test] + fn owner_can_delete_keyword_document() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let (_owner, signer, key) = + create_contract_with_keywords_and_description(&mut platform); + + let search_contract = + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .expect("load search contract"); + let doc_type = search_contract + .document_type_for_name("contractKeywords") + .unwrap(); + + let query = DriveDocumentQuery::all_items_query(&search_contract, doc_type, None); + let existing_docs = platform + .drive + .query_documents( + query, + None, + false, + None, + Some(platform_version.protocol_version), + ) + .expect("query failed"); + + let doc = existing_docs.documents().first().unwrap().clone(); + + let transition = BatchTransition::new_document_deletion_transition_from_document( + doc, + doc_type, + &key, + 2, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("delete"); + + let serialized = transition.serialize_to_bytes().unwrap(); + let platform_state = platform.state.load(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &[serialized], + &platform_state, + &BlockInfo::default(), + &platform.drive.grove.start_transaction(), + platform_version, + false, + None, + ) + .expect("process"); + + assert_matches!( + processing_result.into_execution_results().remove(0), + SuccessfulExecution(..) + ); + } + } } From 43177137a954125c15fe38f204b3af2201d2ae84 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Sat, 12 Apr 2025 01:11:33 +0700 Subject: [PATCH 36/46] optimize keyword update --- .../v0/mod.rs | 1 + .../data_triggers/triggers/dpns/v0/mod.rs | 2 + .../triggers/withdrawals/v0/mod.rs | 1 + .../batch/state/v0/fetch_documents.rs | 3 +- .../v1/update_description/mod.rs | 9 ++- .../v1/update_description/v1/mod.rs | 10 ++- .../update_contract/v1/update_keywords/mod.rs | 9 ++- .../v1/update_keywords/v1/mod.rs | 75 +++++++++++++------ .../validate_uniqueness_of_data/v0/mod.rs | 1 + .../v0/mod.rs | 1 + .../v0/mod.rs | 1 + 11 files changed, 80 insertions(+), 33 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/platform_events/fee_pool_outwards_distribution/fetch_reward_shares_list_for_masternode/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/fee_pool_outwards_distribution/fetch_reward_shares_list_for_masternode/v0/mod.rs index a7999958dc6..d64499dcd53 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/fee_pool_outwards_distribution/fetch_reward_shares_list_for_masternode/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/fee_pool_outwards_distribution/fetch_reward_shares_list_for_masternode/v0/mod.rs @@ -66,6 +66,7 @@ impl Platform { block_time_ms: None, }; + // todo: deal with cost of this operation let query_documents_outcome = self.drive.query_documents( drive_query, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs index e94ab7595b5..cd7d7ba1a3b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs @@ -243,6 +243,7 @@ pub(super) fn create_domain_data_trigger_v0( block_time_ms: None, }; + // todo: deal with cost of this operation let documents = context .platform .drive @@ -333,6 +334,7 @@ pub(super) fn create_domain_data_trigger_v0( block_time_ms: None, }; + // todo: deal with cost of this operation let preorder_documents = context .platform .drive diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs index f6e6e07bc1c..51be13ab46b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs @@ -76,6 +76,7 @@ pub(super) fn delete_withdrawal_data_trigger_v0( block_time_ms: None, }; + // todo: deal with cost of this operation let withdrawals = context .platform .drive diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/fetch_documents.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/fetch_documents.rs index c206b54bd57..88e145b32f4 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/fetch_documents.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/fetch_documents.rs @@ -163,7 +163,7 @@ pub(crate) fn fetch_documents_for_transitions_knowing_contract_and_document_type block_time_ms: None, }; - //todo: deal with cost of this operation + // todo: deal with cost of this operation let documents_outcome = drive.query_documents( drive_query, None, @@ -207,6 +207,7 @@ pub(crate) fn fetch_document_with_id( block_time_ms: None, }; + // todo: deal with cost of this operation let documents_outcome = drive.query_documents( drive_query, None, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs index 6e381902bda..edcecc128a1 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs @@ -14,7 +14,8 @@ use std::collections::HashMap; mod v1; impl Drive { - /// Updates contract description in the state. + /// Updates the documents in the Keyword Search contract for the contract + /// update description and returns the fee result pub fn update_contract_description( &self, contract_id: Identifier, @@ -52,7 +53,8 @@ impl Drive { } } - /// Adds contract description update operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract description pub fn update_contract_description_add_to_operations( &self, contract_id: Identifier, @@ -92,7 +94,8 @@ impl Drive { } } - /// The operations needed to update a description + /// Creates and returns the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract description pub fn update_contract_description_operations( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs index 0dfcf5fb2c4..b7eecd11331 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs @@ -17,7 +17,8 @@ use platform_version::version::PlatformVersion; use std::collections::HashMap; impl Drive { - /// Adds operations for updating a contract description and returns the fee result. + /// Updates the documents in the Keyword Search contract for the contract + /// update description and returns the fee result pub(super) fn update_contract_description_v1( &self, contract_id: Identifier, @@ -50,7 +51,8 @@ impl Drive { Ok(fees) } - /// Adds contract description update operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract description pub(super) fn update_contract_description_add_to_operations_v1( &self, contract_id: Identifier, @@ -87,7 +89,8 @@ impl Drive { ) } - /// The operations needed to update a contract description + /// Creates and returns the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract description pub(super) fn update_contract_description_operations_v1( &self, contract_id: Identifier, @@ -119,6 +122,7 @@ impl Drive { }, ); + // todo: deal with cost of this operation let query_outcome = self.query_documents( query, Some(&block_info.epoch), diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs index cfb6624e55a..3b65b078997 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs @@ -14,7 +14,8 @@ use std::collections::HashMap; mod v1; impl Drive { - /// Updates keywords in the state. + /// Updates the documents in the Keyword Search contract for the contract + /// update keywords and returns the fee result pub fn update_contract_keywords( &self, contract_id: Identifier, @@ -52,7 +53,8 @@ impl Drive { } } - /// Adds keywords creation operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract keywords pub fn update_contract_keywords_add_to_operations( &self, contract_id: Identifier, @@ -92,7 +94,8 @@ impl Drive { } } - /// The operations needed to update keywords + /// Creates and returns the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract keywords pub fn update_contract_keywords_operations( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs index 0de7077f3ca..f8bfdc5329f 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs @@ -1,5 +1,6 @@ use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; use crate::drive::Drive; +use crate::error::drive::DriveError; use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; use crate::query::{DriveDocumentQuery, WhereClause, WhereOperator}; @@ -15,7 +16,8 @@ use platform_version::version::PlatformVersion; use std::collections::HashMap; impl Drive { - /// Adds operations for updating keywords and returns the fee result. + /// Updates the documents in the Keyword Search contract for the contract + /// update keywords and returns the fee result pub(super) fn update_contract_keywords_v1( &self, contract_id: Identifier, @@ -48,7 +50,8 @@ impl Drive { Ok(fees) } - /// Adds keyword update operations to drive operations + /// Creates and applies the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract keywords pub(super) fn update_contract_keywords_add_to_operations_v1( &self, contract_id: Identifier, @@ -85,8 +88,8 @@ impl Drive { ) } - /// The operations needed to update the keywords search contract documents - /// First we delete the existing keywords then we add the new ones + /// Creates and returns the LowLeveLDriveOperations needed to update + /// the documents in the Keyword Search contract for the contract keywords pub(super) fn update_contract_keywords_operations_v1( &self, contract_id: Identifier, @@ -101,7 +104,7 @@ impl Drive { ) -> Result, Error> { let mut operations: Vec = vec![]; - // First delete the existing keywords + // First get the existing keywords so we know which ones we need to delete and which new ones we need to add let contract = self .cache .system_data_contracts @@ -119,6 +122,7 @@ impl Drive { }, ); + // todo: deal with cost of this operation let query_outcome = self.query_documents( query, Some(&block_info.epoch), @@ -127,30 +131,55 @@ impl Drive { Some(platform_version.protocol_version), )?; - let existing_documents = query_outcome.documents(); - for document in existing_documents { - operations.extend(self.delete_document_for_contract_operations( - document.id(), - &contract, - document_type, - None, + let mut existing: Vec<(String, Identifier)> = Vec::new(); + for doc in query_outcome.documents() { + let kw = doc + .get("keyword") + .and_then(|v| v.as_str()) + .ok_or_else(|| { + Error::Drive(DriveError::CorruptedDriveState( + "keyword should exist".to_string(), + )) + })? + .to_string(); + existing.push((kw, doc.id())); + } + + // If an existing keyword is not in the new keyword set, we delete it + for (kw, doc_id) in &existing { + if !keywords.iter().any(|k| k == kw) { + operations.extend(self.delete_document_for_contract_operations( + *doc_id, + &contract, + document_type, + None, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?); + } + } + + // Finally, add the new ones + let mut keywords_to_add: Vec = Vec::new(); + for kw in keywords { + if !existing.iter().any(|(e_kw, _)| e_kw == kw) { + keywords_to_add.push(kw.clone()); + } + } + + if !keywords_to_add.is_empty() { + operations.extend(self.add_new_contract_keywords_operations_v1( + contract_id, + owner_id, + &keywords_to_add, + block_info, estimated_costs_only_with_layer_info, transaction, platform_version, )?); } - // Then add the new ones - operations.extend(self.add_new_contract_keywords_operations_v1( - contract_id, - owner_id, - keywords, - block_info, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - )?); - Ok(operations) } } diff --git a/packages/rs-drive/src/drive/document/index_uniqueness/internal/validate_uniqueness_of_data/v0/mod.rs b/packages/rs-drive/src/drive/document/index_uniqueness/internal/validate_uniqueness_of_data/v0/mod.rs index dab9fd17703..acc70692f62 100644 --- a/packages/rs-drive/src/drive/document/index_uniqueness/internal/validate_uniqueness_of_data/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/index_uniqueness/internal/validate_uniqueness_of_data/v0/mod.rs @@ -187,6 +187,7 @@ impl Drive { block_time_ms: None, }; + // todo: deal with cost of this operation let query_result = self.query_documents( query, None, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs index 4e611e39fb3..13d20203cf1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs @@ -82,6 +82,7 @@ impl Drive { block_time_ms: None, }; + // todo: deal with cost of this operation let outcome = self.query_documents( drive_query, None, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs index ea92ef5a67b..e99fa9311e1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs @@ -83,6 +83,7 @@ impl Drive { block_time_ms: None, }; + // todo: deal with cost of this operation let outcome = self.query_documents( drive_query, None, From ef6fd85bd451ba285972b5f21da711e70d5edc58 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Sat, 12 Apr 2025 12:29:27 +0700 Subject: [PATCH 37/46] better --- .../schema/v1/keyword-search-contract-documents.json | 7 ++++--- .../src/drive/contract/insert/add_new_keywords/v1/mod.rs | 8 +++----- .../update/update_contract/v1/update_keywords/v1/mod.rs | 2 +- .../update_document_for_contract_operations/v0/mod.rs | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json b/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json index be74e7cbe6c..1dd4d55478f 100644 --- a/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json +++ b/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json @@ -1,7 +1,7 @@ { "contractKeywords": { "type": "object", - "documentsMutable": true, + "documentsMutable": false, "canBeDeleted": true, "creationRestrictionMode": 2, "indices": [ @@ -42,6 +42,7 @@ "contractId", "keyword" ], + "description": "Keywords associated with the contract allowing for better searchability. This document type can be deleted but not manually created nor updated. Creation occurs automatically internally on DataContractCreate and mirrors the contract's keywords field. It can be updated with DataContractUpdate.", "additionalProperties": false }, "shortDescription": { @@ -80,7 +81,7 @@ "contractId", "description" ], - "description": "Short description of the contract. This document type is immutable and creation is not allowed. Creation occurs automatically internally on DataContractCreate and mirrors the contract's description field.", + "description": "Short description of the contract. This document type is mutable but creation is not allowed. Creation occurs automatically internally on DataContractCreate and mirrors the contract's description field initially.", "additionalProperties": false }, "fullDescription": { @@ -119,7 +120,7 @@ "contractId", "description" ], - "description": "Full description of the contract. This document type is mutable by contract owner but creation is not allowed. Creation occurs automatically internally on DataContractCreate and mirrors the contract's description field initially.", + "description": "Full description of the contract. This document type is mutable but creation is not allowed. Creation occurs automatically internally on DataContractCreate and mirrors the contract's description field initially.", "additionalProperties": false } } \ No newline at end of file diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs index 6abea56a76e..97846cfa529 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs @@ -105,12 +105,11 @@ impl Drive { let contract = self.cache.system_data_contracts.load_keyword_search(); let document_type = contract.document_type_for_name("contractKeywords")?; - for (i, keyword) in keywords.iter().enumerate() { + for keyword in keywords.iter() { let document = self.build_contract_keyword_document_owned_v1( contract_id, owner_id, - keyword, - i as u64, + keyword, // since keywords are unique in the contract, we can use it as entropy block_info, )?; @@ -143,14 +142,13 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, keyword: &String, - keyword_index: u64, block_info: &BlockInfo, ) -> Result { let document_id = Document::generate_document_id_v0( &contract_id, &owner_id, "contractKeywords", - keyword_index.to_be_bytes().as_slice(), + &keyword.as_bytes(), ); let properties = BTreeMap::from([ diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs index f8bfdc5329f..a219ba93900 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs @@ -169,7 +169,7 @@ impl Drive { } if !keywords_to_add.is_empty() { - operations.extend(self.add_new_contract_keywords_operations_v1( + operations.extend(self.add_new_contract_keywords_operations( contract_id, owner_id, &keywords_to_add, 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 a3c0aec24c5..b903ca123c1 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 @@ -57,7 +57,7 @@ impl Drive { // if it requires revision then there are reasons for us to be able to update in drive { return Err(Error::Drive(DriveError::UpdatingReadOnlyImmutableDocument( - "documents for this contract are not mutable", + "this document type is not mutable", ))); } From 3c0c4717aa61eee5d9145ea8622ee14dfeff6c3c Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Sat, 12 Apr 2025 14:06:08 +0700 Subject: [PATCH 38/46] fix linting --- .../src/drive/contract/insert/add_new_keywords/v1/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs index 97846cfa529..9c49185a9cb 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs @@ -148,7 +148,7 @@ impl Drive { &contract_id, &owner_id, "contractKeywords", - &keyword.as_bytes(), + keyword.as_bytes(), ); let properties = BTreeMap::from([ From 5df68e382d3ba707bdfc08c56ef33ad3ecbdb39d Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Mon, 14 Apr 2025 17:03:11 +0700 Subject: [PATCH 39/46] fix fee in test --- .../state_transitions/batch/tests/token/direct_selling/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs index d1ded56c94b..742846b5326 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs @@ -119,7 +119,7 @@ mod token_selling_tests { .drive .fetch_identity_balance(buyer.id().to_buffer(), None, platform_version) .expect("expected to fetch credit balance"); - assert_eq!(buyer_credit_balance, Some(699_868_054_220)); // 10.0 - 3.0 spent - fees =~ 7 dash left + assert_eq!(buyer_credit_balance, Some(699_868_051_500)); // 10.0 - 3.0 spent - fees =~ 7 dash left } #[test] From 334dc745cd3e29bb7eb8b2526c0e6318b1ea1805 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 16 Apr 2025 17:22:57 +0700 Subject: [PATCH 40/46] increase stack size --- .github/workflows/tests-rs-package.yml | 2 +- packages/dapi-grpc/Cargo.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests-rs-package.yml b/.github/workflows/tests-rs-package.yml index 5cefd1a9c5b..b52e2bd8bfd 100644 --- a/.github/workflows/tests-rs-package.yml +++ b/.github/workflows/tests-rs-package.yml @@ -195,7 +195,7 @@ jobs: uses: ./.github/actions/librocksdb - name: Run tests - run: cargo test --package=${{ inputs.package }} --all-features --locked + run: RUST_MIN_STACK=16777216 cargo test --package=${{ inputs.package }} --all-features --locked env: SCCACHE_S3_KEY_PREFIX: ${{ runner.os }}/sccache/${{ runner.arch }}/linux-gnu ROCKSDB_STATIC: "/opt/rocksdb/usr/local/lib/librocksdb.a" diff --git a/packages/dapi-grpc/Cargo.toml b/packages/dapi-grpc/Cargo.toml index 110c3cdd936..f229ba3c746 100644 --- a/packages/dapi-grpc/Cargo.toml +++ b/packages/dapi-grpc/Cargo.toml @@ -46,6 +46,7 @@ futures-core = "0.3.30" tonic = { version = "0.13.0", features = [ "codegen", "prost", + "tls-ring", ], default-features = false } serde = { version = "1.0.219", optional = true, features = ["derive"] } serde_bytes = { version = "0.11.12", optional = true } @@ -64,6 +65,7 @@ tonic = { version = "0.13.0", features = [ "transport", "tls-native-roots", "tls-webpki-roots", + "tls-ring", ], default-features = false } [build-dependencies] From 89259ac699928a2cfafa884ea332bbc19349aa77 Mon Sep 17 00:00:00 2001 From: QuantumExplorer Date: Thu, 17 Apr 2025 11:56:12 +0700 Subject: [PATCH 41/46] fix(platform): sam's fixes for token search (#2551) --- .../v1/keyword-search-contract-documents.json | 6 +-- .../create_genesis_state/test/tokens.rs | 27 +++++----- .../basic_structure/v0/mod.rs | 49 ++++++++--------- .../data_contract_update/mod.rs | 18 +++---- .../state_transition/state_transitions/mod.rs | 54 ++++++++++--------- .../contract/insert/add_description/mod.rs | 29 ++++------ .../insert/add_description/{v1 => v0}/mod.rs | 28 ++++------ .../contract/insert/add_new_keywords/mod.rs | 47 ++++------------ .../insert/add_new_keywords/{v1 => v0}/mod.rs | 35 ++++++------ .../rs-drive/src/drive/contract/update/mod.rs | 3 ++ .../contract/update/update_contract/v1/mod.rs | 7 +-- .../v1 => }/update_description/mod.rs | 31 ++++------- .../v1 => update_description/v0}/mod.rs | 25 +++++---- .../v1 => }/update_keywords/mod.rs | 31 ++++------- .../v1 => update_keywords/v0}/mod.rs | 40 +++++--------- .../mod.rs | 52 ++++++++++++++++++ .../v0/mod.rs | 22 +++++++- .../drive_contract_method_versions/mod.rs | 4 ++ .../drive_contract_method_versions/v1.rs | 8 ++- .../drive_contract_method_versions/v2.rs | 8 ++- 20 files changed, 271 insertions(+), 253 deletions(-) rename packages/rs-drive/src/drive/contract/insert/add_description/{v1 => v0}/mod.rs (91%) rename packages/rs-drive/src/drive/contract/insert/add_new_keywords/{v1 => v0}/mod.rs (85%) rename packages/rs-drive/src/drive/contract/update/{update_contract/v1 => }/update_description/mod.rs (81%) rename packages/rs-drive/src/drive/contract/update/{update_contract/v1/update_description/v1 => update_description/v0}/mod.rs (90%) rename packages/rs-drive/src/drive/contract/update/{update_contract/v1 => }/update_keywords/mod.rs (80%) rename packages/rs-drive/src/drive/contract/update/{update_contract/v1/update_keywords/v1 => update_keywords/v0}/mod.rs (82%) diff --git a/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json b/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json index 1dd4d55478f..fac5cc55d30 100644 --- a/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json +++ b/packages/keyword-search-contract/schema/v1/keyword-search-contract-documents.json @@ -2,7 +2,7 @@ "contractKeywords": { "type": "object", "documentsMutable": false, - "canBeDeleted": true, + "canBeDeleted": false, "creationRestrictionMode": 2, "indices": [ { @@ -48,7 +48,7 @@ "shortDescription": { "type": "object", "documentsMutable": true, - "canBeDeleted": true, + "canBeDeleted": false, "creationRestrictionMode": 2, "indices": [ { @@ -87,7 +87,7 @@ "fullDescription": { "type": "object", "documentsMutable": true, - "canBeDeleted": true, + "canBeDeleted": false, "creationRestrictionMode": 2, "indices": [ { diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs index 1f8534a43f1..0d1e3180b86 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/test/tokens.rs @@ -1,8 +1,12 @@ use crate::error::Error; use crate::platform_types::platform::Platform; use dpp::block::block_info::BlockInfo; +use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; use dpp::data_contract::associated_token::token_configuration::v0::TokenConfigurationV0; +use dpp::data_contract::associated_token::token_configuration_convention::accessors::v0::TokenConfigurationConventionV0Getters; use dpp::data_contract::associated_token::token_configuration_convention::v0::TokenConfigurationConventionV0; +use dpp::data_contract::associated_token::token_configuration_localization::v0::TokenConfigurationLocalizationV0; +use dpp::data_contract::associated_token::token_configuration_localization::TokenConfigurationLocalization; use dpp::data_contract::associated_token::token_distribution_rules::v0::TokenDistributionRulesV0; use dpp::data_contract::associated_token::token_keeps_history_rules::v0::TokenKeepsHistoryRulesV0; use dpp::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers; @@ -30,10 +34,6 @@ use drive::grovedb::TransactionArg; use rand::rngs::StdRng; use rand::SeedableRng; use std::sync::LazyLock; -use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; -use dpp::data_contract::associated_token::token_configuration_convention::accessors::v0::TokenConfigurationConventionV0Getters; -use dpp::data_contract::associated_token::token_configuration_localization::TokenConfigurationLocalization; -use dpp::data_contract::associated_token::token_configuration_localization::v0::TokenConfigurationLocalizationV0; const IDENTITY_ID_1: Identifier = Identifier::new([1; 32]); const IDENTITY_ID_2: Identifier = Identifier::new([2; 32]); @@ -271,14 +271,17 @@ impl Platform { description: Some("Some token description".to_string()), }); - token_configuration.conventions_mut().localizations_mut().insert( - "en".to_string(), - TokenConfigurationLocalization::V0(TokenConfigurationLocalizationV0 { - should_capitalize: false, - singular_form: "cat".to_string(), - plural_form: "cats".to_string(), - }), - ); + token_configuration + .conventions_mut() + .localizations_mut() + .insert( + "en".to_string(), + TokenConfigurationLocalization::V0(TokenConfigurationLocalizationV0 { + should_capitalize: false, + singular_form: "cat".to_string(), + plural_form: "cats".to_string(), + }), + ); let tokens = [ (0, token_configuration.clone()), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v0/mod.rs index 81717e7c1b1..121e9cf348c 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v0/mod.rs @@ -1,7 +1,10 @@ -use std::collections::HashSet; -use dpp::consensus::basic::BasicError; use crate::error::Error; -use dpp::consensus::basic::data_contract::{DuplicateKeywordsError, InvalidDataContractVersionError, InvalidDescriptionLengthError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, NonContiguousContractTokenPositionsError, TooManyKeywordsError}; +use dpp::consensus::basic::data_contract::{ + DuplicateKeywordsError, InvalidDataContractVersionError, InvalidDescriptionLengthError, + InvalidKeywordLengthError, InvalidTokenBaseSupplyError, + NonContiguousContractTokenPositionsError, TooManyKeywordsError, +}; +use dpp::consensus::basic::BasicError; use dpp::consensus::ConsensusError; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; use dpp::data_contract::{TokenContractPosition, INITIAL_DATA_CONTRACT_VERSION}; @@ -10,6 +13,7 @@ use dpp::state_transition::data_contract_create_transition::accessors::DataContr use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; use dpp::validation::SimpleConsensusValidationResult; use dpp::version::PlatformVersion; +use std::collections::HashSet; pub(in crate::execution::validation::state_transition::state_transitions::data_contract_create) trait DataContractCreateStateTransitionBasicStructureValidationV0 { @@ -78,16 +82,15 @@ impl DataContractCreateStateTransitionBasicStructureValidationV0 for DataContrac } } - // Validate there are no more than 20 keywords if self.data_contract().keywords().len() > 20 { return Ok(SimpleConsensusValidationResult::new_with_error( - ConsensusError::BasicError( - BasicError::TooManyKeywordsError(TooManyKeywordsError::new( + ConsensusError::BasicError(BasicError::TooManyKeywordsError( + TooManyKeywordsError::new( self.data_contract().id(), self.data_contract().keywords().len() as u8, - )) - ) + ), + )), )); } @@ -97,24 +100,21 @@ impl DataContractCreateStateTransitionBasicStructureValidationV0 for DataContrac // First check keyword length if keyword.len() < 3 || keyword.len() > 50 { return Ok(SimpleConsensusValidationResult::new_with_error( - ConsensusError::BasicError( - BasicError::InvalidKeywordLengthError(InvalidKeywordLengthError::new( + ConsensusError::BasicError(BasicError::InvalidKeywordLengthError( + InvalidKeywordLengthError::new( self.data_contract().id(), keyword.to_string(), - )), - ) + ), + )), )); } // Then check uniqueness if !seen_keywords.insert(keyword) { return Ok(SimpleConsensusValidationResult::new_with_error( - ConsensusError::BasicError( - BasicError::DuplicateKeywordsError(DuplicateKeywordsError::new( - self.data_contract().id(), - keyword.to_string(), - )), - ) + ConsensusError::BasicError(BasicError::DuplicateKeywordsError( + DuplicateKeywordsError::new(self.data_contract().id(), keyword.to_string()), + )), )); } } @@ -123,19 +123,16 @@ impl DataContractCreateStateTransitionBasicStructureValidationV0 for DataContrac if let Some(description) = self.data_contract().description() { if !(description.len() >= 3 && description.len() <= 100) { return Ok(SimpleConsensusValidationResult::new_with_error( - ConsensusError::BasicError( - BasicError::InvalidDescriptionLengthError( - InvalidDescriptionLengthError::new( - self.data_contract().id(), - description.to_string(), - ), + ConsensusError::BasicError(BasicError::InvalidDescriptionLengthError( + InvalidDescriptionLengthError::new( + self.data_contract().id(), + description.to_string(), ), - ) + )), )); } } - Ok(SimpleConsensusValidationResult::new()) } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index 46dd89558a3..f61111ab945 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -1298,7 +1298,7 @@ mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![tx_bytes], + &[tx_bytes], &platform_state, &BlockInfo::default(), &transaction, @@ -1488,7 +1488,7 @@ mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![tx_bytes], + &[tx_bytes], &platform_state, &BlockInfo::default(), &transaction, @@ -1973,7 +1973,7 @@ mod tests { .unwrap(); assert_eq!( *fetched.contract.keywords(), - vec!["newA", "newB", "newC"] + ["newA", "newB", "newC"] .iter() .map(|&s| s.to_string()) .collect::>() @@ -2301,8 +2301,8 @@ mod tests { &identity, &signer, &key, - &"old1", - &platform_version, + "old1", + platform_version, ); // verify initial docs @@ -2316,15 +2316,15 @@ mod tests { &identity, &signer, &key, - &"newA", - &platform_version, + "newA", + platform_version, ) .expect("update should succeed"); // fetch contract – description updated? let fetched = platform .drive - .fetch_contract(cid.into(), None, None, None, &platform_version) + .fetch_contract(cid.into(), None, None, None, platform_version) .value .unwrap() .unwrap(); @@ -2334,7 +2334,7 @@ mod tests { ); // search‑contract docs updated? - let docs_after = description_docs_for_contract(&platform, cid, &platform_version); + let docs_after = description_docs_for_contract(&platform, cid, platform_version); assert_eq!(docs_after, "newA".to_string()); // old docs gone assert!(!docs_after.contains(&"old1".to_string())); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 5e128f17220..8b6d9f0061b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -313,6 +313,7 @@ pub(in crate::execution) mod tests { (identity, signer, master_key) } + #[allow(clippy::too_many_arguments)] pub(crate) fn setup_add_key_to_identity( platform: &mut TempPlatform, identity: &mut Identity, @@ -971,6 +972,7 @@ pub(in crate::execution) mod tests { (identity_1_info.0, identity_2_info.0, dpns_contract) } + #[allow(clippy::too_many_arguments)] fn create_dpns_name_contest_on_identities( platform: &mut TempPlatform, identity_1: &(Identity, SimpleSigner, IdentityPublicKey), @@ -1189,10 +1191,8 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![ - documents_batch_create_serialized_preorder_transition_1.clone(), - documents_batch_create_serialized_preorder_transition_2.clone(), - ], + &[documents_batch_create_serialized_preorder_transition_1.clone(), + documents_batch_create_serialized_preorder_transition_2.clone()], platform_state, &BlockInfo::default_with_time( platform_state @@ -1234,10 +1234,8 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![ - documents_batch_create_serialized_transition_1.clone(), - documents_batch_create_serialized_transition_2.clone(), - ], + &[documents_batch_create_serialized_transition_1.clone(), + documents_batch_create_serialized_transition_2.clone()], platform_state, &BlockInfo::default_with_time( platform_state @@ -1279,6 +1277,7 @@ pub(in crate::execution) mod tests { ) } + #[allow(clippy::too_many_arguments)] fn create_dpns_name_contest_on_identities_for_contract_records( platform: &mut TempPlatform, identity_1: &(Identity, SimpleSigner, IdentityPublicKey), @@ -1505,10 +1504,8 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![ - documents_batch_create_serialized_preorder_transition_1.clone(), - documents_batch_create_serialized_preorder_transition_2.clone(), - ], + &[documents_batch_create_serialized_preorder_transition_1.clone(), + documents_batch_create_serialized_preorder_transition_2.clone()], platform_state, &BlockInfo::default_with_time( platform_state @@ -1537,10 +1534,8 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![ - documents_batch_create_serialized_transition_1.clone(), - documents_batch_create_serialized_transition_2.clone(), - ], + &[documents_batch_create_serialized_transition_1.clone(), + documents_batch_create_serialized_transition_2.clone()], platform_state, &BlockInfo::default_with_time( platform_state @@ -1688,7 +1683,7 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![documents_batch_create_serialized_preorder_transition_1.clone()], + &[documents_batch_create_serialized_preorder_transition_1.clone()], platform_state, &BlockInfo::default_with_time( platform_state @@ -1717,7 +1712,7 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![documents_batch_create_serialized_transition_1.clone()], + &[documents_batch_create_serialized_transition_1.clone()], platform_state, &BlockInfo::default_with_time( platform_state @@ -1961,6 +1956,7 @@ pub(in crate::execution) mod tests { assert_eq!(second_contender.vote_tally(), Some(0)); } + #[allow(clippy::too_many_arguments)] pub(in crate::execution) fn perform_vote( platform: &mut TempPlatform, platform_state: &Guard>, @@ -2011,7 +2007,7 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![masternode_vote_serialized_transition.clone()], + &[masternode_vote_serialized_transition.clone()], platform_state, &BlockInfo::default(), &transaction, @@ -2040,6 +2036,7 @@ pub(in crate::execution) mod tests { } } + #[allow(clippy::too_many_arguments)] pub(in crate::execution) fn perform_votes( platform: &mut TempPlatform, dpns_contract: &DataContract, @@ -2105,6 +2102,7 @@ pub(in crate::execution) mod tests { masternodes_by_vote_choice } + #[allow(clippy::too_many_arguments)] pub(in crate::execution) fn get_vote_states( platform: &TempPlatform, platform_state: &PlatformState, @@ -2211,6 +2209,7 @@ pub(in crate::execution) mod tests { ) } + #[allow(clippy::too_many_arguments)] pub(in crate::execution) fn get_proved_vote_states( platform: &TempPlatform, platform_state: &PlatformState, @@ -2493,8 +2492,8 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &vec![serialized_state_transition], - &platform_state, + &[serialized_state_transition], + platform_state, &BlockInfo::default(), &transaction, platform_version, @@ -2514,6 +2513,9 @@ pub(in crate::execution) mod tests { } mod keyword_search_contract { + use dpp::consensus::basic::BasicError; + use dpp::consensus::ConsensusError; + use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult::PaidConsensusError; use super::*; // // ────────────────────────────────────────────────────────────────────────── @@ -2891,7 +2893,7 @@ pub(in crate::execution) mod tests { } #[test] - fn owner_can_delete_keyword_document() { + fn owner_can_not_delete_keyword_document() { let platform_version = PlatformVersion::latest(); let mut platform = TestPlatformBuilder::new() .build_with_mock_rpc() @@ -2951,10 +2953,12 @@ pub(in crate::execution) mod tests { None, ) .expect("process"); - assert_matches!( - processing_result.into_execution_results().remove(0), - SuccessfulExecution(..) + processing_result.execution_results().as_slice(), + [PaidConsensusError( + ConsensusError::BasicError(BasicError::InvalidDocumentTransitionActionError { .. }), + _ + )] ); } } diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs index 5b179a9fa35..7a30de4169a 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs @@ -11,7 +11,7 @@ use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -mod v1; +mod v0; impl Drive { /// Creates the documents in the Keyword Search contract for the contract description and @@ -31,12 +31,9 @@ impl Drive { .methods .contract .insert - .insert_contract + .add_description { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract descriptions are not supported in this version", - ))), - 1 => self.add_new_contract_description_v1( + 0 => self.add_new_contract_description_v0( contract_id, owner_id, description, @@ -47,7 +44,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_contract_description".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -71,12 +68,9 @@ impl Drive { .methods .contract .insert - .insert_contract + .add_description { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract descriptions are not supported in this version", - ))), - 1 => self.add_new_contract_description_add_to_operations_v1( + 0 => self.add_new_contract_description_add_to_operations_v0( contract_id, owner_id, description, @@ -88,7 +82,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_contract_description_add_to_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -113,12 +107,9 @@ impl Drive { .methods .contract .insert - .insert_contract + .add_description { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract descriptions are not supported in this version", - ))), - 1 => self.add_new_contract_description_operations_v1( + 0 => self.add_new_contract_description_operations_v0( contract_id, owner_id, description, @@ -130,7 +121,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_contract_description_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs similarity index 91% rename from packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs rename to packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs index 65181745dbd..2c730f8e158 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs @@ -5,6 +5,7 @@ use crate::util::object_size_info::DocumentInfo::DocumentOwnedInfo; use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contracts::keyword_search_contract; use dpp::document::{Document, DocumentV0}; use dpp::fee::fee_result::FeeResult; use dpp::identifier::Identifier; @@ -16,7 +17,7 @@ use std::collections::{BTreeMap, HashMap}; impl Drive { /// Creates the documents in the Keyword Search contract for the contract description and /// returns the fee result - pub(super) fn add_new_contract_description_v1( + pub(super) fn add_new_contract_description_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -27,7 +28,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.add_new_contract_description_add_to_operations_v1( + self.add_new_contract_description_add_to_operations_v0( contract_id, owner_id, description, @@ -50,7 +51,7 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to create /// the documents in the Keyword Search contract for the contract description - pub(super) fn add_new_contract_description_add_to_operations_v1( + pub(super) fn add_new_contract_description_add_to_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -88,7 +89,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to create /// the documents in the Keyword Search contract for the contract description - pub(crate) fn add_new_contract_description_operations_v1( + pub(crate) fn add_new_contract_description_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -107,7 +108,7 @@ impl Drive { let short_description_document_type = contract.document_type_for_name("shortDescription")?; - let short_description_document = self.build_contract_description_document_owned_v1( + let short_description_document = self.build_contract_description_document_owned_v0( contract_id, owner_id, description, @@ -137,7 +138,7 @@ impl Drive { if !short_only { let full_description_document_type = contract.document_type_for_name("fullDescription")?; - let full_description_document = self.build_contract_description_document_owned_v1( + let full_description_document = self.build_contract_description_document_owned_v0( contract_id, owner_id, description, @@ -167,7 +168,7 @@ impl Drive { } /// Creates and returns a contract `description` document for the Keyword Search contract - pub(super) fn build_contract_description_document_owned_v1( + fn build_contract_description_document_owned_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -175,13 +176,6 @@ impl Drive { full_description: bool, block_info: &BlockInfo, ) -> Result { - let owner_nonce = - match self.fetch_identity_nonce(owner_id.into(), true, None, PlatformVersion::latest()) - { - Ok(maybe_nonce) => maybe_nonce.unwrap_or(1), - Err(e) => return Err(e), - }; - let document_type_name = if full_description { "fullDescription".to_string() } else { @@ -189,10 +183,10 @@ impl Drive { }; let document_id = Document::generate_document_id_v0( - &contract_id, + &keyword_search_contract::ID_BYTES.into(), &owner_id, &document_type_name, - &owner_nonce.to_be_bytes(), + contract_id.as_slice(), ); let properties = BTreeMap::from([ @@ -208,7 +202,7 @@ impl Drive { created_at: Some(block_info.time_ms), updated_at: None, transferred_at: None, - created_at_block_height: Some(block_info.height), + created_at_block_height: None, updated_at_block_height: None, transferred_at_block_height: None, created_at_core_block_height: None, diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs index 26425f07479..0f89e9043c0 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/mod.rs @@ -11,7 +11,7 @@ use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -mod v1; +mod v0; impl Drive { /// Creates the documents in the Keyword Search contract for the contract keywords and @@ -26,17 +26,8 @@ impl Drive { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result { - match platform_version - .drive - .methods - .contract - .insert - .insert_contract - { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract keywords are not supported in this version", - ))), - 1 => self.add_new_contract_keywords_v1( + match platform_version.drive.methods.contract.insert.add_keywords { + 0 => self.add_new_contract_keywords_v0( contract_id, owner_id, keywords, @@ -47,7 +38,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_keywords".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -66,17 +57,8 @@ impl Drive { drive_operations: &mut Vec, platform_version: &PlatformVersion, ) -> Result<(), Error> { - match platform_version - .drive - .methods - .contract - .insert - .insert_contract - { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract keywords are not supported in this version", - ))), - 1 => self.add_new_contract_keywords_add_to_operations_v1( + match platform_version.drive.methods.contract.insert.add_keywords { + 0 => self.add_new_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -88,7 +70,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_keywords_add_to_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -108,17 +90,8 @@ impl Drive { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { - match platform_version - .drive - .methods - .contract - .insert - .insert_contract - { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract keywords are not supported in this version", - ))), - 1 => self.add_new_contract_keywords_operations_v1( + match platform_version.drive.methods.contract.insert.add_keywords { + 0 => self.add_new_contract_keywords_operations_v0( contract_id, owner_id, keywords, @@ -129,7 +102,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_new_keywords_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs similarity index 85% rename from packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs rename to packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 9c49185a9cb..5f83da58b5e 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -5,6 +5,7 @@ use crate::util::object_size_info::DocumentInfo::DocumentOwnedInfo; use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contracts::keyword_search_contract; use dpp::document::{Document, DocumentV0}; use dpp::fee::fee_result::FeeResult; use dpp::identifier::Identifier; @@ -16,7 +17,7 @@ use std::collections::{BTreeMap, HashMap}; impl Drive { /// Creates the documents in the Keyword Search contract for the contract keywords and /// returns the fee result - pub(super) fn add_new_contract_keywords_v1( + pub(super) fn add_new_contract_keywords_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -27,7 +28,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.add_new_contract_keywords_add_to_operations_v1( + self.add_new_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -50,7 +51,7 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to create /// the documents in the Keyword Search contract for the contract keywords - pub(super) fn add_new_contract_keywords_add_to_operations_v1( + pub(super) fn add_new_contract_keywords_add_to_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -88,7 +89,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to create /// the documents in the Keyword Search contract for the contract keywords - pub(crate) fn add_new_contract_keywords_operations_v1( + pub(crate) fn add_new_contract_keywords_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -100,17 +101,16 @@ impl Drive { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { - let mut operations: Vec = vec![]; + let mut drive_operations: Vec = vec![]; let contract = self.cache.system_data_contracts.load_keyword_search(); let document_type = contract.document_type_for_name("contractKeywords")?; for keyword in keywords.iter() { - let document = self.build_contract_keyword_document_owned_v1( + let document = self.build_contract_keyword_document_owned_v0( contract_id, owner_id, keyword, // since keywords are unique in the contract, we can use it as entropy - block_info, )?; let ops = self.add_document_for_contract_operations( @@ -124,31 +124,34 @@ impl Drive { }, true, block_info, - &mut None, + &mut Some(&mut drive_operations), estimated_costs_only_with_layer_info, transaction, platform_version, )?; - operations.extend(ops); + drive_operations.extend(ops); } - Ok(operations) + Ok(drive_operations) } /// Creates and returns a `contractKeyword` document for the Keyword Search contract - pub(super) fn build_contract_keyword_document_owned_v1( + pub(super) fn build_contract_keyword_document_owned_v0( &self, contract_id: Identifier, owner_id: Identifier, keyword: &String, - block_info: &BlockInfo, ) -> Result { + let mut entropy = Vec::with_capacity(contract_id.len() + keyword.len()); + entropy.extend_from_slice(contract_id.as_slice()); + entropy.extend_from_slice(keyword.as_bytes()); + let document_id = Document::generate_document_id_v0( - &contract_id, + &keyword_search_contract::ID_BYTES.into(), &owner_id, "contractKeywords", - keyword.as_bytes(), + entropy.as_slice(), ); let properties = BTreeMap::from([ @@ -161,10 +164,10 @@ impl Drive { owner_id, properties, revision: None, - created_at: Some(block_info.time_ms), + created_at: None, updated_at: None, transferred_at: None, - created_at_block_height: Some(block_info.height), + created_at_block_height: None, updated_at_block_height: None, transferred_at_block_height: None, created_at_core_block_height: None, diff --git a/packages/rs-drive/src/drive/contract/update/mod.rs b/packages/rs-drive/src/drive/contract/update/mod.rs index c24eb531f5c..d50a7e7d905 100644 --- a/packages/rs-drive/src/drive/contract/update/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/mod.rs @@ -1 +1,4 @@ mod update_contract; +mod update_description; + +mod update_keywords; diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs index 57263f111b2..b3965fe69b6 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs @@ -20,11 +20,6 @@ use grovedb::batch::KeyInfoPath; use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -#[allow(clippy::too_many_arguments)] -mod update_description; -#[allow(clippy::too_many_arguments)] -mod update_keywords; - impl Drive { /// Updates a data contract. /// @@ -230,7 +225,7 @@ impl Drive { for (token_pos, configuration) in contract.tokens() { let token_id = contract.token_id(*token_pos).ok_or(Error::DataContract( DataContractError::CorruptedDataContract(format!( - "data contract has a token at position {}, but can not find it", + "data contract has a token at position {}, but it can not be found", token_pos )), ))?; diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_description/mod.rs similarity index 81% rename from packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs rename to packages/rs-drive/src/drive/contract/update/update_description/mod.rs index edcecc128a1..4493ee88822 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_description/mod.rs @@ -11,7 +11,7 @@ use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -mod v1; +mod v0; impl Drive { /// Updates the documents in the Keyword Search contract for the contract @@ -31,12 +31,9 @@ impl Drive { .methods .contract .update - .update_contract + .update_description { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract descriptions are not supported in this version", - ))), - 1 => self.update_contract_description_v1( + 0 => self.update_contract_description_v0( contract_id, owner_id, description, @@ -70,13 +67,10 @@ impl Drive { .drive .methods .contract - .insert - .insert_contract + .update + .update_description { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract descriptions are not supported in this version", - ))), - 1 => self.update_contract_description_add_to_operations_v1( + 0 => self.update_contract_description_add_to_operations_v0( contract_id, owner_id, description, @@ -88,7 +82,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_contract_description_add_to_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -112,13 +106,10 @@ impl Drive { .drive .methods .contract - .insert - .insert_contract + .update + .update_description { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract descriptions are not supported in this version", - ))), - 1 => self.update_contract_description_operations_v1( + 0 => self.update_contract_description_operations_v0( contract_id, owner_id, description, @@ -129,7 +120,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_contract_description_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs similarity index 90% rename from packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs rename to packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs index b7eecd11331..e9439504fb9 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_description/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs @@ -19,7 +19,8 @@ use std::collections::HashMap; impl Drive { /// Updates the documents in the Keyword Search contract for the contract /// update description and returns the fee result - pub(super) fn update_contract_description_v1( + #[allow(clippy::too_many_arguments)] + pub(super) fn update_contract_description_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -30,7 +31,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.update_contract_description_add_to_operations_v1( + self.update_contract_description_add_to_operations_v0( contract_id, owner_id, description, @@ -53,7 +54,8 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract description - pub(super) fn update_contract_description_add_to_operations_v1( + #[allow(clippy::too_many_arguments)] + pub(super) fn update_contract_description_add_to_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -91,7 +93,8 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract description - pub(super) fn update_contract_description_operations_v1( + #[allow(clippy::too_many_arguments)] + pub(super) fn update_contract_description_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -105,11 +108,7 @@ impl Drive { ) -> Result, Error> { let mut operations: Vec = vec![]; - let contract = self - .cache - .system_data_contracts - .load_keyword_search() - .clone(); + let contract = self.cache.system_data_contracts.load_keyword_search(); let document_type = contract.document_type_for_name("shortDescription")?; let mut query = DriveDocumentQuery::all_items_query(&contract, document_type, None); @@ -131,7 +130,7 @@ impl Drive { Some(platform_version.protocol_version), )?; - let existing_documents = query_outcome.documents(); + let mut existing_documents = query_outcome.documents_owned(); if existing_documents.len() > 1 { return Err(Error::Drive(DriveError::CorruptedContractIndexes( @@ -141,7 +140,7 @@ impl Drive { if existing_documents.is_empty() { // Add the new one - operations.extend(self.add_new_contract_description_operations_v1( + operations.extend(self.add_new_contract_description_operations_v0( contract_id, owner_id, description, @@ -153,9 +152,9 @@ impl Drive { )?); } else { // Replace the existing one - let document = existing_documents.first().expect("Document should exist"); - let mut new_document = document.clone(); + let mut new_document = existing_documents.remove(0); new_document.set("description", Value::Text(description.clone())); + new_document.set_updated_at(Some(block_info.time_ms)); let info = DocumentAndContractInfo { owned_document_info: OwnedDocumentInfo { diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs b/packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs similarity index 80% rename from packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs rename to packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs index 3b65b078997..9c10581861d 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs @@ -11,7 +11,7 @@ use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; -mod v1; +mod v0; impl Drive { /// Updates the documents in the Keyword Search contract for the contract @@ -30,13 +30,10 @@ impl Drive { .drive .methods .contract - .insert - .insert_contract + .update + .update_keywords { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract keywords are not supported in this version", - ))), - 1 => self.update_contract_keywords_v1( + 0 => self.update_contract_keywords_v0( contract_id, owner_id, keywords, @@ -47,7 +44,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_keywords".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -71,12 +68,9 @@ impl Drive { .methods .contract .update - .update_contract + .update_keywords { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract keywords are not supported in this version", - ))), - 1 => self.update_contract_keywords_add_to_operations_v1( + 0 => self.update_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -88,7 +82,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_keywords_add_to_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } @@ -113,12 +107,9 @@ impl Drive { .methods .contract .update - .update_contract + .update_keywords { - 0 => Err(Error::Drive(DriveError::NotSupported( - "Contract keywords are not supported in this version", - ))), - 1 => self.update_contract_keywords_operations_v1( + 0 => self.update_contract_keywords_operations_v0( contract_id, owner_id, keywords, @@ -129,7 +120,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_keywords_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs similarity index 82% rename from packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs rename to packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs index a219ba93900..bf0687bd92a 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/update_keywords/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs @@ -1,6 +1,5 @@ use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; use crate::drive::Drive; -use crate::error::drive::DriveError; use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; use crate::query::{DriveDocumentQuery, WhereClause, WhereOperator}; @@ -9,16 +8,17 @@ use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::document::DocumentV0Getters; use dpp::fee::fee_result::FeeResult; use dpp::identifier::Identifier; +use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; use dpp::platform_value::Value; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; use platform_version::version::PlatformVersion; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; impl Drive { /// Updates the documents in the Keyword Search contract for the contract /// update keywords and returns the fee result - pub(super) fn update_contract_keywords_v1( + pub(super) fn update_contract_keywords_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -29,7 +29,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result { let mut drive_operations: Vec = vec![]; - self.update_contract_keywords_add_to_operations_v1( + self.update_contract_keywords_add_to_operations_v0( contract_id, owner_id, keywords, @@ -52,7 +52,7 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract keywords - pub(super) fn update_contract_keywords_add_to_operations_v1( + pub(super) fn update_contract_keywords_add_to_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -90,7 +90,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract keywords - pub(super) fn update_contract_keywords_operations_v1( + pub(super) fn update_contract_keywords_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, @@ -105,11 +105,7 @@ impl Drive { let mut operations: Vec = vec![]; // First get the existing keywords so we know which ones we need to delete and which new ones we need to add - let contract = self - .cache - .system_data_contracts - .load_keyword_search() - .clone(); + let contract = self.cache.system_data_contracts.load_keyword_search(); let document_type = contract.document_type_for_name("contractKeywords")?; let mut query = DriveDocumentQuery::all_items_query(&contract, document_type, None); @@ -131,24 +127,16 @@ impl Drive { Some(platform_version.protocol_version), )?; - let mut existing: Vec<(String, Identifier)> = Vec::new(); - for doc in query_outcome.documents() { - let kw = doc - .get("keyword") - .and_then(|v| v.as_str()) - .ok_or_else(|| { - Error::Drive(DriveError::CorruptedDriveState( - "keyword should exist".to_string(), - )) - })? - .to_string(); - existing.push((kw, doc.id())); + let mut existing: BTreeMap = BTreeMap::new(); + for doc in query_outcome.documents_owned() { + let kw = doc.properties().get_string("keyword")?; + existing.insert(kw, doc.id()); } // If an existing keyword is not in the new keyword set, we delete it for (kw, doc_id) in &existing { - if !keywords.iter().any(|k| k == kw) { - operations.extend(self.delete_document_for_contract_operations( + if !keywords.contains(kw) { + operations.extend(self.force_delete_document_for_contract_operations( *doc_id, &contract, document_type, @@ -163,7 +151,7 @@ impl Drive { // Finally, add the new ones let mut keywords_to_add: Vec = Vec::new(); for kw in keywords { - if !existing.iter().any(|(e_kw, _)| e_kw == kw) { + if !existing.contains_key(kw) { keywords_to_add.push(kw.clone()); } } diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/mod.rs index 919e1631d0d..74fefe304d9 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/mod.rs @@ -65,4 +65,56 @@ impl Drive { })), } } + + /// Prepares the operations for deleting a document and will delete even if the contract does + /// not allow for deletion, this is reserved for system data contracts. + /// + /// # Parameters + /// * `document_id`: The ID of the document to delete. + /// * `contract`: The contract that contains the document. + /// * `document_type`: The type of the document. + /// * `previous_batch_operations`: Previous batch operations to include. + /// * `estimated_costs_only_with_layer_info`: Estimated costs with layer info. + /// * `transaction`: The transaction argument. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(Vec)` if the operation was successful. + /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. + #[allow(clippy::too_many_arguments)] + pub(crate) fn force_delete_document_for_contract_operations( + &self, + document_id: Identifier, + contract: &DataContract, + document_type: DocumentTypeRef, + previous_batch_operations: Option<&mut Vec>, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .document + .delete + .delete_document_for_contract_operations + { + 0 => self.force_delete_document_for_contract_operations_v0( + document_id, + contract, + document_type, + previous_batch_operations, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "force_delete_document_for_contract_operations".to_string(), + known_versions: vec![0], + received: version, + })), + } + } } diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs index 97291e4e8e9..740e760e366 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs @@ -49,14 +49,32 @@ impl Drive { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { - let mut batch_operations: Vec = vec![]; - if !document_type.documents_can_be_deleted() { return Err(Error::Drive(DriveError::UpdatingReadOnlyImmutableDocument( "this document type is not mutable and can not be deleted", ))); } + self.force_delete_document_for_contract_operations_v0(document_id, contract, document_type, previous_batch_operations, estimated_costs_only_with_layer_info, transaction, platform_version) + } + + /// Prepares the operations for deleting a document. + #[inline(always)] + #[allow(clippy::too_many_arguments)] + pub(super) fn force_delete_document_for_contract_operations_v0( + &self, + document_id: Identifier, + contract: &DataContract, + document_type: DocumentTypeRef, + previous_batch_operations: Option<&mut Vec>, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut batch_operations: Vec = vec![]; + if document_type.documents_keep_history() { return Err(Error::Drive( DriveError::InvalidDeletionOfDocumentThatKeepsHistory( diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs index a216992f698..a9fc9cbe44f 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs @@ -30,11 +30,15 @@ pub struct DriveContractApplyMethodVersions { pub struct DriveContractInsertMethodVersions { pub add_contract_to_storage: FeatureVersion, pub insert_contract: FeatureVersion, + pub add_description: FeatureVersion, + pub add_keywords: FeatureVersion, } #[derive(Clone, Debug, Default)] pub struct DriveContractUpdateMethodVersions { pub update_contract: FeatureVersion, + pub update_description: FeatureVersion, + pub update_keywords: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs index 67824dafea1..f8f8f3291b4 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs @@ -18,8 +18,14 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V1: DriveContractMethodVersions = insert: DriveContractInsertMethodVersions { add_contract_to_storage: 0, insert_contract: 0, + add_description: 0, + add_keywords: 0, + }, + update: DriveContractUpdateMethodVersions { + update_contract: 0, + update_description: 0, + update_keywords: 0, }, - update: DriveContractUpdateMethodVersions { update_contract: 0 }, costs: DriveContractCostsMethodVersions { add_estimation_costs_for_contract_insertion: 0, }, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs index 9f4565afee3..9ba0cd15ef4 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs @@ -18,8 +18,14 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V2: DriveContractMethodVersions = insert: DriveContractInsertMethodVersions { add_contract_to_storage: 0, insert_contract: 1, // <--- changed to v1 (for token insertion) + add_description: 0, + add_keywords: 0, + }, + update: DriveContractUpdateMethodVersions { + update_contract: 1, // <--- changed to v1 (for token insertion) + update_description: 0, + update_keywords: 0, }, - update: DriveContractUpdateMethodVersions { update_contract: 1 }, // <--- changed to v1 (for token insertion) costs: DriveContractCostsMethodVersions { add_estimation_costs_for_contract_insertion: 0, }, From 723829d6eda603b1e90dc17551c56436356eb309 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 17 Apr 2025 11:59:37 +0700 Subject: [PATCH 42/46] fmt --- .../state_transition/state_transitions/mod.rs | 36 ++++++++++++------- .../insert/add_new_keywords/v0/mod.rs | 2 +- .../v0/mod.rs | 10 +++++- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 8b6d9f0061b..030f6e22b04 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -1191,8 +1191,10 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &[documents_batch_create_serialized_preorder_transition_1.clone(), - documents_batch_create_serialized_preorder_transition_2.clone()], + &[ + documents_batch_create_serialized_preorder_transition_1.clone(), + documents_batch_create_serialized_preorder_transition_2.clone(), + ], platform_state, &BlockInfo::default_with_time( platform_state @@ -1234,8 +1236,10 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &[documents_batch_create_serialized_transition_1.clone(), - documents_batch_create_serialized_transition_2.clone()], + &[ + documents_batch_create_serialized_transition_1.clone(), + documents_batch_create_serialized_transition_2.clone(), + ], platform_state, &BlockInfo::default_with_time( platform_state @@ -1504,8 +1508,10 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &[documents_batch_create_serialized_preorder_transition_1.clone(), - documents_batch_create_serialized_preorder_transition_2.clone()], + &[ + documents_batch_create_serialized_preorder_transition_1.clone(), + documents_batch_create_serialized_preorder_transition_2.clone(), + ], platform_state, &BlockInfo::default_with_time( platform_state @@ -1534,8 +1540,10 @@ pub(in crate::execution) mod tests { let processing_result = platform .platform .process_raw_state_transitions( - &[documents_batch_create_serialized_transition_1.clone(), - documents_batch_create_serialized_transition_2.clone()], + &[ + documents_batch_create_serialized_transition_1.clone(), + documents_batch_create_serialized_transition_2.clone(), + ], platform_state, &BlockInfo::default_with_time( platform_state @@ -2954,11 +2962,13 @@ pub(in crate::execution) mod tests { ) .expect("process"); assert_matches!( - processing_result.execution_results().as_slice(), - [PaidConsensusError( - ConsensusError::BasicError(BasicError::InvalidDocumentTransitionActionError { .. }), - _ - )] + processing_result.execution_results().as_slice(), + [PaidConsensusError( + ConsensusError::BasicError( + BasicError::InvalidDocumentTransitionActionError { .. } + ), + _ + )] ); } } diff --git a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs index 5f83da58b5e..b3f49fb0e2d 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs @@ -146,7 +146,7 @@ impl Drive { let mut entropy = Vec::with_capacity(contract_id.len() + keyword.len()); entropy.extend_from_slice(contract_id.as_slice()); entropy.extend_from_slice(keyword.as_bytes()); - + let document_id = Document::generate_document_id_v0( &keyword_search_contract::ID_BYTES.into(), &owner_id, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs index 740e760e366..55420aceeb7 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_operations/v0/mod.rs @@ -55,7 +55,15 @@ impl Drive { ))); } - self.force_delete_document_for_contract_operations_v0(document_id, contract, document_type, previous_batch_operations, estimated_costs_only_with_layer_info, transaction, platform_version) + self.force_delete_document_for_contract_operations_v0( + document_id, + contract, + document_type, + previous_batch_operations, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ) } /// Prepares the operations for deleting a document. From 55d1b9698bca0429a5daaa0eb6c92b0f2ddf2e2a Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 17 Apr 2025 12:03:00 +0700 Subject: [PATCH 43/46] clippy --- .../src/drive/contract/update/update_description/mod.rs | 3 +++ .../rs-drive/src/drive/contract/update/update_keywords/mod.rs | 3 +++ .../src/drive/contract/update/update_keywords/v0/mod.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/packages/rs-drive/src/drive/contract/update/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_description/mod.rs index 4493ee88822..43e9a4cb48c 100644 --- a/packages/rs-drive/src/drive/contract/update/update_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_description/mod.rs @@ -16,6 +16,7 @@ mod v0; impl Drive { /// Updates the documents in the Keyword Search contract for the contract /// update description and returns the fee result + #[allow(clippy::too_many_arguments)] pub fn update_contract_description( &self, contract_id: Identifier, @@ -52,6 +53,7 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract description + #[allow(clippy::too_many_arguments)] pub fn update_contract_description_add_to_operations( &self, contract_id: Identifier, @@ -90,6 +92,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract description + #[allow(clippy::too_many_arguments)] pub fn update_contract_description_operations( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs b/packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs index 9c10581861d..73d0b6b07c1 100644 --- a/packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_keywords/mod.rs @@ -16,6 +16,7 @@ mod v0; impl Drive { /// Updates the documents in the Keyword Search contract for the contract /// update keywords and returns the fee result + #[allow(clippy::too_many_arguments)] pub fn update_contract_keywords( &self, contract_id: Identifier, @@ -52,6 +53,7 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract keywords + #[allow(clippy::too_many_arguments)] pub fn update_contract_keywords_add_to_operations( &self, contract_id: Identifier, @@ -90,6 +92,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract keywords + #[allow(clippy::too_many_arguments)] pub fn update_contract_keywords_operations( &self, contract_id: Identifier, diff --git a/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs index bf0687bd92a..00c2bf48a99 100644 --- a/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs @@ -18,6 +18,7 @@ use std::collections::{BTreeMap, HashMap}; impl Drive { /// Updates the documents in the Keyword Search contract for the contract /// update keywords and returns the fee result + #[allow(clippy::too_many_arguments)] pub(super) fn update_contract_keywords_v0( &self, contract_id: Identifier, @@ -52,6 +53,7 @@ impl Drive { /// Creates and applies the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract keywords + #[allow(clippy::too_many_arguments)] pub(super) fn update_contract_keywords_add_to_operations_v0( &self, contract_id: Identifier, @@ -90,6 +92,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to update /// the documents in the Keyword Search contract for the contract keywords + #[allow(clippy::too_many_arguments)] pub(super) fn update_contract_keywords_operations_v0( &self, contract_id: Identifier, From 2cd268face2c75420be0f8cdf83ed59517e75868 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 17 Apr 2025 12:19:55 +0700 Subject: [PATCH 44/46] clean up; --- .../data_contract_update/mod.rs | 20 +++++++++++++------ .../contract/update/update_description/mod.rs | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index f61111ab945..114a1864901 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -1993,6 +1993,7 @@ mod tests { mod description_updates { use super::*; + use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; use dpp::{ data_contract::conversion::value::v0::DataContractValueConversionMethodsV0, data_contracts::SystemDataContract, @@ -2206,15 +2207,22 @@ mod tests { }, ); - let res = platform + let mut res = platform .drive .query_documents(query, None, false, None, None) - .unwrap(); + .expect("expected query to succeed") + .documents_owned(); - res.documents() - .iter() - .map(|d| d.get("description").unwrap().as_str().unwrap().to_owned()) - .collect() + if res.is_empty() { + panic!("expected a document description"); + } + + let first_document = res.remove(0); + + first_document + .properties() + .get_string("description") + .expect("expected description to exist") } // ──────────────────────────────────────────────────────────────────────── diff --git a/packages/rs-drive/src/drive/contract/update/update_description/mod.rs b/packages/rs-drive/src/drive/contract/update/update_description/mod.rs index 43e9a4cb48c..b0f8d2af290 100644 --- a/packages/rs-drive/src/drive/contract/update/update_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_description/mod.rs @@ -45,7 +45,7 @@ impl Drive { ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_contract_description".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0], received: version, })), } From 4ecaafd977768f41770327853ed8890714c59023 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 17 Apr 2025 12:29:11 +0700 Subject: [PATCH 45/46] another fix --- .../src/drive/contract/insert/add_description/mod.rs | 7 ++++++- .../src/drive/contract/insert/add_description/v0/mod.rs | 8 ++++++-- .../src/drive/contract/insert/insert_contract/v1/mod.rs | 1 + .../drive/contract/update/update_description/v0/mod.rs | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs index 7a30de4169a..e6c4b2999a2 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/mod.rs @@ -21,6 +21,7 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, description: &String, + short_only: bool, block_info: &BlockInfo, apply: bool, transaction: TransactionArg, @@ -37,6 +38,7 @@ impl Drive { contract_id, owner_id, description, + short_only, block_info, apply, transaction, @@ -57,6 +59,7 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, description: &String, + short_only: bool, block_info: &BlockInfo, apply: bool, transaction: TransactionArg, @@ -74,6 +77,7 @@ impl Drive { contract_id, owner_id, description, + short_only, block_info, apply, transaction, @@ -95,6 +99,7 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, description: &String, + short_only: bool, block_info: &BlockInfo, estimated_costs_only_with_layer_info: &mut Option< HashMap, @@ -113,7 +118,7 @@ impl Drive { contract_id, owner_id, description, - false, + short_only, block_info, estimated_costs_only_with_layer_info, transaction, diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs index 2c730f8e158..f0f44549048 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs @@ -22,6 +22,7 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, description: &String, + short_only: bool, block_info: &BlockInfo, apply: bool, transaction: TransactionArg, @@ -32,6 +33,7 @@ impl Drive { contract_id, owner_id, description, + short_only, block_info, apply, transaction, @@ -56,6 +58,7 @@ impl Drive { contract_id: Identifier, owner_id: Identifier, description: &String, + short_only: bool, block_info: &BlockInfo, apply: bool, transaction: TransactionArg, @@ -68,10 +71,11 @@ impl Drive { Some(HashMap::new()) }; - let batch_operations = self.add_new_contract_description_operations( + let batch_operations = self.add_new_contract_description_operations_v0( contract_id, owner_id, description, + short_only, block_info, &mut estimated_costs_only_with_layer_info, transaction, @@ -89,7 +93,7 @@ impl Drive { /// Creates and returns the LowLeveLDriveOperations needed to create /// the documents in the Keyword Search contract for the contract description - pub(crate) fn add_new_contract_description_operations_v0( + pub(super) fn add_new_contract_description_operations_v0( &self, contract_id: Identifier, owner_id: Identifier, 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 1ed48c28095..9776452ba6b 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 @@ -324,6 +324,7 @@ impl Drive { contract.id(), contract.owner_id(), description, + false, block_info, estimated_costs_only_with_layer_info, transaction, diff --git a/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs index e9439504fb9..0f4b22e3e93 100644 --- a/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs @@ -140,7 +140,7 @@ impl Drive { if existing_documents.is_empty() { // Add the new one - operations.extend(self.add_new_contract_description_operations_v0( + operations.extend(self.add_new_contract_description_operations( contract_id, owner_id, description, From e7f52fe84092989dc2242184f0baa126b2dc8f07 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 17 Apr 2025 12:35:53 +0700 Subject: [PATCH 46/46] fixed revision --- .../src/drive/contract/insert/add_description/v0/mod.rs | 2 +- .../src/drive/contract/update/update_description/v0/mod.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs index f0f44549048..c0b6b955fca 100644 --- a/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs @@ -202,7 +202,7 @@ impl Drive { id: document_id, owner_id, properties, - revision: None, + revision: Some(1), created_at: Some(block_info.time_ms), updated_at: None, transferred_at: None, diff --git a/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs b/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs index 0f4b22e3e93..b672b82c5d6 100644 --- a/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_description/v0/mod.rs @@ -155,6 +155,7 @@ impl Drive { let mut new_document = existing_documents.remove(0); new_document.set("description", Value::Text(description.clone())); new_document.set_updated_at(Some(block_info.time_ms)); + new_document.bump_revision(); let info = DocumentAndContractInfo { owned_document_info: OwnedDocumentInfo {