From 7a010eae2949ea268fea84611a016464f3216716 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 00:46:42 +0700 Subject: [PATCH 01/10] feat(platform): fees for data contract creation and update --- .../document_type/class_methods/mod.rs | 6 +- .../src/data_contract/document_type/mod.rs | 2 +- .../rs-dpp/src/data_contract/methods/mod.rs | 1 + .../methods/registration_cost/mod.rs | 84 +++++++++ .../methods/registration_cost/v1/mod.rs | 159 ++++++++++++++++++ packages/rs-dpp/src/fee/fee_result/mod.rs | 2 +- packages/rs-dpp/src/validation/operations.rs | 16 +- .../src/execution/check_tx/v0/mod.rs | 65 ++++--- .../execute_event/v0/mod.rs | 151 +++++++++++------ .../validate_fees_of_event/v0/mod.rs | 8 +- .../execution/types/execution_event/mod.rs | 52 ++++++ .../v0/mod.rs | 16 +- .../data_contract_create/mod.rs | 132 +++++++++++---- .../data_contract_update/mod.rs | 32 ++-- .../dpp_versions/dpp_contract_versions/mod.rs | 1 + .../dpp_versions/dpp_contract_versions/v1.rs | 1 + .../dpp_versions/dpp_contract_versions/v2.rs | 1 + .../src/version/fee/data_contract/mod.rs | 46 ----- .../fee/data_contract_registration/mod.rs | 21 +++ .../fee/data_contract_registration/v1.rs | 15 ++ .../fee/data_contract_registration/v2.rs | 15 ++ .../fee/data_contract_validation/mod.rs | 14 ++ .../v1.rs | 4 +- .../src/version/fee/mod.rs | 14 +- .../rs-platform-version/src/version/fee/v1.rs | 6 +- .../rs-platform-version/src/version/fee/v2.rs | 23 +++ .../rs-platform-version/src/version/v9.rs | 4 +- 27 files changed, 696 insertions(+), 195 deletions(-) create mode 100644 packages/rs-dpp/src/data_contract/methods/registration_cost/mod.rs create mode 100644 packages/rs-dpp/src/data_contract/methods/registration_cost/v1/mod.rs delete mode 100644 packages/rs-platform-version/src/version/fee/data_contract/mod.rs create mode 100644 packages/rs-platform-version/src/version/fee/data_contract_registration/mod.rs create mode 100644 packages/rs-platform-version/src/version/fee/data_contract_registration/v1.rs create mode 100644 packages/rs-platform-version/src/version/fee/data_contract_registration/v2.rs create mode 100644 packages/rs-platform-version/src/version/fee/data_contract_validation/mod.rs rename packages/rs-platform-version/src/version/fee/{data_contract => data_contract_validation}/v1.rs (77%) create mode 100644 packages/rs-platform-version/src/version/fee/v2.rs diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs index 77a2dca60c6..bfad96e4a76 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs @@ -9,7 +9,7 @@ mod create_document_types_from_document_schemas; mod try_from_schema; #[inline] -fn consensus_or_protocol_data_contract_error( +pub(crate) fn consensus_or_protocol_data_contract_error( data_contract_error: DataContractError, ) -> ProtocolError { #[cfg(feature = "validation")] @@ -25,7 +25,9 @@ fn consensus_or_protocol_data_contract_error( } #[inline] -fn consensus_or_protocol_value_error(platform_value_error: platform_value::Error) -> ProtocolError { +pub(crate) fn consensus_or_protocol_value_error( + platform_value_error: platform_value::Error, +) -> ProtocolError { #[cfg(feature = "validation")] { ProtocolError::ConsensusError( diff --git a/packages/rs-dpp/src/data_contract/document_type/mod.rs b/packages/rs-dpp/src/data_contract/document_type/mod.rs index b7b22fdff63..165afc0e254 100644 --- a/packages/rs-dpp/src/data_contract/document_type/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/mod.rs @@ -38,7 +38,7 @@ pub const EMPTY_TREE_STORAGE_SIZE: usize = 33; pub const MAX_INDEX_SIZE: usize = 255; pub const STORAGE_FLAGS_SIZE: usize = 2; -mod property_names { +pub(crate) mod property_names { pub const DOCUMENTS_KEEP_HISTORY: &str = "documentsKeepHistory"; pub const DOCUMENTS_MUTABLE: &str = "documentsMutable"; diff --git a/packages/rs-dpp/src/data_contract/methods/mod.rs b/packages/rs-dpp/src/data_contract/methods/mod.rs index 279eafce441..04f79db8876 100644 --- a/packages/rs-dpp/src/data_contract/methods/mod.rs +++ b/packages/rs-dpp/src/data_contract/methods/mod.rs @@ -1,4 +1,5 @@ mod equal_ignoring_time_based_fields; +mod registration_cost; pub mod schema; #[cfg(feature = "validation")] pub mod validate_document; diff --git a/packages/rs-dpp/src/data_contract/methods/registration_cost/mod.rs b/packages/rs-dpp/src/data_contract/methods/registration_cost/mod.rs new file mode 100644 index 00000000000..aed872ccf12 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/methods/registration_cost/mod.rs @@ -0,0 +1,84 @@ +mod v1; + +use crate::data_contract::serialized_version::DataContractInSerializationFormat; +use crate::data_contract::DataContract; +use crate::ProtocolError; +use platform_version::version::PlatformVersion; + +impl DataContract { + /// Returns the registration cost of the data contract based on the current platform version + /// and the number of associated search keywords. + /// + /// This method dispatches to a version-specific implementation based on the + /// platform version configuration. If the version is unrecognized, it returns a version mismatch error. + /// + /// # Arguments + /// - `platform_version`: A reference to the platform version, used to determine which + /// registration cost algorithm to apply. + /// + /// # Returns + /// - `Ok(u64)`: The total registration cost in credits for this contract. + /// - `Err(ProtocolError)`: If the platform version is unrecognized or if the fee computation overflows. + /// + /// # Version Behavior + /// - Version 0: Always returns `0` (used before protocol version 9, ie before 2.0, where registration cost was not charged). + /// - Version 1: Uses a detailed cost model based on document types, indexes, tokens, and keyword count. + pub fn registration_cost( + &self, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .dpp + .contract_versions + .methods + .registration_cost + { + 0 => Ok(0), // Before 2.0 it's just 0 (There was some validation cost) + 1 => Ok(self.registration_cost_v1(platform_version)), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "DataContract::registration_cost".to_string(), + known_versions: vec![0, 1], + received: version, + }), + } + } +} + +impl DataContractInSerializationFormat { + /// Returns the registration cost of the data contract based on the current platform version + /// and the number of associated search keywords. + /// + /// This method dispatches to a version-specific implementation based on the + /// platform version configuration. If the version is unrecognized, it returns a version mismatch error. + /// + /// # Arguments + /// - `platform_version`: A reference to the platform version, used to determine which + /// registration cost algorithm to apply. + /// + /// # Returns + /// - `Ok(u64)`: The total registration cost in credits for this contract. + /// - `Err(ProtocolError)`: If the platform version is unrecognized or if the fee computation overflows. + /// + /// # Version Behavior + /// - Version 0: Always returns `0` (used before protocol version 9, ie before 2.0, where registration cost was not charged). + /// - Version 1: Uses a detailed cost model based on document types, indexes, tokens, and keyword count. + pub fn registration_cost( + &self, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .dpp + .contract_versions + .methods + .registration_cost + { + 0 => Ok(0), // Before 2.0 it's just 0 (There was some validation cost) + 1 => Ok(self.registration_cost_v1(platform_version)), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "DataContract::registration_cost".to_string(), + known_versions: vec![0, 1], + received: version, + }), + } + } +} diff --git a/packages/rs-dpp/src/data_contract/methods/registration_cost/v1/mod.rs b/packages/rs-dpp/src/data_contract/methods/registration_cost/v1/mod.rs new file mode 100644 index 00000000000..6dce1253630 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/methods/registration_cost/v1/mod.rs @@ -0,0 +1,159 @@ +use crate::data_contract::accessors::v0::DataContractV0Getters; +use crate::data_contract::accessors::v1::DataContractV1Getters; +use crate::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; +use crate::data_contract::associated_token::token_distribution_rules::accessors::v0::TokenDistributionRulesV0Getters; +use crate::data_contract::document_type::accessors::DocumentTypeV0Getters; +use crate::data_contract::document_type::Index; +use crate::data_contract::serialized_version::DataContractInSerializationFormat; +use crate::fee::Credits; +use crate::prelude::DataContract; +use platform_value::Value; +use platform_version::version::PlatformVersion; + +impl DataContract { + /// Computes the registration cost of a data contract based on its document types, + /// indexes, token configurations, and keyword count. + /// + /// # Parameters + /// - `platform_version`: A reference to the current platform version providing fee parameters. + /// + /// # Returns + /// - `Ok(Credits)`: The total registration cost in credits if all additions are overflow-safe. + /// - `Err(ProtocolError)`: If any arithmetic operation results in overflow. + /// + /// # Fee Components + /// - Base contract registration fee. + /// - Per document type registration fee. + /// - Per index registration fee (unique and non-unique). + /// - Token registration fee per token. + /// - Additional fees for tokens using perpetual or pre-programmed distribution. + /// - Search keyword fees (`keyword_count * search_keyword_fee`). + pub(super) fn registration_cost_v1(&self, platform_version: &PlatformVersion) -> Credits { + let fee_version = &platform_version.fee_version.data_contract_registration; + let mut cost = fee_version.base_contract_registration_fee; + + for document_type in self.document_types().values() { + cost = cost.saturating_add(fee_version.document_type_registration_fee); + + for index in document_type.indexes().values() { + let base_index_fee = if index.contested_index.is_some() { + fee_version.document_type_base_contested_index_registration_fee + } else if index.unique { + fee_version.document_type_base_unique_index_registration_fee + } else { + fee_version.document_type_base_non_unique_index_registration_fee + }; + + cost = cost.saturating_add(base_index_fee); + } + } + + for token_config in self.tokens().values() { + cost = cost.saturating_add(fee_version.token_registration_fee); + + if token_config + .distribution_rules() + .perpetual_distribution() + .is_some() + { + cost = cost.saturating_add(fee_version.token_uses_perpetual_distribution_fee); + } + + if token_config + .distribution_rules() + .pre_programmed_distribution() + .is_some() + { + cost = cost.saturating_add(fee_version.token_uses_pre_programmed_distribution_fee); + } + } + + let keyword_cost = fee_version + .search_keyword_fee + .saturating_mul(self.keywords().len() as u64); + + cost = cost.saturating_add(keyword_cost); + + cost + } +} + +impl DataContractInSerializationFormat { + /// Computes the registration cost of a data contract based on its document types, + /// indexes, token configurations, and keyword count. + /// + /// # Parameters + /// - `platform_version`: A reference to the current platform version providing fee parameters. + /// + /// # Returns + /// - `Ok(Credits)`: The total registration cost in credits if all additions are overflow-safe. + /// - `Err(ProtocolError)`: If any arithmetic operation results in overflow. + /// + /// # Fee Components + /// - Base contract registration fee. + /// - Per document type registration fee. + /// - Per index registration fee (unique and non-unique). + /// - Token registration fee per token. + /// - Additional fees for tokens using perpetual or pre-programmed distribution. + /// - Search keyword fees (`keyword_count * search_keyword_fee`). + pub(super) fn registration_cost_v1(&self, platform_version: &PlatformVersion) -> Credits { + let fee_version = &platform_version.fee_version.data_contract_registration; + let mut cost = fee_version.base_contract_registration_fee; + + for document_type_schema in self.document_schemas().values() { + cost = cost.saturating_add(fee_version.document_type_registration_fee); + + // If this is not okay the registration will fail on basic validation + if let Ok(schema_map) = document_type_schema.to_map() { + // Initialize indices + if let Ok(Some(index_values)) = Value::inner_optional_array_slice_value( + schema_map, + crate::data_contract::document_type::property_names::INDICES, + ) { + for index_value in index_values { + if let Ok(index_value_map) = index_value.to_map() { + if let Ok(index) = Index::try_from(index_value_map.as_slice()) { + let base_index_fee = if index.contested_index.is_some() { + fee_version.document_type_base_contested_index_registration_fee + } else if index.unique { + fee_version.document_type_base_unique_index_registration_fee + } else { + fee_version.document_type_base_non_unique_index_registration_fee + }; + cost = cost.saturating_add(base_index_fee); + } + } + } + } + }; + } + + for token_config in self.tokens().values() { + cost = cost.saturating_add(fee_version.token_registration_fee); + + if token_config + .distribution_rules() + .perpetual_distribution() + .is_some() + { + cost = cost.saturating_add(fee_version.token_uses_perpetual_distribution_fee); + } + + if token_config + .distribution_rules() + .pre_programmed_distribution() + .is_some() + { + cost = cost.saturating_add(fee_version.token_uses_pre_programmed_distribution_fee); + } + } + + let keyword_cost = fee_version + .search_keyword_fee + .saturating_mul(self.keywords().len() as u64); + + cost = cost.saturating_add(keyword_cost); + + cost + } +} diff --git a/packages/rs-dpp/src/fee/fee_result/mod.rs b/packages/rs-dpp/src/fee/fee_result/mod.rs index f0fbbc41a2b..b87c9f77856 100644 --- a/packages/rs-dpp/src/fee/fee_result/mod.rs +++ b/packages/rs-dpp/src/fee/fee_result/mod.rs @@ -210,7 +210,7 @@ impl FeeResult { /// Convenience method to get total fee pub fn total_base_fee(&self) -> Credits { - self.storage_fee + self.processing_fee + self.storage_fee.saturating_add(self.processing_fee) } /// Convenience method to get required removed balance diff --git a/packages/rs-dpp/src/validation/operations.rs b/packages/rs-dpp/src/validation/operations.rs index 477f1eb06a1..abcf1140255 100644 --- a/packages/rs-dpp/src/validation/operations.rs +++ b/packages/rs-dpp/src/validation/operations.rs @@ -14,19 +14,19 @@ impl ProtocolValidationOperation { ProtocolValidationOperation::DocumentTypeSchemaValidationForSize(size) => { platform_version .fee_version - .data_contract + .data_contract_validation .document_type_base_fee + *size * platform_version .fee_version - .data_contract - .document_type_size_fee + .data_contract_validation + .document_type_schema_size_fee } ProtocolValidationOperation::DocumentTypeSchemaPropertyValidation(properties_count) => { *properties_count * platform_version .fee_version - .data_contract + .data_contract_validation .document_type_per_property_fee } ProtocolValidationOperation::DocumentTypeSchemaIndexValidation( @@ -37,21 +37,21 @@ impl ProtocolValidationOperation { *index_properties_count * platform_version .fee_version - .data_contract + .data_contract_validation .document_type_unique_index_per_property_fee + platform_version .fee_version - .data_contract + .data_contract_validation .document_type_base_unique_index_fee } else { *index_properties_count * platform_version .fee_version - .data_contract + .data_contract_validation .document_type_non_unique_index_per_property_fee + platform_version .fee_version - .data_contract + .data_contract_validation .document_type_base_non_unique_index_fee } } 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 3e794714efd..94caa353ba5 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 @@ -459,7 +459,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -559,7 +559,7 @@ mod tests { 166, 203, 222, 4, 64, 31, 215, 199, 149, 151, 190, 246, 251, 44, ]), public_keys: BTreeMap::from([(1, key.clone())]), - balance: 1000000000, + balance: 25_000_000_000, // 0.25 Dash revision: 0, } .into(); @@ -602,7 +602,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -630,7 +630,10 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2489210); + assert_eq!( + processing_result.aggregated_fees().processing_fee, + 24002489210 + ); let check_result = platform .check_tx( @@ -709,7 +712,7 @@ mod tests { 166, 203, 222, 4, 64, 31, 215, 199, 149, 151, 190, 246, 251, 44, ]), public_keys: BTreeMap::from([(1, key.clone())]), - balance: 1000000000, + balance: 27_000_000_000, revision: 0, } .into(); @@ -803,7 +806,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -953,7 +956,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); assert_eq!(validation_result.data.unwrap().priority, 10000); @@ -1068,7 +1071,7 @@ mod tests { 166, 203, 222, 4, 64, 31, 215, 199, 149, 151, 190, 246, 251, 44, ]), public_keys: BTreeMap::from([(1, key.clone())]), - balance: 1000000000, + balance: 25_000_000_000, // 0.25 Dash revision: 0, } .into(); @@ -1107,7 +1110,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); assert_eq!(validation_result.data.unwrap().priority, 10000); @@ -1141,7 +1144,11 @@ 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, 4978420); + // Plus we have 24_000_000_000 in base costs + assert_eq!( + processing_result.aggregated_fees().processing_fee, + 24004978420 + ); let check_result = platform .check_tx( @@ -1222,7 +1229,7 @@ mod tests { 166, 203, 222, 4, 64, 31, 215, 199, 149, 151, 190, 246, 251, 44, ]), public_keys: BTreeMap::from([(1, key.clone())]), - balance: 200000000, // we have enough balance only for 1 insertion (this is where this test is different) + balance: 24_200_000_000, // we have enough balance only for 1 insertion (this is where this test is different) revision: 0, } .into(); @@ -1258,7 +1265,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -1456,7 +1463,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -1569,7 +1576,7 @@ mod tests { 166, 203, 222, 4, 64, 31, 215, 199, 149, 151, 190, 246, 251, 44, ]), public_keys: BTreeMap::from([(1, key.clone())]), - balance: 1000000000, + balance: 100_000_000_000, // 1.0 Dash revision: 0, } .into(); @@ -1613,7 +1620,10 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2489210); + assert_eq!( + processing_result.aggregated_fees().processing_fee, + 24002489210 + ); platform .drive @@ -1666,7 +1676,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -1699,7 +1709,7 @@ mod tests { assert_eq!( update_processing_result.aggregated_fees().processing_fee, - 2504030 + 27002504030 ); let check_result = platform @@ -1915,7 +1925,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -2025,7 +2035,7 @@ mod tests { 166, 203, 222, 4, 64, 31, 215, 199, 149, 151, 190, 246, 251, 44, ]), public_keys: BTreeMap::from([(1, key.clone())]), - balance: 1000000000, + balance: 100_000_000_000, // 1 Dash revision: 0, } .into(); @@ -2069,7 +2079,10 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2489210); + assert_eq!( + processing_result.aggregated_fees().processing_fee, + 24002489210 + ); platform .drive @@ -2160,7 +2173,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let check_result = platform .check_tx( @@ -2425,7 +2438,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); } #[test] @@ -2560,7 +2573,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let transaction = platform.drive.grove.start_transaction(); @@ -2709,7 +2722,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let transaction = platform.drive.grove.start_transaction(); @@ -2994,7 +3007,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let transaction = platform.drive.grove.start_transaction(); @@ -3296,7 +3309,7 @@ mod tests { ) .expect("expected to check tx"); - assert!(validation_result.errors.is_empty()); + assert_eq!(validation_result.errors.as_slice(), &[]); let transaction = platform.drive.grove.start_transaction(); diff --git a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs index 87004687898..90bab997f7e 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs @@ -13,14 +13,85 @@ use dpp::block::block_info::BlockInfo; use dpp::consensus::ConsensusError; use dpp::fee::default_costs::CachedEpochIndexFeeVersions; use dpp::fee::fee_result::FeeResult; +use dpp::fee::Credits; +use dpp::identity::PartialIdentity; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::version::PlatformVersion; use drive::drive::identity::update::apply_balance_change_outcome::ApplyBalanceChangeOutcomeV0Methods; use drive::grovedb::Transaction; +use drive::util::batch::DriveOperation; impl Platform where C: CoreRPCLike, { + fn paid_function( + &self, + mut fee_validation_result: ConsensusValidationResult, + identity: PartialIdentity, + operations: Vec, + execution_operations: Vec, + user_fee_increase: UserFeeIncrease, + additional_fixed_fee_cost: Option, + block_info: &BlockInfo, + mut consensus_errors: Vec, + transaction: &Transaction, + platform_version: &PlatformVersion, + previous_fee_versions: &CachedEpochIndexFeeVersions, + ) -> Result { + if fee_validation_result.is_valid_with_data() { + //todo: make this into an atomic event with partial batches + let mut individual_fee_result = self + .drive + .apply_drive_operations( + operations, + true, + block_info, + Some(transaction), + platform_version, + Some(previous_fee_versions), + ) + .map_err(Error::Drive)?; + + ValidationOperation::add_many_to_fee_result( + &execution_operations, + &mut individual_fee_result, + platform_version, + )?; + + individual_fee_result.apply_user_fee_increase(user_fee_increase); + + if let Some(additional_fixed_fee_cost) = additional_fixed_fee_cost { + individual_fee_result.processing_fee = individual_fee_result + .processing_fee + .saturating_add(additional_fixed_fee_cost); + } + + let balance_change = individual_fee_result.into_balance_change(identity.id); + + let outcome = self.drive.apply_balance_change_from_fee_to_identity( + balance_change, + Some(transaction), + platform_version, + )?; + + if consensus_errors.is_empty() { + Ok(SuccessfulPaidExecution( + Some(fee_validation_result.into_data()?), + outcome.actual_fee_paid_owned(), + )) + } else { + Ok(UnsuccessfulPaidExecution( + Some(fee_validation_result.into_data()?), + outcome.actual_fee_paid_owned(), + consensus_errors, + )) + } + } else { + consensus_errors.append(&mut fee_validation_result.errors); + Ok(UnpaidConsensusExecutionError(consensus_errors)) + } + } /// Executes the given `event` based on the `block_info` and `transaction`. /// /// This function takes an `ExecutionEvent`, `BlockInfo`, and `Transaction` as input and performs @@ -75,62 +146,46 @@ where execution_operations, user_fee_increase, .. + } => { + // We can unwrap here because we have the match right above + let fee_validation_result = maybe_fee_validation_result.unwrap(); + self.paid_function( + fee_validation_result, + identity, + operations, + execution_operations, + user_fee_increase, + None, + block_info, + consensus_errors, + transaction, + platform_version, + previous_fee_versions, + ) } - | ExecutionEvent::Paid { + ExecutionEvent::Paid { identity, operations, execution_operations, + additional_fixed_fee_cost, user_fee_increase, .. } => { // We can unwrap here because we have the match right above - let mut fee_validation_result = maybe_fee_validation_result.unwrap(); - if fee_validation_result.is_valid_with_data() { - //todo: make this into an atomic event with partial batches - let mut individual_fee_result = self - .drive - .apply_drive_operations( - operations, - true, - block_info, - Some(transaction), - platform_version, - Some(previous_fee_versions), - ) - .map_err(Error::Drive)?; - - ValidationOperation::add_many_to_fee_result( - &execution_operations, - &mut individual_fee_result, - platform_version, - )?; - - individual_fee_result.apply_user_fee_increase(user_fee_increase); - - let balance_change = individual_fee_result.into_balance_change(identity.id); - - let outcome = self.drive.apply_balance_change_from_fee_to_identity( - balance_change, - Some(transaction), - platform_version, - )?; - - if consensus_errors.is_empty() { - Ok(SuccessfulPaidExecution( - Some(fee_validation_result.into_data()?), - outcome.actual_fee_paid_owned(), - )) - } else { - Ok(UnsuccessfulPaidExecution( - Some(fee_validation_result.into_data()?), - outcome.actual_fee_paid_owned(), - consensus_errors, - )) - } - } else { - consensus_errors.append(&mut fee_validation_result.errors); - Ok(UnpaidConsensusExecutionError(consensus_errors)) - } + let fee_validation_result = maybe_fee_validation_result.unwrap(); + self.paid_function( + fee_validation_result, + identity, + operations, + execution_operations, + user_fee_increase, + additional_fixed_fee_cost, + block_info, + consensus_errors, + transaction, + platform_version, + previous_fee_versions, + ) } // This is for Partially used Asset Locks // NOT used for identity create or identity top up diff --git a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs index 04e8f0f503e..b8810cec48a 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs @@ -101,6 +101,7 @@ where removed_balance, operations, execution_operations, + additional_fixed_fee_cost: additional_fee_cost, user_fee_increase, } => { let balance = identity.balance.ok_or(Error::Execution( @@ -131,7 +132,12 @@ where estimated_fee_result.apply_user_fee_increase(*user_fee_increase); // TODO: Should take into account refunds as well - let required_balance = estimated_fee_result.total_base_fee(); + let mut required_balance = estimated_fee_result.total_base_fee(); + + if let Some(additional_fee_cost) = additional_fee_cost { + required_balance += *additional_fee_cost; + } + if balance_after_principal_operation >= required_balance { Ok(ConsensusValidationResult::new_with_data( estimated_fee_result, diff --git a/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs b/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs index a0eb4605360..8c85e10f796 100644 --- a/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs @@ -33,6 +33,8 @@ pub(in crate::execution) enum ExecutionEvent<'a> { operations: Vec>, /// the execution operations that we must also pay for execution_operations: Vec, + /// Additional fee cost, these are processing fees where the user fee increase does not apply + additional_fixed_fee_cost: Option, /// the fee multiplier that the user agreed to, 0 means 100% of the base fee, 1 means 101% user_fee_increase: UserFeeIncrease, }, @@ -135,6 +137,7 @@ impl ExecutionEvent<'_> { removed_balance: Some(removed_balance), operations, execution_operations: execution_context.operations_consume(), + additional_fixed_fee_cost: None, user_fee_increase, }) } else { @@ -154,6 +157,7 @@ impl ExecutionEvent<'_> { removed_balance: Some(removed_balance), operations, execution_operations: execution_context.operations_consume(), + additional_fixed_fee_cost: None, user_fee_increase, }) } else { @@ -173,6 +177,7 @@ impl ExecutionEvent<'_> { removed_balance, operations, execution_operations: execution_context.operations_consume(), + additional_fixed_fee_cost: None, user_fee_increase, }) } else { @@ -193,6 +198,52 @@ impl ExecutionEvent<'_> { .contested_document_single_vote_cost, }) } + StateTransitionAction::DataContractCreateAction(data_contract_create_action) => { + let user_fee_increase = action.user_fee_increase(); + let registration_cost = data_contract_create_action + .data_contract_ref() + .registration_cost(platform_version)?; + let operations = + action.into_high_level_drive_operations(epoch, platform_version)?; + if let Some(identity) = identity { + Ok(ExecutionEvent::Paid { + identity, + removed_balance: None, + operations, + execution_operations: execution_context.operations_consume(), + additional_fixed_fee_cost: Some(registration_cost), + user_fee_increase, + }) + } else { + Err(Error::Execution(ExecutionError::CorruptedCodeExecution( + "partial identity should be present for other state transitions", + ))) + } + } + StateTransitionAction::DataContractUpdateAction(data_contract_update_action) => { + let user_fee_increase = action.user_fee_increase(); + // The update cost pays for the whole contract again, that's fine for now. + // It would be a lot of work to fix this, so we'll just go with this for now. + let registration_cost = data_contract_update_action + .data_contract_ref() + .registration_cost(platform_version)?; + let operations = + action.into_high_level_drive_operations(epoch, platform_version)?; + if let Some(identity) = identity { + Ok(ExecutionEvent::Paid { + identity, + removed_balance: None, + operations, + execution_operations: execution_context.operations_consume(), + additional_fixed_fee_cost: Some(registration_cost), + user_fee_increase, + }) + } else { + Err(Error::Execution(ExecutionError::CorruptedCodeExecution( + "partial identity should be present for other state transitions", + ))) + } + } _ => { let user_fee_increase = action.user_fee_increase(); let operations = @@ -203,6 +254,7 @@ impl ExecutionEvent<'_> { removed_balance: None, operations, execution_operations: execution_context.operations_consume(), + additional_fixed_fee_cost: None, user_fee_increase, }) } else { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_simple_pre_check_balance/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_simple_pre_check_balance/v0/mod.rs index 9a9e2f8901f..59599801284 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_simple_pre_check_balance/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_simple_pre_check_balance/v0/mod.rs @@ -2,6 +2,8 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use dpp::consensus::state::identity::IdentityInsufficientBalanceError; use dpp::identity::PartialIdentity; +use dpp::state_transition::data_contract_create_transition::accessors::DataContractCreateTransitionAccessorsV0; +use dpp::state_transition::data_contract_update_transition::accessors::DataContractUpdateTransitionAccessorsV0; use dpp::state_transition::StateTransition; use dpp::validation::SimpleConsensusValidationResult; use dpp::version::PlatformVersion; @@ -21,17 +23,27 @@ impl ValidateSimplePreCheckBalanceV0 for StateTransition { platform_version: &PlatformVersion, ) -> Result { let amount = match self { - StateTransition::DataContractCreate(_) => { + StateTransition::DataContractCreate(data_contract_create_transition) => { platform_version .fee_version .state_transition_min_fees .contract_create + .saturating_add( + data_contract_create_transition + .data_contract() + .registration_cost(platform_version)?, + ) } - StateTransition::DataContractUpdate(_) => { + StateTransition::DataContractUpdate(data_contract_update_transition) => { platform_version .fee_version .state_transition_min_fees .contract_update + .saturating_add( + data_contract_update_transition + .data_contract() + .registration_cost(platform_version)?, + ) } StateTransition::Batch(_) => { platform_version 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 9810a027ae2..a3b98f6e8a4 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 @@ -223,6 +223,70 @@ mod tests { let platform_state = platform.state.load(); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(2.0)); + + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", + None, + None, + false, //no need to validate the data contracts in tests for drive + platform_version, + ) + .expect("expected to get json based contract"); + + let data_contract_create_transition = DataContractCreateTransition::new_from_data_contract( + data_contract, + 1, + &identity.into_partial_identity_info(), + key.id(), + &signer, + platform_version, + None, + ) + .expect("expect to create documents batch transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &[data_contract_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + } + + #[test] + fn test_data_contract_creation_with_contested_unique_index_old_version_has_low_fees() { + let platform_version = PlatformVersion::get(8).unwrap(); + let mut platform = TestPlatformBuilder::new() + .with_initial_protocol_version(8) + .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( @@ -286,7 +350,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(2.0)); let data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index-with-contract-id.json", @@ -349,7 +413,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(2.0)); let data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index-and-other-unique-index.json", @@ -428,7 +492,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -521,7 +585,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -649,7 +713,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -743,7 +807,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, contract_signer, contract_key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency.json", @@ -848,7 +912,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, contract_signer, contract_key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency.json", @@ -954,7 +1018,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _signer_2, _key_2) = setup_identity(&mut platform, 93, dash_to_credits!(0.5)); @@ -1060,7 +1124,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, contract_signer, contract_key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (token_contract_owner_id, _, _) = setup_identity(&mut platform, 11, dash_to_credits!(0.1)); @@ -1183,7 +1247,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -1303,7 +1367,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 5456, dash_to_credits!(0.1)); @@ -1487,7 +1551,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -1581,7 +1645,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 564, dash_to_credits!(0.1)); @@ -1694,7 +1758,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 564, dash_to_credits!(0.1)); @@ -1808,7 +1872,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -1916,7 +1980,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -2015,7 +2079,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -2150,7 +2214,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, contract_signer, contract_key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (token_contract_owner_id, _, _) = setup_identity(&mut platform, 11, dash_to_credits!(0.1)); @@ -2277,7 +2341,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -2395,7 +2459,7 @@ mod tests { let platform_state = platform.state.load(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/basic-token/basic-token.json", @@ -2503,7 +2567,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -2634,7 +2698,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -2762,7 +2826,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -2891,7 +2955,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -3019,7 +3083,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -3147,7 +3211,7 @@ mod tests { let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); @@ -3291,7 +3355,7 @@ mod tests { 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)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // Load the base contract JSON and convert it to `DataContract` let data_contract = json_document_to_contract_with_ids( @@ -3373,7 +3437,7 @@ mod tests { 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)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // Load the base contract JSON and convert it to `DataContract` let data_contract = json_document_to_contract_with_ids( @@ -3457,7 +3521,7 @@ mod tests { let platform_state = platform.state.load(); // Create identity - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // Load the base contract JSON and convert it to `DataContract` let data_contract = json_document_to_contract_with_ids( @@ -3531,7 +3595,7 @@ mod tests { .set_genesis_state(); let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/keyword_test/keyword_base_contract.json", @@ -3602,7 +3666,7 @@ mod tests { 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)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // Load the base contract JSON and convert to `DataContract` let data_contract = json_document_to_contract_with_ids( @@ -3801,7 +3865,7 @@ mod tests { .set_genesis_state(); let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // --- mutate the contract --- let mut contract_value = base_contract_value_with_keyword(platform_version); @@ -3856,7 +3920,7 @@ mod tests { .set_genesis_state(); let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut contract_value = base_contract_value_with_keyword(platform_version); // 101 chars – valid for the contract (max 10 000) but exceeds the @@ -3913,7 +3977,7 @@ mod tests { .set_genesis_state(); let platform_state = platform.state.load(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let mut contract_value = base_contract_value_with_keyword(platform_version); contract_value["description"] = 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 5f6663790c8..88d48caa5c8 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 @@ -610,7 +610,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let card_game_path = "tests/supporting_files/contract/crypto-card-game/crypto-card-game-direct-purchase-creation-restricted-to-owner.json"; @@ -714,7 +714,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -837,7 +837,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -966,7 +966,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -1080,7 +1080,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity_2, _, _) = setup_identity(&mut platform, 928, dash_to_credits!(0.1)); @@ -1234,7 +1234,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -1336,7 +1336,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let (identity2, _signer2, _key2) = setup_identity(&mut platform, 93, dash_to_credits!(0.2)); @@ -1436,7 +1436,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = PlatformVersion::latest(); @@ -1542,7 +1542,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -1647,7 +1647,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -1734,7 +1734,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = platform_state @@ -2108,7 +2108,7 @@ mod tests { .build_with_mock_rpc() .set_initial_state_structure(); let (identity, signer, key) = - setup_identity(&mut platform, 1234, dash_to_credits!(0.1)); + setup_identity(&mut platform, 1234, dash_to_credits!(1.0)); let platform_state = platform.state.load(); let platform_version = PlatformVersion::latest(); @@ -2452,7 +2452,7 @@ mod tests { .set_genesis_state(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(10.0)); // create initial contract with one keyword so update is allowed let (cid, _) = create_contract_with_keywords( @@ -2529,7 +2529,7 @@ mod tests { .build_with_mock_rpc() .set_genesis_state(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // initial contract with two keywords let (cid, _) = create_contract_with_keywords( @@ -2832,7 +2832,7 @@ mod tests { .set_genesis_state(); let (identity, signer, key) = - setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // create initial contract with description so update is allowed let (cid, _) = create_contract_with_description( @@ -2894,7 +2894,7 @@ mod tests { .build_with_mock_rpc() .set_genesis_state(); - let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(1.0)); // initial contract with description let (cid, _) = create_contract_with_description( diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs index fae14c1ed5c..80a573de920 100644 --- a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs @@ -25,6 +25,7 @@ pub struct DataContractMethodVersions { pub schema: FeatureVersion, pub validate_groups: FeatureVersion, pub equal_ignoring_time_fields: FeatureVersion, + pub registration_cost: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs index c7060f812e7..4cbe0a93817 100644 --- a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs @@ -21,6 +21,7 @@ pub const CONTRACT_VERSIONS_V1: DPPContractVersions = DPPContractVersions { schema: 0, validate_groups: 0, equal_ignoring_time_fields: 0, + registration_cost: 0, }, document_type_versions: DocumentTypeVersions { index_versions: DocumentTypeIndexVersions { diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v2.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v2.rs index ff8fa7c824f..3c11b5b5fc9 100644 --- a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v2.rs +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v2.rs @@ -21,6 +21,7 @@ pub const CONTRACT_VERSIONS_V2: DPPContractVersions = DPPContractVersions { schema: 0, validate_groups: 0, equal_ignoring_time_fields: 0, + registration_cost: 1, //changed to version 1 }, document_type_versions: DocumentTypeVersions { index_versions: DocumentTypeIndexVersions { diff --git a/packages/rs-platform-version/src/version/fee/data_contract/mod.rs b/packages/rs-platform-version/src/version/fee/data_contract/mod.rs deleted file mode 100644 index 96921030e1c..00000000000 --- a/packages/rs-platform-version/src/version/fee/data_contract/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -use bincode::{Decode, Encode}; - -pub mod v1; - -#[derive(Clone, Debug, Default, Encode, Decode, PartialEq, Eq)] -pub struct FeeDataContractValidationVersion { - pub document_type_base_fee: u64, - pub document_type_size_fee: u64, - pub document_type_per_property_fee: u64, - pub document_type_base_non_unique_index_fee: u64, - pub document_type_non_unique_index_per_property_fee: u64, - pub document_type_base_unique_index_fee: u64, - pub document_type_unique_index_per_property_fee: u64, -} - -#[cfg(test)] -mod tests { - use super::FeeDataContractValidationVersion; - - #[test] - // If this test failed, then a new field was added in FeeDataContractValidationVersion. And the corresponding eq needs to be updated as well - fn test_fee_data_contract_validation_fees_version_equality() { - let version1 = FeeDataContractValidationVersion { - document_type_base_fee: 1, - document_type_size_fee: 2, - document_type_per_property_fee: 3, - document_type_base_non_unique_index_fee: 4, - document_type_non_unique_index_per_property_fee: 5, - document_type_base_unique_index_fee: 6, - document_type_unique_index_per_property_fee: 7, - }; - - let version2 = FeeDataContractValidationVersion { - document_type_base_fee: 1, - document_type_size_fee: 2, - document_type_per_property_fee: 3, - document_type_base_non_unique_index_fee: 4, - document_type_non_unique_index_per_property_fee: 5, - document_type_base_unique_index_fee: 6, - document_type_unique_index_per_property_fee: 7, - }; - - // This assertion will check if all fields are considered in the equality comparison - assert_eq!(version1, version2, "FeeDataContractValidationVersion equality test failed. If a field was added or removed, update the Eq implementation."); - } -} diff --git a/packages/rs-platform-version/src/version/fee/data_contract_registration/mod.rs b/packages/rs-platform-version/src/version/fee/data_contract_registration/mod.rs new file mode 100644 index 00000000000..aa3eeb7940f --- /dev/null +++ b/packages/rs-platform-version/src/version/fee/data_contract_registration/mod.rs @@ -0,0 +1,21 @@ +use bincode::{Decode, Encode}; + +pub mod v1; +pub mod v2; + +/// These are the fee costs for various actions excluding validation +/// Re-Validation will happen on data contract update which is why we don't bundle them +/// together. +#[derive(Clone, Debug, Default, Encode, Decode, PartialEq, Eq)] +pub struct FeeDataContractRegistrationVersion { + pub base_contract_registration_fee: u64, + pub document_type_registration_fee: u64, + pub document_type_base_non_unique_index_registration_fee: u64, + pub document_type_base_unique_index_registration_fee: u64, + /// All contested indexes are unique, but if the index is contested you only apply this fee + pub document_type_base_contested_index_registration_fee: u64, + pub token_registration_fee: u64, + pub token_uses_perpetual_distribution_fee: u64, + pub token_uses_pre_programmed_distribution_fee: u64, + pub search_keyword_fee: u64, +} diff --git a/packages/rs-platform-version/src/version/fee/data_contract_registration/v1.rs b/packages/rs-platform-version/src/version/fee/data_contract_registration/v1.rs new file mode 100644 index 00000000000..03950cf5d63 --- /dev/null +++ b/packages/rs-platform-version/src/version/fee/data_contract_registration/v1.rs @@ -0,0 +1,15 @@ +use crate::version::fee::data_contract_registration::FeeDataContractRegistrationVersion; + +// There were no fees for these things before Protocol version 9 (version 2.0) +pub const FEE_DATA_CONTRACT_REGISTRATION_VERSION1: FeeDataContractRegistrationVersion = + FeeDataContractRegistrationVersion { + base_contract_registration_fee: 0, + document_type_registration_fee: 0, + document_type_base_non_unique_index_registration_fee: 0, + document_type_base_unique_index_registration_fee: 0, + document_type_base_contested_index_registration_fee: 0, + token_registration_fee: 0, + token_uses_perpetual_distribution_fee: 0, + token_uses_pre_programmed_distribution_fee: 0, + search_keyword_fee: 0, + }; diff --git a/packages/rs-platform-version/src/version/fee/data_contract_registration/v2.rs b/packages/rs-platform-version/src/version/fee/data_contract_registration/v2.rs new file mode 100644 index 00000000000..e1bea5c57a1 --- /dev/null +++ b/packages/rs-platform-version/src/version/fee/data_contract_registration/v2.rs @@ -0,0 +1,15 @@ +use crate::version::fee::data_contract_registration::FeeDataContractRegistrationVersion; + +/// Introduced in protocol version 9 (version 2.0) +pub const FEE_DATA_CONTRACT_REGISTRATION_VERSION2: FeeDataContractRegistrationVersion = + FeeDataContractRegistrationVersion { + base_contract_registration_fee: 10_000_000_000, // 0.1 Dash + document_type_registration_fee: 2_000_000_000, // 0.02 Dash + document_type_base_non_unique_index_registration_fee: 1_000_000_000, // 0.01 Dash + document_type_base_unique_index_registration_fee: 1_000_000_000, // 0.01 Dash + document_type_base_contested_index_registration_fee: 100_000_000_000, // 1 Dash + token_registration_fee: 10_000_000_000, // 0.1 Dash + token_uses_perpetual_distribution_fee: 10_000_000_000, // 0.1 Dash + token_uses_pre_programmed_distribution_fee: 10_000_000_000, // 0.1 Dash + search_keyword_fee: 10_000_000_000, // 0.1 Dash + }; diff --git a/packages/rs-platform-version/src/version/fee/data_contract_validation/mod.rs b/packages/rs-platform-version/src/version/fee/data_contract_validation/mod.rs new file mode 100644 index 00000000000..28ad0e6fb6b --- /dev/null +++ b/packages/rs-platform-version/src/version/fee/data_contract_validation/mod.rs @@ -0,0 +1,14 @@ +use bincode::{Decode, Encode}; + +pub mod v1; + +#[derive(Clone, Debug, Default, Encode, Decode, PartialEq, Eq)] +pub struct FeeDataContractValidationVersion { + pub document_type_base_fee: u64, + pub document_type_schema_size_fee: u64, + pub document_type_per_property_fee: u64, + pub document_type_base_non_unique_index_fee: u64, + pub document_type_non_unique_index_per_property_fee: u64, + pub document_type_base_unique_index_fee: u64, + pub document_type_unique_index_per_property_fee: u64, +} diff --git a/packages/rs-platform-version/src/version/fee/data_contract/v1.rs b/packages/rs-platform-version/src/version/fee/data_contract_validation/v1.rs similarity index 77% rename from packages/rs-platform-version/src/version/fee/data_contract/v1.rs rename to packages/rs-platform-version/src/version/fee/data_contract_validation/v1.rs index 516da472cfd..2c151ab1b2e 100644 --- a/packages/rs-platform-version/src/version/fee/data_contract/v1.rs +++ b/packages/rs-platform-version/src/version/fee/data_contract_validation/v1.rs @@ -1,9 +1,9 @@ -use crate::version::fee::data_contract::FeeDataContractValidationVersion; +use crate::version::fee::data_contract_validation::FeeDataContractValidationVersion; pub const FEE_DATA_CONTRACT_VALIDATION_VERSION1: FeeDataContractValidationVersion = FeeDataContractValidationVersion { document_type_base_fee: 500, - document_type_size_fee: 10, + document_type_schema_size_fee: 10, document_type_per_property_fee: 40, document_type_base_non_unique_index_fee: 50, document_type_non_unique_index_per_property_fee: 30, diff --git a/packages/rs-platform-version/src/version/fee/mod.rs b/packages/rs-platform-version/src/version/fee/mod.rs index 735e1b51460..df0dc5a16d5 100644 --- a/packages/rs-platform-version/src/version/fee/mod.rs +++ b/packages/rs-platform-version/src/version/fee/mod.rs @@ -1,5 +1,7 @@ use crate::error::PlatformVersionError; -use crate::version::fee::data_contract::FeeDataContractValidationVersion; +use crate::version::fee::data_contract_registration::v1::FEE_DATA_CONTRACT_REGISTRATION_VERSION1; +use crate::version::fee::data_contract_registration::FeeDataContractRegistrationVersion; +use crate::version::fee::data_contract_validation::FeeDataContractValidationVersion; use crate::version::fee::hashing::FeeHashingVersion; use crate::version::fee::processing::{ FeeProcessingVersion, FeeProcessingVersionFieldsBeforeVersion1Point4, @@ -11,13 +13,15 @@ use crate::version::fee::v1::FEE_VERSION1; use crate::version::fee::vote_resolution_fund_fees::VoteResolutionFundFees; use bincode::{Decode, Encode}; -mod data_contract; +pub mod data_contract_registration; +mod data_contract_validation; mod hashing; mod processing; pub mod signature; pub mod state_transition_min_fees; pub mod storage; pub mod v1; +pub mod v2; pub mod vote_resolution_fund_fees; pub type FeeVersionNumber = u32; @@ -33,7 +37,8 @@ pub struct FeeVersion { pub signature: FeeSignatureVersion, pub hashing: FeeHashingVersion, pub processing: FeeProcessingVersion, - pub data_contract: FeeDataContractValidationVersion, + pub data_contract_validation: FeeDataContractValidationVersion, + pub data_contract_registration: FeeDataContractRegistrationVersion, pub state_transition_min_fees: StateTransitionMinFees, pub vote_resolution_fund_fees: VoteResolutionFundFees, } @@ -99,7 +104,8 @@ impl From for FeeVersion { signature: value.signature, hashing: value.hashing, processing: FeeProcessingVersion::from(value.processing), - data_contract: value.data_contract, + data_contract_validation: value.data_contract, + data_contract_registration: FEE_DATA_CONTRACT_REGISTRATION_VERSION1, state_transition_min_fees: value.state_transition_min_fees, vote_resolution_fund_fees: value.vote_resolution_fund_fees, } diff --git a/packages/rs-platform-version/src/version/fee/v1.rs b/packages/rs-platform-version/src/version/fee/v1.rs index fe43f0464c4..c77c9ec98b2 100644 --- a/packages/rs-platform-version/src/version/fee/v1.rs +++ b/packages/rs-platform-version/src/version/fee/v1.rs @@ -1,4 +1,5 @@ -use crate::version::fee::data_contract::v1::FEE_DATA_CONTRACT_VALIDATION_VERSION1; +use crate::version::fee::data_contract_registration::v1::FEE_DATA_CONTRACT_REGISTRATION_VERSION1; +use crate::version::fee::data_contract_validation::v1::FEE_DATA_CONTRACT_VALIDATION_VERSION1; use crate::version::fee::hashing::v1::FEE_HASHING_VERSION1; use crate::version::fee::processing::v1::FEE_PROCESSING_VERSION1; use crate::version::fee::signature::v1::FEE_SIGNATURE_VERSION1; @@ -14,7 +15,8 @@ pub const FEE_VERSION1: FeeVersion = FeeVersion { signature: FEE_SIGNATURE_VERSION1, hashing: FEE_HASHING_VERSION1, processing: FEE_PROCESSING_VERSION1, - data_contract: FEE_DATA_CONTRACT_VALIDATION_VERSION1, + data_contract_validation: FEE_DATA_CONTRACT_VALIDATION_VERSION1, + data_contract_registration: FEE_DATA_CONTRACT_REGISTRATION_VERSION1, state_transition_min_fees: STATE_TRANSITION_MIN_FEES_VERSION1, vote_resolution_fund_fees: VOTE_RESOLUTION_FUND_FEES_VERSION1, }; diff --git a/packages/rs-platform-version/src/version/fee/v2.rs b/packages/rs-platform-version/src/version/fee/v2.rs new file mode 100644 index 00000000000..fe82ac5534f --- /dev/null +++ b/packages/rs-platform-version/src/version/fee/v2.rs @@ -0,0 +1,23 @@ +use crate::version::fee::data_contract_registration::v2::FEE_DATA_CONTRACT_REGISTRATION_VERSION2; +use crate::version::fee::data_contract_validation::v1::FEE_DATA_CONTRACT_VALIDATION_VERSION1; +use crate::version::fee::hashing::v1::FEE_HASHING_VERSION1; +use crate::version::fee::processing::v1::FEE_PROCESSING_VERSION1; +use crate::version::fee::signature::v1::FEE_SIGNATURE_VERSION1; +use crate::version::fee::state_transition_min_fees::v1::STATE_TRANSITION_MIN_FEES_VERSION1; +use crate::version::fee::storage::v1::FEE_STORAGE_VERSION1; +use crate::version::fee::vote_resolution_fund_fees::v1::VOTE_RESOLUTION_FUND_FEES_VERSION1; +use crate::version::fee::FeeVersion; + +/// Introduced in protocol version 9 (2.0) +pub const FEE_VERSION2: FeeVersion = FeeVersion { + fee_version_number: 1, + uses_version_fee_multiplier_permille: Some(1000), //No action + storage: FEE_STORAGE_VERSION1, + signature: FEE_SIGNATURE_VERSION1, + hashing: FEE_HASHING_VERSION1, + processing: FEE_PROCESSING_VERSION1, + data_contract_validation: FEE_DATA_CONTRACT_VALIDATION_VERSION1, + data_contract_registration: FEE_DATA_CONTRACT_REGISTRATION_VERSION2, // changed to v2 + state_transition_min_fees: STATE_TRANSITION_MIN_FEES_VERSION1, + vote_resolution_fund_fees: VOTE_RESOLUTION_FUND_FEES_VERSION1, +}; diff --git a/packages/rs-platform-version/src/version/v9.rs b/packages/rs-platform-version/src/version/v9.rs index dbc3264fe55..95b7a01029f 100644 --- a/packages/rs-platform-version/src/version/v9.rs +++ b/packages/rs-platform-version/src/version/v9.rs @@ -21,7 +21,7 @@ use crate::version::drive_abci_versions::drive_abci_validation_versions::v6::DRI use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; use crate::version::drive_abci_versions::DriveAbciVersion; use crate::version::drive_versions::v4::DRIVE_VERSION_V4; -use crate::version::fee::v1::FEE_VERSION1; +use crate::version::fee::v2::FEE_VERSION2; use crate::version::protocol_version::PlatformVersion; use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; @@ -58,7 +58,7 @@ pub const PLATFORM_V9: PlatformVersion = PlatformVersion { factory_versions: DPP_FACTORY_VERSIONS_V1, }, system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, - fee_version: FEE_VERSION1, + fee_version: FEE_VERSION2, //changed to have data contract pay registration fees system_limits: SYSTEM_LIMITS_V1, consensus: ConsensusVersions { tenderdash_consensus_version: 1, From a861ed290bdc7814a34e9bc3b67a14f2509be21b Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 01:07:27 +0700 Subject: [PATCH 02/10] clippy fixes --- .../state_transition_processing/execute_event/v0/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs index 90bab997f7e..61c4342481a 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs @@ -25,6 +25,7 @@ impl Platform where C: CoreRPCLike, { + #[allow(clippy::too_many_arguments)] fn paid_function( &self, mut fee_validation_result: ConsensusValidationResult, @@ -118,7 +119,7 @@ where pub(super) fn execute_event_v0( &self, event: ExecutionEvent, - mut consensus_errors: Vec, + consensus_errors: Vec, block_info: &BlockInfo, transaction: &Transaction, platform_version: &PlatformVersion, From 4484bb7e0dc282b7643d2b8cd2610cf28e824d34 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 02:10:15 +0700 Subject: [PATCH 03/10] fixed js test --- .../test/functional/platform/Identity.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/platform-test-suite/test/functional/platform/Identity.spec.js b/packages/platform-test-suite/test/functional/platform/Identity.spec.js index 8f5e8994c40..ae7971b8d33 100644 --- a/packages/platform-test-suite/test/functional/platform/Identity.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Identity.spec.js @@ -341,7 +341,7 @@ describe('Platform', () => { }); it('should fail to create more documents if there are no more credits', async () => { - const lowBalanceIdentity = await client.platform.identities.register(200000); + const lowBalanceIdentity = await client.platform.identities.register(23200000); // Additional wait time to mitigate testnet latency await waitForSTPropagated(); From 42083cf642700498bab1436a342162db9fa87976 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 02:18:25 +0700 Subject: [PATCH 04/10] fixed js --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 14b7d2a2968..6e5b826a89d 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,8 @@ "path-to-regexp": "^1.9.0", "cookie": "^0.7.0", "cross-spawn": "^7.0.5", - "nanoid": "^3.3.8" + "nanoid": "^3.3.8", + "base-x": "^3.0.11" }, "dependencies": { "node-gyp": "^10.0.1" From c5bb4884f746da4b5cf94dd894adaa9e6f288c90 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 02:27:55 +0700 Subject: [PATCH 05/10] fixed js --- .pnp.cjs | 10 +++++----- ...se-x-npm-3.0.11-3798da0834-c2e3c443fd.zip} | Bin 5149 -> 5215 bytes .yarn/cache/fsevents-patch-19706e7e35-10.zip | Bin 0 -> 23750 bytes yarn.lock | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) rename .yarn/cache/{base-x-npm-3.0.9-7b2588e106-957101d6fd.zip => base-x-npm-3.0.11-3798da0834-c2e3c443fd.zip} (50%) create mode 100644 .yarn/cache/fsevents-patch-19706e7e35-10.zip diff --git a/.pnp.cjs b/.pnp.cjs index a7758f32aff..13460650039 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -4474,7 +4474,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/@types-bs58-npm-4.0.1-179273a650-5063fed6bb.zip/node_modules/@types/bs58/",\ "packageDependencies": [\ ["@types/bs58", "npm:4.0.1"],\ - ["base-x", "npm:3.0.9"]\ + ["base-x", "npm:3.0.11"]\ ],\ "linkType": "HARD"\ }]\ @@ -6517,10 +6517,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["base-x", [\ - ["npm:3.0.9", {\ - "packageLocation": "./.yarn/cache/base-x-npm-3.0.9-7b2588e106-957101d6fd.zip/node_modules/base-x/",\ + ["npm:3.0.11", {\ + "packageLocation": "./.yarn/cache/base-x-npm-3.0.11-3798da0834-c2e3c443fd.zip/node_modules/base-x/",\ "packageDependencies": [\ - ["base-x", "npm:3.0.9"],\ + ["base-x", "npm:3.0.11"],\ ["safe-buffer", "npm:5.2.1"]\ ],\ "linkType": "HARD"\ @@ -6877,7 +6877,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/bs58-npm-4.0.1-8d2a7822b1-b3c5365bb9.zip/node_modules/bs58/",\ "packageDependencies": [\ ["bs58", "npm:4.0.1"],\ - ["base-x", "npm:3.0.9"]\ + ["base-x", "npm:3.0.11"]\ ],\ "linkType": "HARD"\ }]\ diff --git a/.yarn/cache/base-x-npm-3.0.9-7b2588e106-957101d6fd.zip b/.yarn/cache/base-x-npm-3.0.11-3798da0834-c2e3c443fd.zip similarity index 50% rename from .yarn/cache/base-x-npm-3.0.9-7b2588e106-957101d6fd.zip rename to .yarn/cache/base-x-npm-3.0.11-3798da0834-c2e3c443fd.zip index 79bdd2c70524002e41956f1380456d7b3f331e7f..a47894a0b101fa04b1b1154461e218b9749bc6e9 100644 GIT binary patch delta 2120 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

wQ>~-wnH!j;BGg*bRj{z2^V}f8on9* zxrM)>NEyEkFRuQejQ5$Ir-hgq$_e&=PBTD90H~ud=*Ra!3X(U9ymE+q6Vf7VEYZS1 zfc_n1BSX{HC`2oJe?Ufvq?D8^s~8{u_6_V;;HA=8nKLmBltriD;sf6k=~Rl_2H>Gt z;F*teWxx2GN5wu`RxGF9KX+Xfpt-(vT{A#Y^a)2YUCR=p$feQ;OLX}cuiyoLdQ@F% zC|G8k?Vd@&RN83JK9i)IArBu6Rbw_o>slLPGmS&gak50F5`t6`Ggcrv+&HUD!Xx*OXb4`1DEl z!2yn*cXEX}yDt-n__EUFcR^TpzSG-fRpC z6J3*lHMVs**yslw+s5TeW~C}f{-iLwHj>c-GIOITXMxN$y{xU3r`QWD)3K#*C2M4H zY6!nJd`_X$!6)NzIJdKZY5$(BucPxG%=Yg|@4Ds&#XgmEMcC%O8a)qv)j26uB(nUY zr@isgC;nS+^fsK4ci=nBO*BTP?t@Ng&pShBSoh9oKl&->bO-L+S>4++w&&3v^qSKF z@%b;VM@{&o?R{6RE-gy#XU#7O+|R#jk53+ZdAIOmTKnf5l2ny{;gQO9n+!@8T8#sE zW0cj--D085wa0BVxMR^)H%#?yd6yM@vVqw;%%Hu3IZZu0ZMKI$X|{)<*&hDTY|ZU$ z*VG&v@^I5`eIWE(b7OkKZZ~rNC%4@$^T(_fS%nUJ^kauTT6b7milZ$Sd$h)Zu{iC)#r@9zQr3vJf_`mkei87!bOOY@?WT(ijX{RLMaKTOTjZZe$+t6~I6zeAcHiV{c9 zVOcWvHvY=}-7{k$r&nuFVcbUy>ch^hnA8PJ*|HK+lMxdilbwG6P)h>@6aWGM2mnB? z)(DbAeIerk00314001D9@e&u4z6K6|O^?$s5WV+TjC$AuB5~W@B3Ld+tdKZx=(~qCLRPZ^rM?4KwBHqZq9t+)CGcK%yh1nW{KE0KGQtLbkskrW zRqYua-{# zXRIaH`Kqkdz^3Z8BKc@pKEBGgvAL&7*PH&|1sGZD(MAu?Nvo$CrA-#Tef>V^bMHE3 zV(5WO!X7>=Z^NxA+fa|$Y^|w(Upg8%rQL-fBPsAwKF%yR>cq-YqI7f8pjMWgGUH2I zkr3~PewGRTSEpqpu5C^)E1O#7sTWbr*%}HBB?|{78)}1PCE+7j$EDy#Kv6WbKAxZ| zsA(co>H&UmXc{s%X!XZIkYaPdKs#P zq6_}}e$1!-xJHO%_9iZ4oru8m18NMLkTqd8nNMj|Oh)s8zdwW@y5GHK@wDHC-0kX+ zPa8YkmB(_wMx$Dq{`B3C%Kj7#$?i=6Ul6v#kgz3JO=qw~ToO z007$$li(6W8#o6096D403ZMW00000000000HlFRlRpzp0&579Kob^|-v|nm nt`jN(Kns&V6Bd*36Egz25R*U?7LzRz4wFd~5C*{!00000|Fh=L diff --git a/.yarn/cache/fsevents-patch-19706e7e35-10.zip b/.yarn/cache/fsevents-patch-19706e7e35-10.zip new file mode 100644 index 0000000000000000000000000000000000000000..aff1ab12ce57f312cc3bc58c78597020f7980e62 GIT binary patch literal 23750 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 literal 0 HcmV?d00001 diff --git a/yarn.lock b/yarn.lock index c69a41f3f37..6f87bd9552a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4730,12 +4730,12 @@ __metadata: languageName: node linkType: hard -"base-x@npm:^3.0.2, base-x@npm:^3.0.6": - version: 3.0.9 - resolution: "base-x@npm:3.0.9" +"base-x@npm:^3.0.11": + version: 3.0.11 + resolution: "base-x@npm:3.0.11" dependencies: safe-buffer: "npm:^5.0.1" - checksum: 957101d6fd09e1903e846fd8f69fd7e5e3e50254383e61ab667c725866bec54e5ece5ba49ce385128ae48f9ec93a26567d1d5ebb91f4d56ef4a9cc0d5a5481e8 + checksum: c2e3c443fd07cb9b9d3e179a9e9c581daa31881005841fe8d6a834e534505890fedf03465ccf14512da60e3f7be00fe66167806b159ba076d2c03952ae7460c4 languageName: node linkType: hard From b69944d17eda1df5cf16fc35ec72238a60c96796 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 02:57:58 +0700 Subject: [PATCH 06/10] increase funding in js --- .../test/functional/platform/DataContract.spec.js | 4 ++-- .../test/functional/platform/Identity.spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js index 28fe50b14ec..3eaea3a1ce7 100644 --- a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js +++ b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js @@ -25,11 +25,11 @@ describe('Platform', () => { let identity; before(async () => { - client = await createClientWithFundedWallet(35000000); + client = await createClientWithFundedWallet(3500000000); // 35 Dash // Looks like updating the contact and keeping history requires about // 7 million credits in fees. Investigate this further. - identity = await client.platform.identities.register(30000000); + identity = await client.platform.identities.register(3000000000); // 30 Dash const nextNonce = await client.platform .nonceManager.bumpIdentityNonce(identity.getId()); dataContractFixture = await getDataContractFixture(nextNonce); diff --git a/packages/platform-test-suite/test/functional/platform/Identity.spec.js b/packages/platform-test-suite/test/functional/platform/Identity.spec.js index ae7971b8d33..fa155aaf3b0 100644 --- a/packages/platform-test-suite/test/functional/platform/Identity.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Identity.spec.js @@ -38,7 +38,7 @@ describe('Platform', () => { let walletAccount; before(async () => { - client = await createClientWithFundedWallet(20000000); + client = await createClientWithFundedWallet(2000000000); // 20 Dash walletAccount = await client.getWalletAccount(); }); From ad6c71af273874cd16ed53a002e21ce5c77c7b11 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 03:36:11 +0700 Subject: [PATCH 07/10] fix --- .../test/functional/platform/DataContract.spec.js | 4 ++-- .../test/functional/platform/Document.spec.js | 4 ++-- .../test/functional/platform/Identity.spec.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js index 3eaea3a1ce7..348740129b2 100644 --- a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js +++ b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js @@ -25,11 +25,11 @@ describe('Platform', () => { let identity; before(async () => { - client = await createClientWithFundedWallet(3500000000); // 35 Dash + client = await createClientWithFundedWallet(350000000); // 3.5 Dash // Looks like updating the contact and keeping history requires about // 7 million credits in fees. Investigate this further. - identity = await client.platform.identities.register(3000000000); // 30 Dash + identity = await client.platform.identities.register(300000000); // 3 Dash const nextNonce = await client.platform .nonceManager.bumpIdentityNonce(identity.getId()); dataContractFixture = await getDataContractFixture(nextNonce); diff --git a/packages/platform-test-suite/test/functional/platform/Document.spec.js b/packages/platform-test-suite/test/functional/platform/Document.spec.js index 85f9abf963a..f30c7b4feb4 100644 --- a/packages/platform-test-suite/test/functional/platform/Document.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Document.spec.js @@ -38,9 +38,9 @@ describe('Platform', () => { let document; before(async () => { - client = await createClientWithFundedWallet(1010000); + client = await createClientWithFundedWallet(101000000); // 1 Dash - identity = await client.platform.identities.register(1000000); + identity = await client.platform.identities.register(100000000); // Additional wait time to mitigate testnet latency await waitForSTPropagated(); diff --git a/packages/platform-test-suite/test/functional/platform/Identity.spec.js b/packages/platform-test-suite/test/functional/platform/Identity.spec.js index fa155aaf3b0..1ec0ff5b38e 100644 --- a/packages/platform-test-suite/test/functional/platform/Identity.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Identity.spec.js @@ -38,7 +38,7 @@ describe('Platform', () => { let walletAccount; before(async () => { - client = await createClientWithFundedWallet(2000000000); // 20 Dash + client = await createClientWithFundedWallet(150000000); // 1.5 Dash walletAccount = await client.getWalletAccount(); }); From 3c0aa421469758c7fe5c45925279fa97c96c90bf Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 04:15:07 +0700 Subject: [PATCH 08/10] fix --- packages/platform-test-suite/test/e2e/contacts.spec.js | 2 +- .../test/functional/platform/Identity.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/platform-test-suite/test/e2e/contacts.spec.js b/packages/platform-test-suite/test/e2e/contacts.spec.js index fe8eaf2fced..fe3dd51ebd7 100644 --- a/packages/platform-test-suite/test/e2e/contacts.spec.js +++ b/packages/platform-test-suite/test/e2e/contacts.spec.js @@ -104,7 +104,7 @@ describe('e2e', () => { describe('Bob', () => { it('should create user wallet and identity', async () => { // Create Bob wallet - bobClient = await createClientWithFundedWallet(500000); + bobClient = await createClientWithFundedWallet(100000000); // 1 Dash bobIdentity = await bobClient.platform.identities.register(400000); diff --git a/packages/platform-test-suite/test/functional/platform/Identity.spec.js b/packages/platform-test-suite/test/functional/platform/Identity.spec.js index 1ec0ff5b38e..790f6cbc59a 100644 --- a/packages/platform-test-suite/test/functional/platform/Identity.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Identity.spec.js @@ -341,7 +341,7 @@ describe('Platform', () => { }); it('should fail to create more documents if there are no more credits', async () => { - const lowBalanceIdentity = await client.platform.identities.register(23200000); + const lowBalanceIdentity = await client.platform.identities.register(200000); // Additional wait time to mitigate testnet latency await waitForSTPropagated(); From 868fa9c7de0b797dd0a1bb0f613ddd32db941d49 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 04:48:21 +0700 Subject: [PATCH 09/10] another fix --- packages/platform-test-suite/test/e2e/contacts.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/platform-test-suite/test/e2e/contacts.spec.js b/packages/platform-test-suite/test/e2e/contacts.spec.js index fe3dd51ebd7..fceb6027730 100644 --- a/packages/platform-test-suite/test/e2e/contacts.spec.js +++ b/packages/platform-test-suite/test/e2e/contacts.spec.js @@ -104,9 +104,9 @@ describe('e2e', () => { describe('Bob', () => { it('should create user wallet and identity', async () => { // Create Bob wallet - bobClient = await createClientWithFundedWallet(100000000); // 1 Dash + bobClient = await createClientWithFundedWallet(150000000); // 1.5 Dash - bobIdentity = await bobClient.platform.identities.register(400000); + bobIdentity = await bobClient.platform.identities.register(140000000); // 1.4 Dash // Additional wait time to mitigate testnet latency await waitForSTPropagated(); From 560904562fd5da1475b63b6d298c034cb5f7d4b2 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 3 May 2025 05:21:32 +0700 Subject: [PATCH 10/10] last fix --- .../test/functional/platform/Identity.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/platform-test-suite/test/functional/platform/Identity.spec.js b/packages/platform-test-suite/test/functional/platform/Identity.spec.js index 790f6cbc59a..8238ff38a37 100644 --- a/packages/platform-test-suite/test/functional/platform/Identity.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Identity.spec.js @@ -50,7 +50,7 @@ describe('Platform', () => { }); it('should create an identity', async () => { - identity = await client.platform.identities.register(400000); + identity = await client.platform.identities.register(140000000); // 1.4 Dash expect(identity).to.exist(); });