From c7a1b0fa914edc9cb71ea419385a5cb44e2ba6b1 Mon Sep 17 00:00:00 2001 From: Paul DeLucia <69597248+pauldelucia@users.noreply.github.com> Date: Tue, 7 May 2024 22:36:30 +0530 Subject: [PATCH 1/3] feat: use all current identities for strategy test state transitions (#1820) --- packages/strategy-tests/src/lib.rs | 41 ++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/strategy-tests/src/lib.rs b/packages/strategy-tests/src/lib.rs index 4ed118819c..29ce98f09c 100644 --- a/packages/strategy-tests/src/lib.rs +++ b/packages/strategy-tests/src/lib.rs @@ -42,8 +42,8 @@ use dpp::state_transition::data_contract_update_transition::methods::DataContrac use operations::{DataContractUpdateAction, DataContractUpdateOp}; use platform_version::TryFromPlatformVersioned; use rand::prelude::StdRng; +use rand::seq::SliceRandom; use rand::Rng; -use tracing::error; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use bincode::{Decode, Encode}; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; @@ -413,7 +413,7 @@ impl Strategy { ) { Ok(transitions) => transitions, Err(e) => { - error!("identity_state_transitions_for_block error: {}", e); + tracing::error!("identity_state_transitions_for_block error: {}", e); return (vec![], finalize_block_operations, vec![]); } }; @@ -1202,15 +1202,17 @@ impl Strategy { ) { Ok(contract_factory) => contract_factory, Err(e) => { - error!("Failed to get DataContractFactory while creating random contract: {e}"); + tracing::error!("Failed to get DataContractFactory while creating random contract: {e}"); continue; } }; // Create `count` ContractCreate transitions and push to operations vec for _ in 0..count { - // Get the contract owner_id from loaded_identity and loaded_identity nonce - let identity = ¤t_identities[0]; + // Get the contract owner_id from a random current_identity and identity nonce + let identity = current_identities + .choose(rng) + .expect("Expected to get an identity for ContractCreate"); let identity_nonce = identity_nonce_counter.entry(identity.id()).or_default(); *identity_nonce += 1; @@ -1242,7 +1244,7 @@ impl Strategy { )) } Err(e) => { - error!( + tracing::error!( "Error generating random document type: {:?}", e ); @@ -1261,7 +1263,7 @@ impl Strategy { ) { Ok(contract) => contract, Err(e) => { - error!("Failed to create random data contract: {e}"); + tracing::error!("Failed to create random data contract: {e}"); continue; } }; @@ -1271,7 +1273,9 @@ impl Strategy { { Ok(transition) => transition, Err(e) => { - error!("Failed to create ContractCreate transition: {e}"); + tracing::error!( + "Failed to create ContractCreate transition: {e}" + ); continue; } }; @@ -1293,7 +1297,7 @@ impl Strategy { fn(Identifier, String) -> Result, >, ) { - error!("Error signing state transition: {:?}", e); + tracing::error!("Error signing state transition: {:?}", e); } operations.push(state_transition); @@ -1327,7 +1331,13 @@ impl Strategy { ); contract_ref.increment_version(); - let identity = ¤t_identities[0]; + let identity = current_identities + .iter() + .find(|identity| { + identity.id() == contract_ref.owner_id() + }) + .or_else(|| current_identities.choose(rng)).expect("Expected to get an identity for DataContractUpdate"); + let identity_contract_nonce = contract_nonce_counter .entry((identity.id(), contract_ref.id())) .or_default(); @@ -1336,7 +1346,7 @@ impl Strategy { // Prepare the DataContractUpdateTransition with the updated contract_ref match DataContractUpdateTransition::try_from_platform_versioned((DataContract::V0(contract_ref.clone()), *identity_contract_nonce), platform_version) { Ok(data_contract_update_transition) => { - let identity_public_key = current_identities[0] + let identity_public_key = identity .get_first_public_key_matching( Purpose::AUTHENTICATION, HashSet::from([SecurityLevel::CRITICAL]), @@ -1356,15 +1366,18 @@ impl Strategy { operations.push(state_transition); }, - Err(e) => error!("Error converting data contract to update transition: {:?}", e), + Err(e) => tracing::error!("Error converting data contract to update transition: {:?}", e), } } Err(e) => { - error!("Error generating random document type: {:?}", e) + tracing::error!( + "Error generating random document type: {:?}", + e + ) } } } else { - // Handle the case where the contract is not found in known_contracts + tracing::error!("Contract not found in known_contracts"); } } } From 2b5626363870d6bc340bb383ee1f9178d98367fa Mon Sep 17 00:00:00 2001 From: QuantumExplorer Date: Tue, 7 May 2024 19:42:22 +0200 Subject: [PATCH 2/3] refactor(platform)!: document creation/update/deletion does not refetch contract (#1840) --- .../create_genesis_state/v0/mod.rs | 25 +- .../state_transitions/documents_batch/mod.rs | 26 +- .../tests/strategy_tests/main.rs | 4 +- .../tests/strategy_tests/query.rs | 2 +- .../drive/batch/drive_op_batch/document.rs | 352 ++++-------------- .../src/drive/batch/drive_op_batch/mod.rs | 56 ++- .../document/document_create_transition.rs | 9 +- .../document/document_delete_transition.rs | 18 +- .../document/document_purchase_transition.rs | 7 +- .../document/document_replace_transition.rs | 7 +- .../document/document_transfer_transition.rs | 7 +- .../document_update_price_transition.rs | 7 +- .../delete_document_for_contract/mod.rs | 3 +- .../delete_document_for_contract/v0/mod.rs | 3 +- .../mod.rs | 3 +- .../v0/mod.rs | 3 +- .../delete_document_for_contract_id/mod.rs | 5 +- .../delete_document_for_contract_id/v0/mod.rs | 7 +- .../mod.rs | 5 +- .../v0/mod.rs | 7 +- .../mod.rs | 3 +- .../v0/mod.rs | 3 +- .../mod.rs | 3 +- .../v0/mod.rs | 3 +- .../rs-drive/src/drive/document/delete/mod.rs | 29 -- .../mod.rs | 3 +- .../v0/mod.rs | 3 +- .../rs-drive/src/drive/document/update/mod.rs | 4 +- .../drive/object_size_info/contract_info.rs | 133 +++++++ .../src/drive/object_size_info/mod.rs | 31 +- packages/rs-sdk/src/platform/fetch_many.rs | 2 +- 31 files changed, 326 insertions(+), 447 deletions(-) create mode 100644 packages/rs-drive/src/drive/object_size_info/contract_info.rs diff --git a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v0/mod.rs index 83a50e457d..73795a0aab 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v0/mod.rs @@ -49,7 +49,9 @@ use drive::drive::batch::{ DataContractOperationType, DocumentOperationType, DriveOperation, IdentityOperationType, }; -use drive::drive::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use drive::drive::object_size_info::{ + DataContractInfo, DocumentInfo, DocumentTypeInfo, OwnedDocumentInfo, +}; use drive::query::TransactionArg; use std::borrow::Cow; use std::collections::BTreeMap; @@ -267,18 +269,15 @@ impl Platform { let document_type = contract.document_type_for_name("domain")?; - let operation = - DriveOperation::DocumentOperation(DocumentOperationType::AddDocumentForContract { - document_and_contract_info: DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentInfo::DocumentOwnedInfo((document, None)), - owner_id: None, - }, - contract, - document_type, - }, - override_document: false, - }); + let operation = DriveOperation::DocumentOperation(DocumentOperationType::AddDocument { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentOwnedInfo((document, None)), + owner_id: None, + }, + contract_info: DataContractInfo::BorrowedDataContract(contract), + document_type_info: DocumentTypeInfo::DocumentTypeRef(document_type), + override_document: false, + }); operations.push(operation); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs index 4926564cbb..da5d970161 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs @@ -732,7 +732,7 @@ mod tests { assert_eq!(processing_result.valid_count(), 1); - assert_eq!(processing_result.aggregated_fees().processing_fee, 5081030); + assert_eq!(processing_result.aggregated_fees().processing_fee, 3810570); } #[test] @@ -2014,7 +2014,7 @@ mod tests { assert_eq!(processing_result.aggregated_fees().storage_fee, 0); // There is no storage fee, as there are no indexes that will change - assert_eq!(processing_result.aggregated_fees().processing_fee, 5609930); + assert_eq!(processing_result.aggregated_fees().processing_fee, 4926670); } #[test] @@ -2205,7 +2205,7 @@ mod tests { Some(14992395) ); - assert_eq!(processing_result.aggregated_fees().processing_fee, 9357180); + assert_eq!(processing_result.aggregated_fees().processing_fee, 8622720); let query_sender_results = platform .drive @@ -2742,7 +2742,7 @@ mod tests { assert_eq!(processing_result.valid_count(), 1); - assert_eq!(processing_result.aggregated_fees().processing_fee, 10283900); + assert_eq!(processing_result.aggregated_fees().processing_fee, 9549440); let query_sender_results = platform .drive @@ -3145,7 +3145,7 @@ mod tests { assert_eq!(processing_result.valid_count(), 1); - assert_eq!(processing_result.aggregated_fees().processing_fee, 6814950); + assert_eq!(processing_result.aggregated_fees().processing_fee, 6075290); let query_sender_results = platform .drive @@ -3266,11 +3266,11 @@ mod tests { .change(), &BalanceChange::RemoveFromBalance { required_removed_balance: 123579000, - desired_removed_balance: 128673220, + desired_removed_balance: 127933560, } ); - let original_creation_cost = 128673220; + let original_creation_cost = 127933560; platform .drive @@ -3397,7 +3397,7 @@ mod tests { None ); - assert_eq!(processing_result.aggregated_fees().processing_fee, 6814950); + assert_eq!(processing_result.aggregated_fees().processing_fee, 6075290); let seller_balance = platform .drive @@ -3408,7 +3408,7 @@ mod tests { // the seller should have received 0.1 and already had 0.1 minus the processing fee and storage fee assert_eq!( seller_balance, - dash_to_credits!(0.1) - 6814950 - 216000 - original_creation_cost + dash_to_credits!(0.1) - 6075290 - 216000 - original_creation_cost ); let query_sender_results = platform @@ -3503,7 +3503,7 @@ mod tests { assert_eq!(processing_result.aggregated_fees().storage_fee, 64611000); - assert_eq!(processing_result.aggregated_fees().processing_fee, 10873700); + assert_eq!(processing_result.aggregated_fees().processing_fee, 10134040); assert_eq!( processing_result @@ -3537,7 +3537,7 @@ mod tests { // the seller should have received 0.1 and already had 0.1 minus the processing fee and storage fee assert_eq!( seller_balance, - dash_to_credits!(0.2) - 6814950 - 216000 - original_creation_cost + 22704503 + dash_to_credits!(0.2) - 6075290 - 216000 - original_creation_cost + 22704503 ); let buyers_balance = platform @@ -3547,7 +3547,7 @@ mod tests { .expect("expected that purchaser exists"); // the buyer payed 0.1, but also storage and processing fees - assert_eq!(buyers_balance, dash_to_credits!(0.9) - 10873700 - 64611000); + assert_eq!(buyers_balance, dash_to_credits!(0.9) - 10134040 - 64611000); } #[test] @@ -4413,7 +4413,7 @@ mod tests { assert_eq!(processing_result.valid_count(), 1); - assert_eq!(processing_result.aggregated_fees().processing_fee, 6814950); + assert_eq!(processing_result.aggregated_fees().processing_fee, 6075290); let query_sender_results = platform .drive diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 812cf5f846..43ea171e36 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -1778,7 +1778,7 @@ mod tests { .unwrap() .unwrap() ), - "c0c1f59b535f358448a33c20b419b93bcfa12b05b221f77a7347892f48ca2f16".to_string() + "10fbe38850d752b491305b2587468788acbd6dd130272c5a8844d0da05e3a9cf".to_string() ) } @@ -1903,7 +1903,7 @@ mod tests { .unwrap() .unwrap() ), - "a7be306dcdf58930dc14befa2b78c839d66699cf9d454942ac9c595161ffe99e".to_string() + "9ed86b1ed5d0f7a981cb0ff2f3943603a095a031c463b3389bce8a6f60e2b21e".to_string() ) } diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index 3423bca21c..c8825c7dfe 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -20,7 +20,7 @@ use drive_abci::rpc::core::MockCoreRPCLike; use rand::prelude::SliceRandom; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use strategy_tests::frequency::Frequency; use tenderdash_abci::proto::google::protobuf::Timestamp; use tenderdash_abci::proto::serializers::timestamp::ToMilis; diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs index d26327ff8f..99f5cb5388 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs @@ -1,16 +1,16 @@ use crate::drive::batch::drive_op_batch::DriveLowLevelOperationConverter; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::{DocumentRefAndSerialization, DocumentRefInfo}; -use crate::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; +use crate::drive::object_size_info::{ + DataContractInfo, DocumentAndContractInfo, DocumentTypeInfo, OwnedDocumentInfo, +}; use crate::drive::Drive; -use crate::error::document::DocumentError; use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::DocumentTypeRef; use dpp::data_contract::DataContract; -use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; use dpp::document::Document; use dpp::prelude::Identifier; @@ -51,113 +51,45 @@ pub struct DocumentOperationsForContractDocumentType<'a> { /// Operations on Documents #[derive(Clone, Debug)] pub enum DocumentOperationType<'a> { - /// Deserializes a document and adds it to a contract. - AddSerializedDocumentForContract { - /// The serialized document - serialized_document: &'a [u8], - /// The contract - contract: &'a DataContract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Should we override the document if one already exists? - override_document: bool, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option>, - }, /// Adds a document to a contract matching the desired info. AddDocument { /// The document and contract info, also may contain the owner_id owned_document_info: OwnedDocumentInfo<'a>, - ///DataContract - contract_id: Identifier, + /// Data Contract info to potentially be resolved if needed + contract_info: DataContractInfo<'a>, /// Document type - document_type_name: Cow<'a, String>, + document_type_info: DocumentTypeInfo<'a>, /// Should we override the document if one already exists? override_document: bool, }, - /// Adds a withdrawal document. - AddWithdrawalDocument { + /// Updates a document and returns the associated fee. + UpdateDocument { /// The document and contract info, also may contain the owner_id owned_document_info: OwnedDocumentInfo<'a>, + /// Data Contract info to potentially be resolved if needed + contract_info: DataContractInfo<'a>, + /// Document type + document_type_info: DocumentTypeInfo<'a>, }, - /// Adds a document to a contract. - AddDocumentForContract { + /// Deletes a document + DeleteDocument { + /// The document id + document_id: Identifier, + /// Data Contract info to potentially be resolved if needed + contract_info: DataContractInfo<'a>, + /// Document type + document_type_info: DocumentTypeInfo<'a>, + }, + /// Convenience method to add a withdrawal document. + AddWithdrawalDocument { /// The document and contract info, also may contain the owner_id - document_and_contract_info: DocumentAndContractInfo<'a>, - /// Should we override the document if one already exists? - override_document: bool, + owned_document_info: OwnedDocumentInfo<'a>, }, /// Adds a document to a contract. MultipleDocumentOperationsForSameContractDocumentType { /// The document operations document_operations: DocumentOperationsForContractDocumentType<'a>, }, - /// Deletes a document and returns the associated fee. - DeleteDocumentOfNamedTypeForContractId { - /// The document id - document_id: [u8; 32], - /// The contract id - contract_id: [u8; 32], - /// The name of the document type - document_type_name: Cow<'a, String>, - }, - /// Deletes a document and returns the associated fee. - DeleteDocumentOfNamedTypeForContract { - /// The document id - document_id: [u8; 32], - /// The contract - contract: &'a DataContract, - /// The name of the document type - document_type_name: &'a str, - }, - /// Deletes a document and returns the associated fee. - DeleteDocumentForContract { - /// The document id - document_id: [u8; 32], - /// The contract - contract: &'a DataContract, - /// The name of the document type - document_type: DocumentTypeRef<'a>, - }, - /// Updates a serialized document and returns the associated fee. - UpdateSerializedDocumentForContract { - /// The serialized document - serialized_document: &'a [u8], - /// The contract - contract: &'a DataContract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option>, - }, - /// Updates a document and returns the associated fee. - UpdateDocument { - /// The document and contract info, also may contain the owner_id - owned_document_info: OwnedDocumentInfo<'a>, - /// DataContract - contract_id: Identifier, - /// Document type - document_type_name: Cow<'a, String>, - }, - /// Updates a document and returns the associated fee. - UpdateDocumentForContract { - /// The document to update - document: &'a Document, - /// The document in pre-serialized form - serialized_document: &'a [u8], - /// The contract - contract: &'a DataContract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option>, - }, } impl DriveLowLevelOperationConverter for DocumentOperationType<'_> { @@ -172,65 +104,22 @@ impl DriveLowLevelOperationConverter for DocumentOperationType<'_> { platform_version: &PlatformVersion, ) -> Result, Error> { match self { - DocumentOperationType::AddSerializedDocumentForContract { - serialized_document, - contract, - document_type_name, - owner_id, - override_document, - storage_flags, - } => { - let document_type = contract - .document_type_for_name(document_type_name) - .map_err(ProtocolError::DataContractError)?; - - let document = - Document::from_bytes(serialized_document, document_type, platform_version)?; - - let document_info = - DocumentRefAndSerialization((&document, serialized_document, storage_flags)); - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract, - document_type, - }; - drive.add_document_for_contract_operations( - document_and_contract_info, - override_document, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - ) - } DocumentOperationType::AddDocument { owned_document_info, - contract_id, - document_type_name, + contract_info, + document_type_info, override_document, } => { let mut drive_operations: Vec = vec![]; - let contract_fetch_info = drive - .get_contract_with_fetch_info_and_add_to_operations( - contract_id.into_buffer(), - Some(&block_info.epoch), - true, - transaction, - &mut drive_operations, - platform_version, - )? - .ok_or(Error::Document(DocumentError::DataContractNotFound))?; - - let contract = &contract_fetch_info.contract; - - let document_type = contract - .document_type_for_name(document_type_name.as_str()) - .map_err(ProtocolError::DataContractError)?; + let contract_resolved_info = contract_info.resolve( + drive, + block_info, + transaction, + &mut drive_operations, + platform_version, + )?; + let contract = contract_resolved_info.as_ref(); + let document_type = document_type_info.resolve(contract)?; let document_and_contract_info = DocumentAndContractInfo { owned_document_info, @@ -273,119 +162,59 @@ impl DriveLowLevelOperationConverter for DocumentOperationType<'_> { platform_version, ) } - DocumentOperationType::AddDocumentForContract { - document_and_contract_info, - override_document, - } => drive.add_document_for_contract_operations( - document_and_contract_info, - override_document, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - ), - DocumentOperationType::DeleteDocumentForContract { - document_id, - contract, - document_type, - } => drive.delete_document_for_contract_operations( - document_id, - contract, - document_type, - None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - ), - DocumentOperationType::DeleteDocumentOfNamedTypeForContractId { - document_id, - contract_id, - document_type_name, - } => drive.delete_document_for_contract_id_with_named_type_operations( - document_id, - contract_id, - document_type_name.as_str(), - &block_info.epoch, - None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - ), - DocumentOperationType::DeleteDocumentOfNamedTypeForContract { - document_id, - contract, - document_type_name, - } => drive.delete_document_for_contract_with_named_type_operations( - document_id, - contract, - document_type_name, - None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - ), - DocumentOperationType::UpdateSerializedDocumentForContract { - serialized_document, - contract, - document_type_name, - owner_id, - storage_flags, + DocumentOperationType::UpdateDocument { + owned_document_info, + contract_info, + document_type_info, } => { - let document_type = contract - .document_type_for_name(document_type_name) - .map_err(ProtocolError::DataContractError)?; - - let document = - Document::from_bytes(serialized_document, document_type, platform_version)?; - - let document_info = - DocumentRefAndSerialization((&document, serialized_document, storage_flags)); + let mut drive_operations = vec![]; + let contract_resolved_info = contract_info.resolve( + drive, + block_info, + transaction, + &mut drive_operations, + platform_version, + )?; + let contract = contract_resolved_info.as_ref(); + let document_type = document_type_info.resolve(contract)?; let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, + owned_document_info, contract, document_type, }; - drive.update_document_for_contract_operations( + let mut operations = drive.update_document_for_contract_operations( document_and_contract_info, block_info, &mut None, estimated_costs_only_with_layer_info, transaction, platform_version, - ) + )?; + drive_operations.append(&mut operations); + Ok(drive_operations) } - DocumentOperationType::UpdateDocumentForContract { - document, - serialized_document, - contract, - document_type_name, - owner_id, - storage_flags, + DocumentOperationType::DeleteDocument { + document_id, + contract_info, + document_type_info, } => { - let document_info = - DocumentRefAndSerialization((document, serialized_document, storage_flags)); - - let document_type = contract - .document_type_for_name(document_type_name) - .map_err(ProtocolError::DataContractError)?; + let mut drive_operations: Vec = vec![]; + let contract_resolved_info = contract_info.resolve( + drive, + block_info, + transaction, + &mut drive_operations, + platform_version, + )?; + let contract = contract_resolved_info.as_ref(); + let document_type = document_type_info.resolve(contract)?; - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, + drive.delete_document_for_contract_operations( + document_id, contract, document_type, - }; - drive.update_document_for_contract_operations( - document_and_contract_info, - block_info, - &mut None, + None, estimated_costs_only_with_layer_info, transaction, platform_version, @@ -463,45 +292,6 @@ impl DriveLowLevelOperationConverter for DocumentOperationType<'_> { } Ok(drive_operations) } - DocumentOperationType::UpdateDocument { - owned_document_info, - contract_id, - document_type_name, - } => { - let mut drive_operations = vec![]; - let contract_fetch_info = drive - .get_contract_with_fetch_info_and_add_to_operations( - contract_id.into_buffer(), - Some(&block_info.epoch), - true, - transaction, - &mut drive_operations, - platform_version, - )? - .ok_or(Error::Document(DocumentError::DataContractNotFound))?; - - let contract = &contract_fetch_info.contract; - - let document_type = contract - .document_type_for_name(document_type_name.as_str()) - .map_err(ProtocolError::DataContractError)?; - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info, - contract, - document_type, - }; - let mut operations = drive.update_document_for_contract_operations( - document_and_contract_info, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - platform_version, - )?; - drive_operations.append(&mut operations); - Ok(drive_operations) - } } } } diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs index 7354d38359..a7095f2b6f 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs @@ -203,13 +203,13 @@ mod tests { DocumentOperationsForContractDocumentType, UpdateOperationInfo, }; use crate::drive::batch::DataContractOperationType::ApplyContract; - use crate::drive::batch::DocumentOperationType::AddDocumentForContract; + use crate::drive::batch::DocumentOperationType::AddDocument; use crate::drive::batch::DriveOperation::{DataContractOperation, DocumentOperation}; use crate::drive::contract::paths::contract_root_path; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::DocumentRefInfo; - use crate::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; + use crate::drive::object_size_info::{DataContractInfo, DocumentTypeInfo, OwnedDocumentInfo}; use crate::drive::Drive; use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; @@ -251,18 +251,16 @@ mod tests { ) .expect("expected to get document"); - drive_operations.push(DocumentOperation(AddDocumentForContract { - document_and_contract_info: DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefInfo(( - &dashpay_cr_document, - StorageFlags::optional_default_as_cow(), - )), - owner_id: None, - }, - contract: &contract, - document_type, + drive_operations.push(DocumentOperation(AddDocument { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo(( + &dashpay_cr_document, + StorageFlags::optional_default_as_cow(), + )), + owner_id: None, }, + contract_info: DataContractInfo::BorrowedDataContract(&contract), + document_type_info: DocumentTypeInfo::DocumentTypeRef(document_type), override_document: false, })); @@ -354,17 +352,13 @@ mod tests { ) .expect("expected to get contract"); - drive_operations.push(DocumentOperation(AddDocumentForContract { - document_and_contract_info: DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefInfo((&dashpay_cr_document, None)), - owner_id: None, - }, - contract: &contract, - document_type: contract - .document_type_for_name("contactRequest") - .expect("expected to get document type"), + drive_operations.push(DocumentOperation(AddDocument { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&dashpay_cr_document, None)), + owner_id: None, }, + contract_info: DataContractInfo::BorrowedDataContract(&contract), + document_type_info: DocumentTypeInfo::DocumentTypeNameAsStr("contactRequest"), override_document: false, })); @@ -378,17 +372,13 @@ mod tests { ) .expect("expected to get contract"); - drive_operations.push(DocumentOperation(AddDocumentForContract { - document_and_contract_info: DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefInfo((&dashpay_cr_1_document, None)), - owner_id: None, - }, - contract: &contract, - document_type: contract - .document_type_for_name("contactRequest") - .expect("expected to get document type"), + drive_operations.push(DocumentOperation(AddDocument { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&dashpay_cr_1_document, None)), + owner_id: None, }, + contract_info: DataContractInfo::BorrowedDataContract(&contract), + document_type_info: DocumentTypeInfo::DocumentTypeNameAsStr("contactRequest"), override_document: false, })); diff --git a/packages/rs-drive/src/drive/batch/transitions/document/document_create_transition.rs b/packages/rs-drive/src/drive/batch/transitions/document/document_create_transition.rs index cca4a7dee6..56d3db6c7e 100644 --- a/packages/rs-drive/src/drive/batch/transitions/document/document_create_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/document/document_create_transition.rs @@ -3,7 +3,7 @@ use crate::drive::batch::DriveOperation::{DocumentOperation, IdentityOperation}; use crate::drive::batch::{DocumentOperationType, DriveOperation, IdentityOperationType}; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::DocumentOwnedInfo; -use crate::drive::object_size_info::OwnedDocumentInfo; +use crate::drive::object_size_info::{DocumentTypeInfo, OwnedDocumentInfo}; use crate::error::Error; use dpp::block::epoch::Epoch; @@ -13,6 +13,7 @@ use std::borrow::Cow; use crate::state_transition_action::document::documents_batch::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::document::documents_batch::document_transition::document_create_transition_action::{DocumentCreateTransitionAction, DocumentCreateTransitionActionAccessorsV0, DocumentFromCreateTransitionAction}; use dpp::version::PlatformVersion; +use crate::drive::object_size_info::DataContractInfo::DataContractFetchInfo; impl DriveHighLevelDocumentOperationConverter for DocumentCreateTransitionAction { fn into_high_level_document_drive_operations<'b>( @@ -23,6 +24,8 @@ impl DriveHighLevelDocumentOperationConverter for DocumentCreateTransitionAction ) -> Result>, Error> { let data_contract_id = self.base().data_contract_id(); + let contract_fetch_info = self.base().data_contract_fetch_info(); + let document_type_name = self.base().document_type_name().clone(); let identity_contract_nonce = self.base().identity_contract_nonce(); @@ -43,8 +46,8 @@ impl DriveHighLevelDocumentOperationConverter for DocumentCreateTransitionAction document_info: DocumentOwnedInfo((document, Some(Cow::Owned(storage_flags)))), owner_id: Some(owner_id.into_buffer()), }, - contract_id: data_contract_id, - document_type_name: Cow::Owned(document_type_name), + contract_info: DataContractFetchInfo(contract_fetch_info), + document_type_info: DocumentTypeInfo::DocumentTypeName(document_type_name), override_document: false, }), ]) diff --git a/packages/rs-drive/src/drive/batch/transitions/document/document_delete_transition.rs b/packages/rs-drive/src/drive/batch/transitions/document/document_delete_transition.rs index 816bb1fa84..55ae330832 100644 --- a/packages/rs-drive/src/drive/batch/transitions/document/document_delete_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/document/document_delete_transition.rs @@ -7,11 +7,11 @@ use crate::error::Error; use dpp::block::epoch::Epoch; use dpp::identifier::Identifier; -use std::borrow::Cow; use crate::state_transition_action::document::documents_batch::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::document::documents_batch::document_transition::document_delete_transition_action::DocumentDeleteTransitionAction; use crate::state_transition_action::document::documents_batch::document_transition::document_delete_transition_action::v0::DocumentDeleteTransitionActionAccessorsV0; use dpp::version::PlatformVersion; +use crate::drive::object_size_info::{DataContractInfo, DocumentTypeInfo}; impl DriveHighLevelDocumentOperationConverter for DocumentDeleteTransitionAction { fn into_high_level_document_drive_operations<'b>( @@ -32,13 +32,15 @@ impl DriveHighLevelDocumentOperationConverter for DocumentDeleteTransitionAction contract_id: data_contract_id.into_buffer(), nonce: identity_contract_nonce, }), - DocumentOperation( - DocumentOperationType::DeleteDocumentOfNamedTypeForContractId { - document_id: base.id().to_buffer(), - contract_id: base.data_contract_id().to_buffer(), - document_type_name: Cow::Owned(base.document_type_name_owned()), - }, - ), + DocumentOperation(DocumentOperationType::DeleteDocument { + document_id: base.id(), + contract_info: DataContractInfo::DataContractFetchInfo( + base.data_contract_fetch_info(), + ), + document_type_info: DocumentTypeInfo::DocumentTypeName( + base.document_type_name_owned(), + ), + }), ]) } } diff --git a/packages/rs-drive/src/drive/batch/transitions/document/document_purchase_transition.rs b/packages/rs-drive/src/drive/batch/transitions/document/document_purchase_transition.rs index 97d9cf3816..60ec4c37fa 100644 --- a/packages/rs-drive/src/drive/batch/transitions/document/document_purchase_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/document/document_purchase_transition.rs @@ -3,7 +3,7 @@ use crate::drive::batch::DriveOperation::{DocumentOperation, IdentityOperation}; use crate::drive::batch::{DocumentOperationType, DriveOperation, IdentityOperationType}; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::DocumentOwnedInfo; -use crate::drive::object_size_info::OwnedDocumentInfo; +use crate::drive::object_size_info::{DataContractInfo, DocumentTypeInfo, OwnedDocumentInfo}; use crate::error::Error; use dpp::block::epoch::Epoch; @@ -25,6 +25,7 @@ impl DriveHighLevelDocumentOperationConverter for DocumentPurchaseTransitionActi let identity_contract_nonce = self.base().identity_contract_nonce(); let original_owner_id = self.original_owner_id(); let purchase_amount = self.price(); + let contract_fetch_info = self.base().data_contract_fetch_info(); let document = self.document_owned(); // we are purchasing the document so the new storage flags should be on the new owner @@ -45,8 +46,8 @@ impl DriveHighLevelDocumentOperationConverter for DocumentPurchaseTransitionActi document_info: DocumentOwnedInfo((document, Some(Cow::Owned(storage_flags)))), owner_id: Some(new_document_owner_id.into_buffer()), }, - contract_id: data_contract_id, - document_type_name: Cow::Owned(document_type_name), + contract_info: DataContractInfo::DataContractFetchInfo(contract_fetch_info), + document_type_info: DocumentTypeInfo::DocumentTypeName(document_type_name), }), IdentityOperation(IdentityOperationType::RemoveFromIdentityBalance { identity_id: owner_id.to_buffer(), diff --git a/packages/rs-drive/src/drive/batch/transitions/document/document_replace_transition.rs b/packages/rs-drive/src/drive/batch/transitions/document/document_replace_transition.rs index 58bfaaf1ca..bbfb663e55 100644 --- a/packages/rs-drive/src/drive/batch/transitions/document/document_replace_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/document/document_replace_transition.rs @@ -3,7 +3,7 @@ use crate::drive::batch::DriveOperation::{DocumentOperation, IdentityOperation}; use crate::drive::batch::{DocumentOperationType, DriveOperation, IdentityOperationType}; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::DocumentOwnedInfo; -use crate::drive::object_size_info::OwnedDocumentInfo; +use crate::drive::object_size_info::{DataContractInfo, DocumentTypeInfo, OwnedDocumentInfo}; use crate::error::Error; use dpp::block::epoch::Epoch; @@ -24,6 +24,7 @@ impl DriveHighLevelDocumentOperationConverter for DocumentReplaceTransitionActio let data_contract_id = self.base().data_contract_id(); let document_type_name = self.base().document_type_name().clone(); let identity_contract_nonce = self.base().identity_contract_nonce(); + let contract_fetch_info = self.base().data_contract_fetch_info(); let document = Document::try_from_owned_replace_transition_action(self, owner_id, platform_version)?; @@ -40,8 +41,8 @@ impl DriveHighLevelDocumentOperationConverter for DocumentReplaceTransitionActio document_info: DocumentOwnedInfo((document, Some(Cow::Owned(storage_flags)))), owner_id: Some(owner_id.into_buffer()), }, - contract_id: data_contract_id, - document_type_name: Cow::Owned(document_type_name), + contract_info: DataContractInfo::DataContractFetchInfo(contract_fetch_info), + document_type_info: DocumentTypeInfo::DocumentTypeName(document_type_name), }), ]) } diff --git a/packages/rs-drive/src/drive/batch/transitions/document/document_transfer_transition.rs b/packages/rs-drive/src/drive/batch/transitions/document/document_transfer_transition.rs index e16715f4db..66d0ab4484 100644 --- a/packages/rs-drive/src/drive/batch/transitions/document/document_transfer_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/document/document_transfer_transition.rs @@ -3,7 +3,7 @@ use crate::drive::batch::DriveOperation::{DocumentOperation, IdentityOperation}; use crate::drive::batch::{DocumentOperationType, DriveOperation, IdentityOperationType}; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::DocumentOwnedInfo; -use crate::drive::object_size_info::OwnedDocumentInfo; +use crate::drive::object_size_info::{DataContractInfo, DocumentTypeInfo, OwnedDocumentInfo}; use crate::error::Error; use dpp::block::epoch::Epoch; @@ -24,6 +24,7 @@ impl DriveHighLevelDocumentOperationConverter for DocumentTransferTransitionActi let data_contract_id = self.base().data_contract_id(); let document_type_name = self.base().document_type_name().clone(); let identity_contract_nonce = self.base().identity_contract_nonce(); + let contract_fetch_info = self.base().data_contract_fetch_info(); let document = self.document_owned(); // we are transferring the document so the new storage flags should be on the new owner @@ -44,8 +45,8 @@ impl DriveHighLevelDocumentOperationConverter for DocumentTransferTransitionActi document_info: DocumentOwnedInfo((document, Some(Cow::Owned(storage_flags)))), owner_id: Some(new_document_owner_id.into_buffer()), }, - contract_id: data_contract_id, - document_type_name: Cow::Owned(document_type_name), + contract_info: DataContractInfo::DataContractFetchInfo(contract_fetch_info), + document_type_info: DocumentTypeInfo::DocumentTypeName(document_type_name), }), ]) } diff --git a/packages/rs-drive/src/drive/batch/transitions/document/document_update_price_transition.rs b/packages/rs-drive/src/drive/batch/transitions/document/document_update_price_transition.rs index 835af6aa21..9225d43a58 100644 --- a/packages/rs-drive/src/drive/batch/transitions/document/document_update_price_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/document/document_update_price_transition.rs @@ -3,7 +3,7 @@ use crate::drive::batch::DriveOperation::{DocumentOperation, IdentityOperation}; use crate::drive::batch::{DocumentOperationType, DriveOperation, IdentityOperationType}; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::DocumentOwnedInfo; -use crate::drive::object_size_info::OwnedDocumentInfo; +use crate::drive::object_size_info::{DataContractInfo, DocumentTypeInfo, OwnedDocumentInfo}; use crate::error::Error; use dpp::block::epoch::Epoch; @@ -23,6 +23,7 @@ impl DriveHighLevelDocumentOperationConverter for DocumentUpdatePriceTransitionA let data_contract_id = self.base().data_contract_id(); let document_type_name = self.base().document_type_name().clone(); let identity_contract_nonce = self.base().identity_contract_nonce(); + let fetch_info = self.base().data_contract_fetch_info(); let document = self.document_owned(); let storage_flags = StorageFlags::new_single_epoch(epoch.index, Some(owner_id.to_buffer())); @@ -38,8 +39,8 @@ impl DriveHighLevelDocumentOperationConverter for DocumentUpdatePriceTransitionA document_info: DocumentOwnedInfo((document, Some(Cow::Owned(storage_flags)))), owner_id: Some(owner_id.into_buffer()), }, - contract_id: data_contract_id, - document_type_name: Cow::Owned(document_type_name), + contract_info: DataContractInfo::DataContractFetchInfo(fetch_info), + document_type_info: DocumentTypeInfo::DocumentTypeName(document_type_name), }), ]) } diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/mod.rs index a90d757fdc..fe1d9b0b46 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/mod.rs @@ -10,6 +10,7 @@ use dpp::fee::fee_result::FeeResult; use dpp::version::PlatformVersion; +use dpp::identifier::Identifier; use grovedb::TransactionArg; impl Drive { @@ -30,7 +31,7 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub fn delete_document_for_contract( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type_name: &str, block_info: BlockInfo, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/v0/mod.rs index b9a941c44d..a9f3180a43 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract/v0/mod.rs @@ -5,6 +5,7 @@ use dpp::block::block_info::BlockInfo; use dpp::data_contract::DataContract; use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -15,7 +16,7 @@ impl Drive { #[inline(always)] pub(super) fn delete_document_for_contract_v0( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type_name: &str, block_info: BlockInfo, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/mod.rs index ad521ec087..27df346622 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/mod.rs @@ -6,6 +6,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::DataContract; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -29,7 +30,7 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub fn delete_document_for_contract_apply_and_add_to_operations( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type_name: &str, estimated_costs_only_with_layer_info: Option< diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/v0/mod.rs index 33ec82159d..8fb4846a19 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_apply_and_add_to_operations/v0/mod.rs @@ -3,6 +3,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::DataContract; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -13,7 +14,7 @@ impl Drive { #[inline(always)] pub(super) fn delete_document_for_contract_apply_and_add_to_operations_v0( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type_name: &str, mut estimated_costs_only_with_layer_info: Option< diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/mod.rs index 64009ee3a0..5305f991ac 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/mod.rs @@ -11,6 +11,7 @@ use crate::error::drive::DriveError; use crate::error::Error; use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -33,8 +34,8 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub fn delete_document_for_contract_id( &self, - document_id: [u8; 32], - contract_id: [u8; 32], + document_id: Identifier, + contract_id: Identifier, document_type_name: &str, block_info: BlockInfo, apply: bool, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/v0/mod.rs index 91da9282b7..e7439154c8 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id/v0/mod.rs @@ -13,6 +13,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -22,8 +23,8 @@ impl Drive { #[inline(always)] pub(super) fn delete_document_for_contract_id_v0( &self, - document_id: [u8; 32], - contract_id: [u8; 32], + document_id: Identifier, + contract_id: Identifier, document_type_name: &str, block_info: BlockInfo, apply: bool, @@ -39,7 +40,7 @@ impl Drive { let contract_fetch_info = self .get_contract_with_fetch_info_and_add_to_operations( - contract_id, + contract_id.to_buffer(), Some(&block_info.epoch), true, transaction, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/mod.rs index 0a64f0ccaf..f4a693ebd0 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/mod.rs @@ -6,6 +6,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::block::epoch::Epoch; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -30,8 +31,8 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub fn delete_document_for_contract_id_with_named_type_operations( &self, - document_id: [u8; 32], - contract_id: [u8; 32], + document_id: Identifier, + contract_id: Identifier, document_type_name: &str, epoch: &Epoch, previous_batch_operations: Option<&mut Vec>, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/v0/mod.rs index 87d1ed5e6d..7435b0aaad 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_id_with_named_type_operations/v0/mod.rs @@ -12,6 +12,7 @@ use crate::fee::op::LowLevelDriveOperation; use dpp::block::epoch::Epoch; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -20,8 +21,8 @@ impl Drive { #[inline(always)] pub(super) fn delete_document_for_contract_id_with_named_type_operations_v0( &self, - document_id: [u8; 32], - contract_id: [u8; 32], + document_id: Identifier, + contract_id: Identifier, document_type_name: &str, epoch: &Epoch, previous_batch_operations: Option<&mut Vec>, @@ -33,7 +34,7 @@ impl Drive { ) -> Result, Error> { let mut operations = vec![]; let Some(contract_fetch_info) = self.get_contract_with_fetch_info_and_add_to_operations( - contract_id, + contract_id.to_buffer(), Some(epoch), true, transaction, 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 1abdf5037d..a4fca0aa96 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 @@ -8,6 +8,7 @@ use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::document_type::DocumentTypeRef; use dpp::data_contract::DataContract; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -30,7 +31,7 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub(crate) fn delete_document_for_contract_operations( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type: DocumentTypeRef, previous_batch_operations: Option<&mut Vec>, 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 1adaab41ae..e972831bb1 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 @@ -29,6 +29,7 @@ use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -37,7 +38,7 @@ impl Drive { #[inline(always)] pub(super) fn delete_document_for_contract_operations_v0( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type: DocumentTypeRef, previous_batch_operations: Option<&mut Vec>, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/mod.rs index 66d0fd37cb..195a8f1c75 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/mod.rs @@ -7,6 +7,7 @@ use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::DataContract; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -29,7 +30,7 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub(crate) fn delete_document_for_contract_with_named_type_operations( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type_name: &str, previous_batch_operations: Option<&mut Vec>, diff --git a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/v0/mod.rs index 59b6755ab3..6999b5130f 100644 --- a/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/delete_document_for_contract_with_named_type_operations/v0/mod.rs @@ -12,6 +12,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -20,7 +21,7 @@ impl Drive { #[inline(always)] pub(super) fn delete_document_for_contract_with_named_type_operations_v0( &self, - document_id: [u8; 32], + document_id: Identifier, contract: &DataContract, document_type_name: &str, previous_batch_operations: Option<&mut Vec>, diff --git a/packages/rs-drive/src/drive/document/delete/mod.rs b/packages/rs-drive/src/drive/document/delete/mod.rs index 6fe049c5ff..89c007e59f 100644 --- a/packages/rs-drive/src/drive/document/delete/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/mod.rs @@ -1,32 +1,3 @@ -// MIT LICENSE -// -// Copyright (c) 2021 Dash Core Group -// -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - //! Delete Documents. //! //! This module implements functions in Drive for deleting documents. diff --git a/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/mod.rs index 1dd989ae6a..bf990bf905 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/mod.rs @@ -6,6 +6,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; use grovedb::batch::KeyInfoPath; use grovedb::{EstimatedLayerInformation, TransactionArg}; @@ -28,7 +29,7 @@ impl Drive { /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. pub(in crate::drive::document) fn remove_document_from_primary_storage( &self, - document_id: [u8; 32], + document_id: Identifier, document_type: DocumentTypeRef, contract_documents_primary_key_path: [&[u8]; 5], estimated_costs_only_with_layer_info: &mut Option< diff --git a/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/v0/mod.rs index 24016aa56f..642d5679f4 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_document_from_primary_storage/v0/mod.rs @@ -16,6 +16,7 @@ use crate::error::Error; use crate::fee::op::LowLevelDriveOperation; use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -24,7 +25,7 @@ impl Drive { #[inline(always)] pub(super) fn remove_document_from_primary_storage_v0( &self, - document_id: [u8; 32], + document_id: Identifier, document_type: DocumentTypeRef, contract_documents_primary_key_path: [&[u8]; 5], estimated_costs_only_with_layer_info: &mut Option< diff --git a/packages/rs-drive/src/drive/document/update/mod.rs b/packages/rs-drive/src/drive/document/update/mod.rs index f8090d3b03..74b4681b63 100644 --- a/packages/rs-drive/src/drive/document/update/mod.rs +++ b/packages/rs-drive/src/drive/document/update/mod.rs @@ -456,7 +456,7 @@ mod tests { drive .delete_document_for_contract( - document.id().to_buffer(), + document.id(), &contract, "profile", BlockInfo::default(), @@ -1641,7 +1641,7 @@ mod tests { ) -> FeeResult { drive .delete_document_for_contract( - person.id.to_buffer(), + person.id, contract, "person", block_info, diff --git a/packages/rs-drive/src/drive/object_size_info/contract_info.rs b/packages/rs-drive/src/drive/object_size_info/contract_info.rs new file mode 100644 index 0000000000..4f7691ad3f --- /dev/null +++ b/packages/rs-drive/src/drive/object_size_info/contract_info.rs @@ -0,0 +1,133 @@ +use crate::drive::contract::DataContractFetchInfo; +use crate::drive::Drive; +use crate::error::document::DocumentError; +use crate::error::Error; +use crate::fee::op::LowLevelDriveOperation; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::data_contract::DataContract; +use dpp::identifier::Identifier; +use dpp::ProtocolError; +use grovedb::TransactionArg; +use platform_version::version::PlatformVersion; +use std::sync::Arc; + +/// Represents various forms of accessing or representing a data contract. +/// This enum is used to handle different scenarios in which data contracts +/// might be needed, providing a unified interface to access their data. +#[derive(Clone, Debug)] +pub enum DataContractInfo<'a> { + /// A unique identifier for a data contract. This variant is typically used + /// when only the identity of the data contract is required without needing + /// to access the full contract itself. + DataContractId(Identifier), + + /// Information necessary for fetching a data contract, encapsulated in an + /// `Arc` for thread-safe shared ownership. This variant is used when the + /// data needs to be fetched or is not immediately available. + DataContractFetchInfo(Arc), + + /// A borrowed reference to a data contract. This variant is used for temporary, + /// read-only access to a data contract, avoiding ownership transfer. + BorrowedDataContract(&'a DataContract), + + /// An owned version of a data contract. This variant is used when full ownership + /// and possibly mutability of the data contract is necessary. + OwnedDataContract(DataContract), +} + +impl<'a> DataContractInfo<'a> { + /// Resolve the data contract info into an object that contains the data contract + pub(crate) fn resolve( + self, + drive: &Drive, + block_info: &BlockInfo, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match self { + DataContractInfo::DataContractId(contract_id) => { + let contract_fetch_info = drive + .get_contract_with_fetch_info_and_add_to_operations( + contract_id.into_buffer(), + Some(&block_info.epoch), + true, + transaction, + drive_operations, + platform_version, + )? + .ok_or(Error::Document(DocumentError::DataContractNotFound))?; + Ok(DataContractResolvedInfo::DataContractFetchInfo( + contract_fetch_info, + )) + } + DataContractInfo::DataContractFetchInfo(contract_fetch_info) => Ok( + DataContractResolvedInfo::DataContractFetchInfo(contract_fetch_info), + ), + DataContractInfo::BorrowedDataContract(contract) => { + Ok(DataContractResolvedInfo::BorrowedDataContract(contract)) + } + DataContractInfo::OwnedDataContract(contract) => { + Ok(DataContractResolvedInfo::OwnedDataContract(contract)) + } + } + } +} + +/// Contains resolved data contract information, typically used after initial +/// fetching or retrieval steps have been completed. This enum simplifies handling +/// of data contract states post-retrieval. +#[derive(Clone, Debug)] +pub(crate) enum DataContractResolvedInfo<'a> { + /// Information necessary for fetched data contracts, encapsulated in an + /// `Arc` to ensure thread-safe shared ownership and access. + DataContractFetchInfo(Arc), + + /// A borrowed reference to a resolved data contract. This variant is suitable + /// for scenarios where temporary, read-only access to a data contract is required. + BorrowedDataContract(&'a DataContract), + + /// An owned instance of a data contract. This variant provides full control + /// and mutability over the data contract, suitable for scenarios requiring + /// modifications or extended operations on the data contract. + OwnedDataContract(DataContract), +} +impl<'a> AsRef for DataContractResolvedInfo<'a> { + fn as_ref(&self) -> &DataContract { + match self { + DataContractResolvedInfo::DataContractFetchInfo(fetch_info) => &fetch_info.contract, + DataContractResolvedInfo::BorrowedDataContract(borrowed) => borrowed, + DataContractResolvedInfo::OwnedDataContract(owned) => owned, + } + } +} + +/// Enumerates methods for identifying or referencing document types, accommodating various application needs. +#[derive(Clone, Debug)] +pub enum DocumentTypeInfo<'a> { + /// Contains the document type name as an owned `String`, suitable for dynamic or mutable scenarios. + DocumentTypeName(String), + + /// References the document type name via a borrowed `&'a str`, ideal for static or temporary usage. + DocumentTypeNameAsStr(&'a str), + + /// References a document type that has already been resolved through `DocumentTypeRef`. + DocumentTypeRef(DocumentTypeRef<'a>), +} + +impl<'a> DocumentTypeInfo<'a> { + /// Resolve the data contract info into an object that contains the data contract + pub fn resolve(self, contract: &'a DataContract) -> Result, ProtocolError> { + match self { + DocumentTypeInfo::DocumentTypeName(document_type_name) => contract + .document_type_for_name(document_type_name.as_str()) + .map_err(ProtocolError::DataContractError), + DocumentTypeInfo::DocumentTypeNameAsStr(document_type_name) => contract + .document_type_for_name(document_type_name) + .map_err(ProtocolError::DataContractError), + DocumentTypeInfo::DocumentTypeRef(document_type_ref) => Ok(document_type_ref), + } + } +} diff --git a/packages/rs-drive/src/drive/object_size_info/mod.rs b/packages/rs-drive/src/drive/object_size_info/mod.rs index 91eb8c07cd..7f739bb9b7 100644 --- a/packages/rs-drive/src/drive/object_size_info/mod.rs +++ b/packages/rs-drive/src/drive/object_size_info/mod.rs @@ -1,37 +1,9 @@ -// MIT LICENSE -// -// Copyright (c) 2021 Dash Core Group -// -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - //! Object Size Info //! //! This module defines enums and implements functions relevant to the sizes of objects. //! +mod contract_info; mod deletion_info; mod document_and_contract_info; mod document_info; @@ -44,6 +16,7 @@ mod path_info; mod path_key_element_info; mod path_key_info; +pub use contract_info::*; pub use deletion_info::*; pub use document_and_contract_info::*; pub use document_info::*; diff --git a/packages/rs-sdk/src/platform/fetch_many.rs b/packages/rs-sdk/src/platform/fetch_many.rs index 6bfc96f92f..39446c1f69 100644 --- a/packages/rs-sdk/src/platform/fetch_many.rs +++ b/packages/rs-sdk/src/platform/fetch_many.rs @@ -21,7 +21,7 @@ use dpp::block::epoch::EpochIndex; use dpp::block::extended_epoch_info::ExtendedEpochInfo; use dpp::data_contract::DataContract; use dpp::document::Document; -use dpp::identity::{KeyID, Purpose}; +use dpp::identity::KeyID; use dpp::prelude::{Identifier, IdentityPublicKey}; use dpp::util::deserializer::ProtocolVersion; use dpp::version::ProtocolVersionVoteCount; From 63d06f6aaeb140a462e4c8e45a82774fc73ba806 Mon Sep 17 00:00:00 2001 From: lklimek <842586+lklimek@users.noreply.github.com> Date: Wed, 8 May 2024 00:23:21 +0200 Subject: [PATCH 3/3] refactor(sdk)!: don't return Arc in SdkBuilder (#1838) --- packages/rs-dapi-client/src/dapi_client.rs | 8 +- packages/rs-sdk/examples/read_contract.rs | 16 ++-- packages/rs-sdk/src/mock.rs | 2 +- packages/rs-sdk/src/mock/provider.rs | 6 +- packages/rs-sdk/src/mock/sdk.rs | 6 +- packages/rs-sdk/src/platform/fetch.rs | 4 +- packages/rs-sdk/src/platform/fetch_many.rs | 6 +- packages/rs-sdk/src/sdk.rs | 92 ++++++++++--------- packages/rs-sdk/tests/fetch/broadcast.rs | 3 +- packages/rs-sdk/tests/fetch/config.rs | 6 +- packages/rs-sdk/tests/fetch/mock_fetch.rs | 10 +- .../rs-sdk/tests/fetch/mock_fetch_many.rs | 2 +- 12 files changed, 81 insertions(+), 80 deletions(-) diff --git a/packages/rs-dapi-client/src/dapi_client.rs b/packages/rs-dapi-client/src/dapi_client.rs index f698050304..4c29819e20 100644 --- a/packages/rs-dapi-client/src/dapi_client.rs +++ b/packages/rs-dapi-client/src/dapi_client.rs @@ -3,7 +3,7 @@ use backon::{ExponentialBuilder, Retryable}; use dapi_grpc::mock::Mockable; use dapi_grpc::tonic::async_trait; -use std::sync::RwLock; +use std::sync::{Arc, RwLock}; use std::time::Duration; use tracing::Instrument; @@ -61,9 +61,9 @@ pub trait DapiRequestExecutor { } /// Access point to DAPI. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct DapiClient { - address_list: RwLock, + address_list: Arc>, settings: RequestSettings, pool: ConnectionPool, #[cfg(feature = "dump")] @@ -77,7 +77,7 @@ impl DapiClient { let address_count = 3 * address_list.len(); Self { - address_list: RwLock::new(address_list), + address_list: Arc::new(RwLock::new(address_list)), settings, pool: ConnectionPool::new(address_count), #[cfg(feature = "dump")] diff --git a/packages/rs-sdk/examples/read_contract.rs b/packages/rs-sdk/examples/read_contract.rs index f0a2bf2b75..0f025efd8a 100644 --- a/packages/rs-sdk/examples/read_contract.rs +++ b/packages/rs-sdk/examples/read_contract.rs @@ -1,4 +1,4 @@ -use std::{num::NonZeroUsize, str::FromStr, sync::Arc}; +use std::{num::NonZeroUsize, str::FromStr}; use clap::Parser; use dash_sdk::{mock::provider::GrpcContextProvider, platform::Fetch, Sdk, SdkBuilder}; @@ -58,7 +58,7 @@ async fn main() { } /// Setup Rust SDK -fn setup_sdk(config: &Config) -> Arc { +fn setup_sdk(config: &Config) -> Sdk { // We need to implement a ContextProvider. // Here, we will just use a mock implementation. // Tricky thing here is that this implementation requires SDK, so we have a @@ -66,7 +66,7 @@ fn setup_sdk(config: &Config) -> Arc { // We'll first provide `None` Sdk, and then update it later. // // To modify context provider, we need locks and Arc to overcome ownership rules. - let context_provider = GrpcContextProvider::new( + let mut context_provider = GrpcContextProvider::new( None, &config.server_address, config.core_port, @@ -76,7 +76,6 @@ fn setup_sdk(config: &Config) -> Arc { NonZeroUsize::new(100).expect("quorum public keys cache size"), ) .expect("context provider"); - let context_provider = Arc::new(std::sync::Mutex::new(context_provider)); // Let's build the Sdk. // First, we need an URI of some Dash Platform DAPI host to connect to and use as seed. @@ -87,16 +86,13 @@ fn setup_sdk(config: &Config) -> Arc { .expect("parse uri"); // Now, we create the Sdk with the wallet and context provider. - let sdk = SdkBuilder::new(AddressList::from_iter([uri])) - .with_context_provider(Arc::clone(&context_provider)) + let mut sdk = SdkBuilder::new(AddressList::from_iter([uri])) .build() .expect("cannot build sdk"); // Reconfigure context provider with Sdk - let mut guard = context_provider.lock().expect("lock context provider"); - guard.set_sdk(Some(Arc::clone(&sdk))); - drop(guard); - + context_provider.set_sdk(Some(sdk.clone())); + sdk.set_context_provider(context_provider); // Return the SDK we created sdk } diff --git a/packages/rs-sdk/src/mock.rs b/packages/rs-sdk/src/mock.rs index 7e5208cd4f..b3f1b69c63 100644 --- a/packages/rs-sdk/src/mock.rs +++ b/packages/rs-sdk/src/mock.rs @@ -12,7 +12,7 @@ //! ## Example //! //! ```no_run -//! let sdk = dash_sdk::Sdk::new_mock(); +//! let mut sdk = dash_sdk::Sdk::new_mock(); //! let query = dash_sdk::platform::Identifier::random(); //! sdk.mock().expect_fetch(query, None as Option); //! ``` diff --git a/packages/rs-sdk/src/mock/provider.rs b/packages/rs-sdk/src/mock/provider.rs index 7e0d928c3a..aa5c6f1a66 100644 --- a/packages/rs-sdk/src/mock/provider.rs +++ b/packages/rs-sdk/src/mock/provider.rs @@ -24,7 +24,7 @@ pub struct GrpcContextProvider { /// values set by the user in the caches: `data_contracts_cache`, `quorum_public_keys_cache`. /// /// We use [Arc] as we have circular dependencies between Sdk and ContextProvider. - sdk: Option>, + sdk: Option, /// Data contracts cache. /// @@ -53,7 +53,7 @@ impl GrpcContextProvider { /// /// Sdk can be set later with [`GrpcContextProvider::set_sdk`]. pub fn new( - sdk: Option>, + sdk: Option, core_ip: &str, core_port: u16, core_user: &str, @@ -78,7 +78,7 @@ impl GrpcContextProvider { /// /// Note that if the `sdk` is `None`, the context provider will not be able to fetch data itself and will rely on /// values set by the user in the caches: `data_contracts_cache`, `quorum_public_keys_cache`. - pub fn set_sdk(&mut self, sdk: Option>) { + pub fn set_sdk(&mut self, sdk: Option) { self.sdk = sdk; } /// Set the directory where to store dumped data. diff --git a/packages/rs-sdk/src/mock/sdk.rs b/packages/rs-sdk/src/mock/sdk.rs index 6fadfea695..56cd074095 100644 --- a/packages/rs-sdk/src/mock/sdk.rs +++ b/packages/rs-sdk/src/mock/sdk.rs @@ -34,13 +34,13 @@ use super::MockResponse; /// ## Panics /// /// Can panic on errors. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct MockDashPlatformSdk { from_proof_expectations: BTreeMap>, platform_version: &'static PlatformVersion, dapi: Arc>, prove: bool, - quorum_provider: Option, + quorum_provider: Option>, } impl MockDashPlatformSdk { @@ -68,7 +68,7 @@ impl MockDashPlatformSdk { pub fn quorum_info_dir>(&mut self, dir: P) -> &mut Self { let mut provider = MockContextProvider::new(); provider.quorum_keys_dir(Some(dir.as_ref().to_path_buf())); - self.quorum_provider = Some(provider); + self.quorum_provider = Some(Arc::new(provider)); self } diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 70266354d2..0560524e0e 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -124,7 +124,7 @@ where tracing::trace!(request = ?request, response = ?response, object_type, "fetched object from platform"); let (object, response_metadata): (Option, ResponseMetadata) = - sdk.parse_proof_with_metadata(request, response)?; + sdk.parse_proof_with_metadata(request, response).await?; match object { Some(item) => Ok((item.into(), response_metadata)), @@ -165,7 +165,7 @@ where let object_type = std::any::type_name::().to_string(); tracing::trace!(request = ?request, response = ?response, object_type, "fetched object from platform"); - let object: Option = sdk.parse_proof(request, response)?; + let object: Option = sdk.parse_proof(request, response).await?; match object { Some(item) => Ok(item.into()), diff --git a/packages/rs-sdk/src/platform/fetch_many.rs b/packages/rs-sdk/src/platform/fetch_many.rs index 39446c1f69..aa1db58d35 100644 --- a/packages/rs-sdk/src/platform/fetch_many.rs +++ b/packages/rs-sdk/src/platform/fetch_many.rs @@ -142,7 +142,8 @@ where let object: BTreeMap> = sdk .parse_proof::<>::Request, BTreeMap>>( request, response, - )? + ) + .await? .unwrap_or_default(); Ok(object) @@ -227,7 +228,8 @@ impl FetchMany for Document { // let object: Option> = sdk let documents: BTreeMap> = sdk - .parse_proof::(document_query, response)? + .parse_proof::(document_query, response) + .await? .unwrap_or_default(); Ok(documents) diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index f6f40e14da..bf3618fa75 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -2,7 +2,7 @@ use std::collections::btree_map::Entry; use std::sync::Arc; -use std::{fmt::Debug, num::NonZeroUsize, ops::DerefMut}; +use std::{fmt::Debug, num::NonZeroUsize}; use crate::error::Error; use crate::internal_cache::InternalSdkCache; @@ -33,7 +33,7 @@ use rs_dapi_client::{ use std::path::{Path, PathBuf}; use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(feature = "mocks")] -use tokio::sync::Mutex; +use tokio::sync::{Mutex, MutexGuard}; use tokio_util::sync::{CancellationToken, WaitForCancellationFuture}; /// How many data contracts fit in the cache. @@ -69,9 +69,12 @@ pub type LastQueryTimestamp = u64; /// Sdk is thread safe and can be shared between threads. /// It uses internal locking when needed. /// +/// It is also safe to clone the Sdk. +/// /// ## Examples /// /// See tests/ for examples of using the SDK. +#[derive(Clone)] pub struct Sdk { inner: SdkInstance, /// Use proofs when retrieving data from the platform. @@ -80,14 +83,14 @@ pub struct Sdk { proofs: bool, /// An internal SDK cache managed exclusively by the SDK - internal_cache: InternalSdkCache, + internal_cache: Arc, /// Context provider used by the SDK. /// /// ## Panics /// /// Note that setting this to None can panic. - context_provider: std::sync::Mutex>>, + context_provider: Option>>, /// Cancellation token; once cancelled, all pending requests should be aborted. pub(crate) cancel_token: CancellationToken, @@ -118,7 +121,7 @@ impl Debug for Sdk { /// /// This is used to store the actual Sdk instance, which can be either a real Sdk or a mock Sdk. /// We use it to avoid exposing internals defined below to the public. -#[derive(Debug)] +#[derive(Debug, Clone)] enum SdkInstance { /// Real Sdk, using DAPI with gRPC transport Dapi { @@ -136,7 +139,10 @@ enum SdkInstance { /// Dapi client is wrapped in a tokio [Mutex](tokio::sync::Mutex) as it's used in async context. dapi: Arc>, /// Mock SDK implementation processing mock expectations and responses. - mock: std::sync::Mutex, + mock: Arc>, + + /// Platform version configured for this Sdk + version: &'static PlatformVersion, }, } @@ -146,7 +152,7 @@ impl Sdk { /// This is a helper method that uses [`SdkBuilder`] to initialize the SDK in mock mode. /// /// See also [`SdkBuilder`]. - pub fn new_mock() -> Arc { + pub fn new_mock() -> Self { SdkBuilder::default() .build() .expect("mock should be created") @@ -160,7 +166,7 @@ impl Sdk { /// /// - `R`: Type of the request that was used to fetch the proof. /// - `O`: Type of the object to be retrieved from the proof. - pub(crate) fn parse_proof + MockResponse>( + pub(crate) async fn parse_proof + MockResponse>( &self, request: O::Request, response: O::Response, @@ -169,6 +175,7 @@ impl Sdk { O::Request: Mockable, { self.parse_proof_with_metadata(request, response) + .await .map(|result| result.0) } @@ -180,7 +187,7 @@ impl Sdk { /// /// - `R`: Type of the request that was used to fetch the proof. /// - `O`: Type of the object to be retrieved from the proof. - pub(crate) fn parse_proof_with_metadata + MockResponse>( + pub(crate) async fn parse_proof_with_metadata + MockResponse>( &self, request: O::Request, response: O::Response, @@ -188,11 +195,8 @@ impl Sdk { where O::Request: Mockable, { - let guard = self + let provider = self .context_provider - .lock() - .expect("context provider lock poisoned"); - let provider = guard .as_ref() .ok_or(drive_proof_verifier::Error::ContextProviderNotSet)?; @@ -201,7 +205,10 @@ impl Sdk { O::maybe_from_proof_with_metadata(request, response, self.version(), &provider) } #[cfg(feature = "mocks")] - SdkInstance::Mock { .. } => self.mock().parse_proof_with_metadata(request, response), + SdkInstance::Mock { ref mock, .. } => { + let guard = mock.lock().await; + guard.parse_proof_with_metadata(request, response) + } } } @@ -211,15 +218,19 @@ impl Sdk { /// /// # Panics /// - /// Panics if the `self` instance is not a `Mock` variant. + /// Panics when: + /// + /// * the `self` instance is not a `Mock` variant, + /// * the `self` instance is in use by another thread. #[cfg(feature = "mocks")] - pub fn mock(&self) -> std::sync::MutexGuard { + pub fn mock(&mut self) -> MutexGuard { if let Sdk { inner: SdkInstance::Mock { ref mock, .. }, .. } = self { - mock.lock().expect("mock lock poisoned") + mock.try_lock() + .expect("mock sdk is in use by another thread and connot be reconfigured") } else { panic!("not a mock") } @@ -414,7 +425,7 @@ impl Sdk { match &self.inner { SdkInstance::Dapi { version, .. } => version, #[cfg(feature = "mocks")] - SdkInstance::Mock { .. } => self.mock().version(), + SdkInstance::Mock { version, .. } => version, } } @@ -428,13 +439,9 @@ impl Sdk { /// [ContextProvider] is used to access state information, like data contracts and quorum public keys. /// /// Note that this will overwrite any previous context provider. - pub fn set_context_provider(&self, context_provider: C) { - let mut guard = self - .context_provider - .lock() - .expect("context provider lock poisoned"); - - guard.deref_mut().replace(Box::new(context_provider)); + pub fn set_context_provider(&mut self, context_provider: C) { + self.context_provider + .replace(Arc::new(Box::new(context_provider))); } /// Returns a future that resolves when the Sdk is cancelled (eg. shutdown was requested). @@ -545,6 +552,7 @@ impl Default for SdkBuilder { cancel_token: CancellationToken::new(), version: PlatformVersion::latest(), + #[cfg(feature = "mocks")] dump_dir: None, } @@ -673,36 +681,33 @@ impl SdkBuilder { /// # Errors /// /// This method will return an error if the Sdk cannot be created. - pub fn build(self) -> Result, Error> { + pub fn build(self) -> Result { PlatformVersion::set_current(self.version); - let sdk= match self.addresses { + let sdk= match self.addresses { // non-mock mode Some(addresses) => { let dapi = DapiClient::new(addresses, self.settings); #[cfg(feature = "mocks")] let dapi = dapi.dump_dir(self.dump_dir.clone()); - let sdk= Sdk{ + let mut sdk= Sdk{ inner:SdkInstance::Dapi { dapi, version:self.version }, proofs:self.proofs, - context_provider: std::sync:: Mutex::new(self.context_provider), + context_provider: self.context_provider.map(Arc::new), cancel_token: self.cancel_token, #[cfg(feature = "mocks")] dump_dir: self.dump_dir, internal_cache: Default::default(), }; - let sdk = Arc::new(sdk); - // if context provider is not set correctly (is None), it means we need to fallback to core wallet - let mut ctx_guard = sdk.context_provider.lock().expect("lock poisoned"); - if ctx_guard.is_none() { + if sdk.context_provider.is_none() { #[cfg(feature = "mocks")] if !self.core_ip.is_empty() { tracing::warn!("ContextProvider not set; mocking with Dash Core. \ Please provide your own ContextProvider with SdkBuilder::with_context_provider()."); - let mut context_provider = GrpcContextProvider::new(Some(Arc::clone(&sdk)), + let mut context_provider = GrpcContextProvider::new(Some(sdk.clone()), &self.core_ip, self.core_port, &self.core_user, &self.core_password, self.data_contract_cache_size, self.quorum_public_keys_cache_size)?; #[cfg(feature = "mocks")] @@ -710,7 +715,7 @@ impl SdkBuilder { context_provider.set_dump_dir(sdk.dump_dir.clone()); } - ctx_guard.replace(Box::new(context_provider)); + sdk.context_provider.replace(Arc::new(Box::new(context_provider))); } else{ tracing::warn!( "Configure ContextProvider with Sdk::with_context_provider(); otherwise Sdk will fail"); @@ -719,9 +724,8 @@ impl SdkBuilder { tracing::warn!( "Configure ContextProvider with Sdk::with_context_provider(); otherwise Sdk will fail"); }; - drop(ctx_guard); - Ok(sdk) + sdk }, #[cfg(feature = "mocks")] // mock mode @@ -730,23 +734,23 @@ impl SdkBuilder { // We create mock context provider that will use the mock DAPI client to retrieve data contracts. let context_provider = self.context_provider.unwrap_or(Box::new(MockContextProvider::new())); - let sdk = Sdk { + Sdk { inner:SdkInstance::Mock { - mock: std::sync::Mutex::new( MockDashPlatformSdk::new(self.version, Arc::clone(&dapi), self.proofs)), + mock:Arc::new(Mutex::new( MockDashPlatformSdk::new(self.version, Arc::clone(&dapi), self.proofs))), dapi, + version:self.version, }, dump_dir: self.dump_dir, proofs:self.proofs, internal_cache: Default::default(), - context_provider: std::sync:: Mutex::new( Some(context_provider)), + context_provider:Some(Arc::new(context_provider)), cancel_token: self.cancel_token, - }; - Ok(Arc::new(sdk)) + } }, #[cfg(not(feature = "mocks"))] - None => Err(Error::Config("Mock mode is not available. Please enable `mocks` feature or provide address list.".to_string())), + None => return Err(Error::Config("Mock mode is not available. Please enable `mocks` feature or provide address list.".to_string())), }; - sdk + Ok(sdk) } } diff --git a/packages/rs-sdk/tests/fetch/broadcast.rs b/packages/rs-sdk/tests/fetch/broadcast.rs index ff8b821ab8..b6566bc0b1 100644 --- a/packages/rs-sdk/tests/fetch/broadcast.rs +++ b/packages/rs-sdk/tests/fetch/broadcast.rs @@ -20,7 +20,6 @@ mod online { let cfg = Config::new(); let sdk = cfg.setup_api("test_wait_timeout").await; - let sdk_ref: &Sdk = sdk.as_ref(); let request: WaitForStateTransitionResultRequest = WaitForStateTransitionResultRequestV0 { prove: false, @@ -36,7 +35,7 @@ mod online { // we add few millis to duration to give chance to the server to time out before we kill request let response = tokio::time::timeout( TIMEOUT + Duration::from_millis(100), - request.execute(sdk_ref, settings), + request.execute(&sdk, settings), ) .await .expect("expected request timeout, got tokio timeout"); diff --git a/packages/rs-sdk/tests/fetch/config.rs b/packages/rs-sdk/tests/fetch/config.rs index d4b0c5132f..839f3dec9d 100644 --- a/packages/rs-sdk/tests/fetch/config.rs +++ b/packages/rs-sdk/tests/fetch/config.rs @@ -6,7 +6,7 @@ use dpp::prelude::Identifier; use rs_dapi_client::AddressList; use serde::Deserialize; -use std::{path::PathBuf, str::FromStr, sync::Arc}; +use std::{path::PathBuf, str::FromStr}; /// Existing document ID /// @@ -144,7 +144,7 @@ impl Config { /// expectations from different tests. /// /// When empty string is provided, expectations are stored in the root of the dump directory. - pub async fn setup_api(&self, namespace: &str) -> Arc { + pub async fn setup_api(&self, namespace: &str) -> dash_sdk::Sdk { let dump_dir = match namespace.is_empty() { true => self.dump_dir.clone(), false => self.dump_dir.join(sanitize_filename::sanitize(namespace)), @@ -194,7 +194,7 @@ impl Config { // offline testing takes precedence over network testing #[cfg(feature = "offline-testing")] let sdk = { - let mock_sdk = dash_sdk::SdkBuilder::new_mock() + let mut mock_sdk = dash_sdk::SdkBuilder::new_mock() .build() .expect("initialize api"); diff --git a/packages/rs-sdk/tests/fetch/mock_fetch.rs b/packages/rs-sdk/tests/fetch/mock_fetch.rs index 1f735e5e54..a5d4916077 100644 --- a/packages/rs-sdk/tests/fetch/mock_fetch.rs +++ b/packages/rs-sdk/tests/fetch/mock_fetch.rs @@ -22,7 +22,7 @@ use dpp::{ #[tokio::test] /// Given some identity, when I fetch it using mock API, then I get the same identity async fn test_mock_fetch_identity() { - let sdk = Sdk::new_mock(); + let mut sdk = Sdk::new_mock(); let expected: Identity = Identity::from(IdentityV0::default()); let query = expected.id(); @@ -43,7 +43,7 @@ async fn test_mock_fetch_identity() { #[tokio::test] /// When I define mock expectation twice for the same request, second call ends with error async fn test_mock_fetch_duplicate_expectation() { - let sdk = Sdk::new_mock(); + let mut sdk = Sdk::new_mock(); let expected: Identity = Identity::from(IdentityV0::default()); let expected2 = @@ -72,7 +72,7 @@ async fn test_mock_fetch_duplicate_expectation() { #[tokio::test] /// Given some random identity ID, when I fetch it using mock API, then I get None async fn test_mock_fetch_identity_not_found() { - let sdk = Sdk::new_mock(); + let mut sdk = Sdk::new_mock(); let id = Identifier::random(); @@ -91,7 +91,7 @@ async fn test_mock_fetch_identity_not_found() { /// Given some data contract, when I fetch it by ID, I get it. #[tokio::test] async fn test_mock_fetch_data_contract() { - let sdk = Sdk::new_mock(); + let mut sdk = Sdk::new_mock(); let document_type: DocumentType = mock_document_type(); let expected = mock_data_contract(Some(&document_type)); @@ -114,7 +114,7 @@ async fn test_mock_fetch_data_contract() { async fn test_mock_fetch_document() { use dpp::document::DocumentV0Getters; - let sdk = Sdk::new_mock(); + let mut sdk = Sdk::new_mock(); let document_type: DocumentType = mock_document_type(); let data_contract = mock_data_contract(Some(&document_type)); diff --git a/packages/rs-sdk/tests/fetch/mock_fetch_many.rs b/packages/rs-sdk/tests/fetch/mock_fetch_many.rs index 1663ad8aa5..fdf3811d8d 100644 --- a/packages/rs-sdk/tests/fetch/mock_fetch_many.rs +++ b/packages/rs-sdk/tests/fetch/mock_fetch_many.rs @@ -19,7 +19,7 @@ use dpp::{ /// document. #[tokio::test] async fn test_mock_document_fetch_many() { - let sdk = Sdk::new_mock(); + let mut sdk = Sdk::new_mock(); let document_type: DocumentType = mock_document_type(); let data_contract = mock_data_contract(Some(&document_type));