diff --git a/packages/rs-dpp/src/data_contract/config/fields.rs b/packages/rs-dpp/src/data_contract/config/fields.rs index 200c0402e0..f322d467a1 100644 --- a/packages/rs-dpp/src/data_contract/config/fields.rs +++ b/packages/rs-dpp/src/data_contract/config/fields.rs @@ -4,6 +4,7 @@ pub const DEFAULT_CONTRACT_MUTABILITY: bool = true; pub const DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY: bool = false; pub const DEFAULT_CONTRACT_DOCUMENT_MUTABILITY: bool = true; pub const DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED: bool = true; +pub const DEFAULT_GRANULAR_NUMERIC_TYPES: bool = true; pub mod property { pub const CAN_BE_DELETED: &str = "canBeDeleted"; @@ -17,4 +18,5 @@ pub mod property { "requiresIdentityEncryptionBoundedKey"; pub const REQUIRES_IDENTITY_DECRYPTION_BOUNDED_KEY: &str = "requiresIdentityDecryptionBoundedKey"; + pub const GRANULAR_NUMERIC_TYPES: &str = "granular_numeric_types"; } diff --git a/packages/rs-dpp/src/data_contract/config/mod.rs b/packages/rs-dpp/src/data_contract/config/mod.rs index 2f2a2c825a..9c30b8d21e 100644 --- a/packages/rs-dpp/src/data_contract/config/mod.rs +++ b/packages/rs-dpp/src/data_contract/config/mod.rs @@ -1,7 +1,11 @@ mod fields; mod methods; pub mod v0; +pub mod v1; +use crate::data_contract::config::v1::{ + DataContractConfigGettersV1, DataContractConfigSettersV1, DataContractConfigV1, +}; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; use crate::version::PlatformVersion; use crate::ProtocolError; @@ -18,6 +22,8 @@ use v0::{DataContractConfigGettersV0, DataContractConfigSettersV0, DataContractC pub enum DataContractConfig { #[serde(rename = "0")] V0(DataContractConfigV0), + #[serde(rename = "1")] + V1(DataContractConfigV1), } impl DataContractConfig { @@ -26,9 +32,10 @@ impl DataContractConfig { ) -> Result { match platform_version.dpp.contract_versions.config { 0 => Ok(DataContractConfigV0::default().into()), + 1 => Ok(DataContractConfigV1::default().into()), version => Err(ProtocolError::UnknownVersionMismatch { method: "DataContractConfig::default_for_version".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, }), } @@ -43,14 +50,19 @@ impl DataContractConfig { let config: DataContractConfigV0 = platform_value::from_value(value)?; Ok(config.into()) } + 1 => { + let config: DataContractConfigV1 = platform_value::from_value(value)?; + Ok(config.into()) + } version => Err(ProtocolError::UnknownVersionMismatch { method: "DataContractConfig::from_value".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, }), } } + // TODO: Remove, it's not using /// Retrieve contract configuration properties. /// /// This method takes a BTreeMap representing a contract and retrieves @@ -77,9 +89,12 @@ impl DataContractConfig { 0 => Ok( DataContractConfigV0::get_contract_configuration_properties_v0(contract)?.into(), ), + 1 => Ok( + DataContractConfigV1::get_contract_configuration_properties_v1(contract)?.into(), + ), version => Err(ProtocolError::UnknownVersionMismatch { method: "DataContractConfig::get_contract_configuration_properties".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, }), } @@ -90,36 +105,42 @@ impl DataContractConfigGettersV0 for DataContractConfig { fn can_be_deleted(&self) -> bool { match self { DataContractConfig::V0(v0) => v0.can_be_deleted, + DataContractConfig::V1(v1) => v1.can_be_deleted, } } fn readonly(&self) -> bool { match self { DataContractConfig::V0(v0) => v0.readonly, + DataContractConfig::V1(v1) => v1.readonly, } } fn keeps_history(&self) -> bool { match self { DataContractConfig::V0(v0) => v0.keeps_history, + DataContractConfig::V1(v1) => v1.keeps_history, } } fn documents_keep_history_contract_default(&self) -> bool { match self { DataContractConfig::V0(v0) => v0.documents_keep_history_contract_default, + DataContractConfig::V1(v1) => v1.documents_keep_history_contract_default, } } fn documents_mutable_contract_default(&self) -> bool { match self { DataContractConfig::V0(v0) => v0.documents_mutable_contract_default, + DataContractConfig::V1(v1) => v1.documents_mutable_contract_default, } } fn documents_can_be_deleted_contract_default(&self) -> bool { match self { DataContractConfig::V0(v0) => v0.documents_can_be_deleted_contract_default, + DataContractConfig::V1(v1) => v1.documents_can_be_deleted_contract_default, } } @@ -127,6 +148,7 @@ impl DataContractConfigGettersV0 for DataContractConfig { fn requires_identity_encryption_bounded_key(&self) -> Option { match self { DataContractConfig::V0(v0) => v0.requires_identity_encryption_bounded_key, + DataContractConfig::V1(v1) => v1.requires_identity_encryption_bounded_key, } } @@ -134,6 +156,7 @@ impl DataContractConfigGettersV0 for DataContractConfig { fn requires_identity_decryption_bounded_key(&self) -> Option { match self { DataContractConfig::V0(v0) => v0.requires_identity_decryption_bounded_key, + DataContractConfig::V1(v1) => v1.requires_identity_decryption_bounded_key, } } } @@ -142,36 +165,42 @@ impl DataContractConfigSettersV0 for DataContractConfig { fn set_can_be_deleted(&mut self, value: bool) { match self { DataContractConfig::V0(v0) => v0.can_be_deleted = value, + DataContractConfig::V1(v1) => v1.can_be_deleted = value, } } fn set_readonly(&mut self, value: bool) { match self { DataContractConfig::V0(v0) => v0.readonly = value, + DataContractConfig::V1(v1) => v1.readonly = value, } } fn set_keeps_history(&mut self, value: bool) { match self { DataContractConfig::V0(v0) => v0.keeps_history = value, + DataContractConfig::V1(v1) => v1.keeps_history = value, } } fn set_documents_keep_history_contract_default(&mut self, value: bool) { match self { DataContractConfig::V0(v0) => v0.documents_keep_history_contract_default = value, + DataContractConfig::V1(v1) => v1.documents_keep_history_contract_default = value, } } fn set_documents_can_be_deleted_contract_default(&mut self, value: bool) { match self { DataContractConfig::V0(v0) => v0.documents_can_be_deleted_contract_default = value, + DataContractConfig::V1(v1) => v1.documents_can_be_deleted_contract_default = value, } } fn set_documents_mutable_contract_default(&mut self, value: bool) { match self { DataContractConfig::V0(v0) => v0.documents_mutable_contract_default = value, + DataContractConfig::V1(v1) => v1.documents_mutable_contract_default = value, } } @@ -181,6 +210,7 @@ impl DataContractConfigSettersV0 for DataContractConfig { ) { match self { DataContractConfig::V0(v0) => v0.requires_identity_encryption_bounded_key = value, + DataContractConfig::V1(v1) => v1.requires_identity_encryption_bounded_key = value, } } @@ -190,6 +220,25 @@ impl DataContractConfigSettersV0 for DataContractConfig { ) { match self { DataContractConfig::V0(v0) => v0.requires_identity_decryption_bounded_key = value, + DataContractConfig::V1(v1) => v1.requires_identity_decryption_bounded_key = value, + } + } +} + +impl DataContractConfigGettersV1 for DataContractConfig { + fn granular_integer_types(&self) -> bool { + match self { + DataContractConfig::V0(_) => false, + DataContractConfig::V1(v1) => v1.granular_integer_types, + } + } +} + +impl DataContractConfigSettersV1 for DataContractConfig { + fn set_granular_integer_types_enabled(&mut self, enable: bool) { + match self { + DataContractConfig::V0(_) => {} + DataContractConfig::V1(v1) => v1.granular_integer_types = enable, } } } diff --git a/packages/rs-dpp/src/data_contract/config/v1/mod.rs b/packages/rs-dpp/src/data_contract/config/v1/mod.rs new file mode 100644 index 0000000000..209bb07ac9 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/config/v1/mod.rs @@ -0,0 +1,157 @@ +use crate::data_contract::config; +use crate::data_contract::config::v0::{DataContractConfigGettersV0, DataContractConfigSettersV0}; +use crate::data_contract::config::{ + DataContractConfig, DEFAULT_CONTRACT_CAN_BE_DELETED, DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED, + DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY, DEFAULT_CONTRACT_DOCUMENT_MUTABILITY, + DEFAULT_CONTRACT_KEEPS_HISTORY, DEFAULT_CONTRACT_MUTABILITY, DEFAULT_GRANULAR_NUMERIC_TYPES, +}; +use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; +use crate::ProtocolError; +use bincode::{Decode, Encode}; +use platform_value::btreemap_extensions::BTreeValueMapHelper; +use platform_value::Value; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "camelCase", default)] +pub struct DataContractConfigV1 { + /// Can the contract ever be deleted. If the contract is deleted, so should be all + /// documents associated with it. TODO: There should also be a way to "stop" the contract - + /// contract and documents are kept in the system, but no new documents can be added to it + pub can_be_deleted: bool, + /// Is the contract mutable. Means that the document definitions can be changed or new + /// document definitions can be added to the contract + pub readonly: bool, + /// Does the contract keep history when the contract itself changes + pub keeps_history: bool, + /// Do documents in the contract keep history. This is a default for all documents in + /// the contract, but can be overridden by the document itself + pub documents_keep_history_contract_default: bool, + /// Are documents in the contract mutable? This specifies whether the documents can be + /// changed. This is a default for all document types in the contract, but can be + /// overridden by the document type config. + pub documents_mutable_contract_default: bool, + /// Can documents in the contract be deleted? This specifies whether the documents can be + /// deleted. This is a default for all document types in the contract, but can be + /// overridden by the document types itself. + pub documents_can_be_deleted_contract_default: bool, + /// Encryption key storage requirements + pub requires_identity_encryption_bounded_key: Option, + /// Decryption key storage requirements + pub requires_identity_decryption_bounded_key: Option, + /// Use granular integer Rust types for `integer` property type + pub granular_integer_types: bool, +} + +/// Trait representing getters for `DataContractConfigV1` +pub trait DataContractConfigGettersV1: DataContractConfigGettersV0 { + /// Use granular integer Rust types for `integer` property type + fn granular_integer_types(&self) -> bool; +} + +/// Trait representing setters for `DataContractConfigV1` +pub trait DataContractConfigSettersV1: DataContractConfigSettersV0 { + /// Enable/disable granular integer Rust types for `integer` property type + fn set_granular_integer_types_enabled(&mut self, enable: bool); +} + +impl Default for DataContractConfigV1 { + fn default() -> Self { + DataContractConfigV1 { + can_be_deleted: DEFAULT_CONTRACT_CAN_BE_DELETED, + readonly: !DEFAULT_CONTRACT_MUTABILITY, + keeps_history: DEFAULT_CONTRACT_KEEPS_HISTORY, + documents_keep_history_contract_default: DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY, + documents_mutable_contract_default: DEFAULT_CONTRACT_DOCUMENT_MUTABILITY, + documents_can_be_deleted_contract_default: DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED, + requires_identity_encryption_bounded_key: None, + requires_identity_decryption_bounded_key: None, + granular_integer_types: true, + } + } +} + +impl DataContractConfigV1 { + pub fn from_value(value: Value) -> Result { + platform_value::from_value(value).map_err(ProtocolError::ValueError) + } + + pub fn default_with_version() -> DataContractConfig { + Self::default().into() + } +} + +impl DataContractConfigV1 { + /// Retrieve contract configuration properties. + /// + /// This method takes a BTreeMap representing a contract and retrieves + /// the configuration properties based on the values found in the map. + /// + /// The process of retrieving contract configuration properties is versioned, + /// and the version is determined by the platform version parameter. + /// If the version is not supported, an error is returned. + /// + /// # Parameters + /// + /// * `contract`: BTreeMap representing the contract. + /// * `platform_version`: The platform version being used. + /// + /// # Returns + /// + /// * `Result`: On success, a ContractConfig. + /// On failure, a ProtocolError. + #[inline(always)] + pub(super) fn get_contract_configuration_properties_v1( + contract: &BTreeMap, + ) -> Result { + let keeps_history = contract + .get_optional_bool(config::property::KEEPS_HISTORY)? + .unwrap_or(DEFAULT_CONTRACT_KEEPS_HISTORY); + let can_be_deleted = contract + .get_optional_bool(config::property::CAN_BE_DELETED)? + .unwrap_or(DEFAULT_CONTRACT_CAN_BE_DELETED); + + let readonly = contract + .get_optional_bool(config::property::READONLY)? + .unwrap_or(!DEFAULT_CONTRACT_MUTABILITY); + + let documents_keep_history_contract_default = contract + .get_optional_bool(config::property::DOCUMENTS_KEEP_HISTORY_CONTRACT_DEFAULT)? + .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY); + + let documents_mutable_contract_default = contract + .get_optional_bool(config::property::DOCUMENTS_MUTABLE_CONTRACT_DEFAULT)? + .unwrap_or(DEFAULT_CONTRACT_DOCUMENT_MUTABILITY); + + let documents_can_be_deleted_contract_default = contract + .get_optional_bool(config::property::DOCUMENTS_CAN_BE_DELETED_CONTRACT_DEFAULT)? + .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED); + + let requires_identity_encryption_bounded_key = contract + .get_optional_integer::(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)? + .map(|int| int.try_into()) + .transpose()?; + + let requires_identity_decryption_bounded_key = contract + .get_optional_integer::(config::property::REQUIRES_IDENTITY_DECRYPTION_BOUNDED_KEY)? + .map(|int| int.try_into()) + .transpose()?; + + let granular_numeric_types = contract + .get_optional_bool(config::property::GRANULAR_NUMERIC_TYPES)? + .unwrap_or(DEFAULT_GRANULAR_NUMERIC_TYPES); + + Ok(DataContractConfigV1 { + can_be_deleted, + readonly, + keeps_history, + documents_keep_history_contract_default, + documents_mutable_contract_default, + documents_can_be_deleted_contract_default, + requires_identity_encryption_bounded_key, + requires_identity_decryption_bounded_key, + granular_integer_types: granular_numeric_types, + }) + } +} diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/mod.rs index cdd1666e02..6eda29a77a 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/mod.rs @@ -1,6 +1,7 @@ mod v0; mod v1; +use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::v0::DocumentTypeV0; use crate::data_contract::document_type::DocumentType; use crate::data_contract::DocumentName; @@ -38,9 +39,7 @@ impl DocumentType { data_contract_id: Identifier, document_schemas: BTreeMap, schema_defs: Option<&BTreeMap>, - documents_keep_history_contract_default: bool, - documents_mutable_contract_default: bool, - documents_can_be_deleted_contract_default: bool, + data_contact_config: &DataContractConfig, full_validation: bool, has_tokens: bool, validation_operations: &mut Vec, @@ -57,9 +56,7 @@ impl DocumentType { data_contract_id, document_schemas, schema_defs, - documents_keep_history_contract_default, - documents_mutable_contract_default, - documents_can_be_deleted_contract_default, + data_contact_config, full_validation, validation_operations, platform_version, @@ -69,9 +66,7 @@ impl DocumentType { data_contract_id, document_schemas, schema_defs, - documents_keep_history_contract_default, - documents_mutable_contract_default, - documents_can_be_deleted_contract_default, + data_contact_config, full_validation, has_tokens, validation_operations, diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v0/mod.rs index 69b497eeea..45817e8dad 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v0/mod.rs @@ -1,4 +1,5 @@ use crate::consensus::basic::data_contract::DocumentTypesAreMissingError; +use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::class_methods::consensus_or_protocol_data_contract_error; use crate::data_contract::document_type::v0::DocumentTypeV0; use crate::data_contract::document_type::DocumentType; @@ -14,9 +15,7 @@ impl DocumentTypeV0 { data_contract_id: Identifier, document_schemas: BTreeMap, schema_defs: Option<&BTreeMap>, - documents_keep_history_contract_default: bool, - documents_mutable_contract_default: bool, - documents_can_be_deleted_contract_default: bool, + data_contact_config: &DataContractConfig, full_validation: bool, validation_operations: &mut Vec, platform_version: &PlatformVersion, @@ -41,9 +40,7 @@ impl DocumentTypeV0 { &name, schema, schema_defs, - documents_keep_history_contract_default, - documents_mutable_contract_default, - documents_can_be_deleted_contract_default, + data_contact_config, full_validation, validation_operations, platform_version, @@ -80,13 +77,14 @@ mod tests { pub fn should_not_allow_creating_document_types_with_empty_schema() { let id = Identifier::random(); + let config = DataContractConfig::default_for_version(PlatformVersion::latest()) + .expect("should create a default config"); + let result = DocumentType::create_document_types_from_document_schemas( id, Default::default(), None, - false, - false, - false, + &config, false, false, &mut vec![], diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v1/mod.rs index 720dc9fe83..6b0a27eaa7 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/create_document_types_from_document_schemas/v1/mod.rs @@ -1,4 +1,5 @@ use crate::consensus::basic::data_contract::DocumentTypesAreMissingError; +use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::class_methods::consensus_or_protocol_data_contract_error; use crate::data_contract::document_type::v0::DocumentTypeV0; use crate::data_contract::document_type::DocumentType; @@ -14,9 +15,7 @@ impl DocumentTypeV0 { data_contract_id: Identifier, document_schemas: BTreeMap, schema_defs: Option<&BTreeMap>, - documents_keep_history_contract_default: bool, - documents_mutable_contract_default: bool, - documents_can_be_deleted_contract_default: bool, + data_contact_config: &DataContractConfig, full_validation: bool, has_tokens: bool, validation_operations: &mut Vec, @@ -42,9 +41,7 @@ impl DocumentTypeV0 { &name, schema, schema_defs, - documents_keep_history_contract_default, - documents_mutable_contract_default, - documents_can_be_deleted_contract_default, + data_contact_config, full_validation, validation_operations, platform_version, diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/mod.rs index d56fad8f84..fcc71ce022 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/mod.rs @@ -1,3 +1,4 @@ +use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::v0::DocumentTypeV0; use crate::data_contract::document_type::DocumentType; use crate::validation::operations::ProtocolValidationOperation; @@ -14,9 +15,7 @@ impl DocumentType { name: &str, schema: Value, schema_defs: Option<&BTreeMap>, - default_keeps_history: bool, - default_mutability: bool, - default_can_be_deleted: bool, + data_contact_config: &DataContractConfig, full_validation: bool, validation_operations: &mut Vec, platform_version: &PlatformVersion, @@ -33,9 +32,7 @@ impl DocumentType { name, schema, schema_defs, - default_keeps_history, - default_mutability, - default_can_be_deleted, + data_contact_config, full_validation, validation_operations, platform_version, @@ -43,7 +40,7 @@ impl DocumentType { .map(|document_type| document_type.into()), version => Err(ProtocolError::UnknownVersionMismatch { method: "try_from_schema".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, }), } diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs index 3394b0f6fc..7ea6e3942e 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs @@ -6,7 +6,6 @@ use crate::consensus::basic::data_contract::{ }; #[cfg(feature = "validation")] use crate::consensus::ConsensusError; -use crate::data_contract::document_type::array::ArrayItemType; use crate::data_contract::document_type::index::Index; use crate::data_contract::document_type::index_level::IndexLevel; use crate::data_contract::document_type::property::{DocumentProperty, DocumentPropertyType}; @@ -31,6 +30,9 @@ use crate::consensus::basic::data_contract::InvalidDocumentTypeNameError; use crate::consensus::basic::document::MissingPositionsInDocumentTypePropertiesError; #[cfg(feature = "validation")] use crate::consensus::basic::BasicError; +use crate::data_contract::config::v0::DataContractConfigGettersV0; +use crate::data_contract::config::v1::DataContractConfigGettersV1; +use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::class_methods::{ consensus_or_protocol_data_contract_error, consensus_or_protocol_value_error, }; @@ -38,9 +40,7 @@ use crate::data_contract::document_type::property_names::{ CAN_BE_DELETED, CREATION_RESTRICTION_MODE, DOCUMENTS_KEEP_HISTORY, DOCUMENTS_MUTABLE, TRADE_MODE, TRANSFERABLE, }; -use crate::data_contract::document_type::{ - property_names, ByteArrayPropertySizes, DocumentType, StringPropertySizes, -}; +use crate::data_contract::document_type::{property_names, DocumentType}; use crate::data_contract::errors::DataContractError; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; use crate::identity::SecurityLevel; @@ -81,9 +81,7 @@ impl DocumentTypeV0 { name: &str, schema: Value, schema_defs: Option<&BTreeMap>, - default_keeps_history: bool, - default_mutability: bool, - default_can_be_deleted: bool, + data_contact_config: &DataContractConfig, full_validation: bool, // we don't need to validate if loaded from state validation_operations: &mut Vec, platform_version: &PlatformVersion, @@ -168,19 +166,19 @@ impl DocumentTypeV0 { let documents_keep_history: bool = Value::inner_optional_bool_value(schema_map, DOCUMENTS_KEEP_HISTORY) .map_err(consensus_or_protocol_value_error)? - .unwrap_or(default_keeps_history); + .unwrap_or(data_contact_config.documents_keep_history_contract_default()); // Are documents of this type mutable? (Overrides contract value) let documents_mutable: bool = Value::inner_optional_bool_value(schema_map, DOCUMENTS_MUTABLE) .map_err(consensus_or_protocol_value_error)? - .unwrap_or(default_mutability); + .unwrap_or(data_contact_config.documents_mutable_contract_default()); // Can documents of this type be deleted? (Overrides contract value) let documents_can_be_deleted: bool = Value::inner_optional_bool_value(schema_map, CAN_BE_DELETED) .map_err(consensus_or_protocol_value_error)? - .unwrap_or(default_can_be_deleted); + .unwrap_or(data_contact_config.documents_can_be_deleted_contract_default()); // Are documents of this type transferable? let documents_transferable_u8: u8 = @@ -270,6 +268,7 @@ impl DocumentTypeV0 { property_key.clone(), property_value, &root_schema, + data_contact_config, ) .map_err(consensus_or_protocol_data_contract_error)?; @@ -280,6 +279,7 @@ impl DocumentTypeV0 { property_key, property_value, &root_schema, + data_contact_config, ) .map_err(consensus_or_protocol_data_contract_error)?; } @@ -592,6 +592,7 @@ fn insert_values( property_key: String, property_value: &Value, root_schema: &Value, + config: &DataContractConfig, ) -> Result<(), DataContractError> { let mut to_visit: Vec<(Option, String, &Value)> = vec![(prefix, property_key, property_value)]; @@ -610,58 +611,11 @@ fn insert_values( inner_properties = referenced_sub_schema.to_btree_ref_string_map()? } - let type_value = inner_properties.get_str(property_names::TYPE)?; - let is_required = known_required.contains(&prefixed_property_key); let is_transient = known_transient.contains(&prefixed_property_key); - let field_type: DocumentPropertyType; - - match type_value { - "array" => { - // Only handling bytearrays for v1 - // Return an error if it is not a byte array - field_type = match inner_properties.get_optional_bool(property_names::BYTE_ARRAY)? { - Some(inner_bool) => { - if inner_bool { - match inner_properties - .get_optional_str(property_names::CONTENT_MEDIA_TYPE)? - { - Some("application/x.dash.dpp.identifier") => { - DocumentPropertyType::Identifier - } - Some(_) | None => { - DocumentPropertyType::ByteArray(ByteArrayPropertySizes { - min_size: inner_properties - .get_optional_integer(property_names::MIN_ITEMS)?, - max_size: inner_properties - .get_optional_integer(property_names::MAX_ITEMS)?, - }) - } - } - } else { - return Err(DataContractError::InvalidContractStructure( - "byteArray should always be true if defined".to_string(), - )); - } - } - // TODO: Update when arrays are implemented - None => { - return Err(DataContractError::InvalidContractStructure( - "only byte arrays are supported now".to_string(), - )); - } - }; - document_properties.insert( - prefixed_property_key, - DocumentProperty { - property_type: field_type, - required: is_required, - transient: is_transient, - }, - ); - } - "object" => { + match DocumentPropertyType::try_from_value_map(&inner_properties, &config.into())? { + DocumentPropertyType::Object(_) => { if let Some(properties_as_value) = inner_properties.get(property_names::PROPERTIES) { let properties = @@ -686,37 +640,19 @@ fn insert_values( } } } - - "string" => { - field_type = DocumentPropertyType::String(StringPropertySizes { - min_length: inner_properties - .get_optional_integer(property_names::MIN_LENGTH)?, - max_length: inner_properties - .get_optional_integer(property_names::MAX_LENGTH)?, - }); - document_properties.insert( - prefixed_property_key, - DocumentProperty { - property_type: field_type, - required: is_required, - transient: is_transient, - }, - ); - } - - _ => { - field_type = DocumentPropertyType::try_from_name(type_value)?; + property_type => { + if !config.granular_integer_types() && property_type.is_integer() {} document_properties.insert( prefixed_property_key, DocumentProperty { - property_type: field_type, + property_type, required: is_required, transient: is_transient, }, ); } - } + }; } Ok(()) @@ -728,6 +664,7 @@ fn insert_values_nested( property_key: String, property_value: &Value, root_schema: &Value, + config: &DataContractConfig, ) -> Result<(), DataContractError> { let mut inner_properties = property_value.to_btree_ref_string_map()?; @@ -737,179 +674,87 @@ fn insert_values_nested( inner_properties = referenced_sub_schema.to_btree_ref_string_map()?; } - let type_value = inner_properties.get_str(property_names::TYPE)?; - let is_required = known_required.contains(&property_key); let is_transient = known_transient.contains(&property_key); - let field_type = match type_value { - "integer" => { - DocumentPropertyType::I64 - // todo: we might want to do the following in the future (must be versioned) - // let minimum = inner_properties.get_optional_integer::(property_names::MINIMUM)?; - // let maximum = inner_properties.get_optional_integer::(property_names::MAXIMUM)?; - // - // match (minimum, maximum) { - // (Some(min), Some(max)) => { - // if min >= 0 { - // if max <= u8::MAX as i64 { - // DocumentPropertyType::U8 - // } else if max <= u16::MAX as i64 { - // DocumentPropertyType::U16 - // } else if max <= u32::MAX as i64 { - // DocumentPropertyType::U32 - // } else { - // DocumentPropertyType::U64 - // } - // } else { - // if min >= i8::MIN as i64 && max <= i8::MAX as i64 { - // DocumentPropertyType::I8 - // } else if min >= i16::MIN as i64 && max <= i16::MAX as i64 { - // DocumentPropertyType::I16 - // } else if min >= i32::MIN as i64 && max <= i32::MAX as i64 { - // DocumentPropertyType::I32 - // } else { - // DocumentPropertyType::I64 - // } - // } - // } - // (Some(min), None) => { - // if min >= 0 { - // DocumentPropertyType::U64 - // } else { - // DocumentPropertyType::I64 - // } - // } - // (None, Some(max)) => { - // if max >= 0 { - // DocumentPropertyType::U64 - // } else { - // DocumentPropertyType::I64 - // } - // } - // (None, None) => DocumentPropertyType::I64, - // } - } - "number" => DocumentPropertyType::F64, - "string" => DocumentPropertyType::String(StringPropertySizes { - min_length: inner_properties.get_optional_integer(property_names::MIN_LENGTH)?, - max_length: inner_properties.get_optional_integer(property_names::MAX_LENGTH)?, - }), - "array" => { - // Only handling bytearrays for v1 - // Return an error if it is not a byte array - match inner_properties.get_optional_bool(property_names::BYTE_ARRAY)? { - Some(inner_bool) => { - if inner_bool { - match inner_properties - .get_optional_str(property_names::CONTENT_MEDIA_TYPE)? - { - Some("application/x.dash.dpp.identifier") => { - DocumentPropertyType::Identifier + let property_type = + match DocumentPropertyType::try_from_value_map(&inner_properties, &config.into())? { + DocumentPropertyType::Object(_) => { + let mut nested_properties = IndexMap::new(); + if let Some(properties_as_value) = inner_properties.get(property_names::PROPERTIES) + { + let properties = + properties_as_value + .as_map() + .ok_or(DataContractError::ValueWrongType( + "properties must be a map".to_string(), + ))?; + + let mut sorted_properties: Vec<_> = properties.iter().collect(); + + sorted_properties.sort_by(|(_, value_1), (_, value_2)| { + let pos_1: u64 = value_1 + .get_integer(property_names::POSITION) + .expect("expected a position"); + let pos_2: u64 = value_2 + .get_integer(property_names::POSITION) + .expect("expected a position"); + pos_1.cmp(&pos_2) + }); + + // Create a new set with the prefix removed from the keys + let stripped_required: BTreeSet = known_required + .iter() + .filter_map(|key| { + if key.starts_with(&property_key) && key.len() > property_key.len() { + Some(key[property_key.len() + 1..].to_string()) + } else { + None } - Some(_) | None => { - DocumentPropertyType::ByteArray(ByteArrayPropertySizes { - min_size: inner_properties - .get_optional_integer(property_names::MIN_ITEMS)?, - max_size: inner_properties - .get_optional_integer(property_names::MAX_ITEMS)?, - }) + }) + .collect(); + + let stripped_transient: BTreeSet = known_transient + .iter() + .filter_map(|key| { + if key.starts_with(&property_key) && key.len() > property_key.len() { + Some(key[property_key.len() + 1..].to_string()) + } else { + None } - } - } else { - return Err(DataContractError::InvalidContractStructure( - "byteArray should always be true if defined".to_string(), - )); + }) + .collect(); + + for (object_property_key, object_property_value) in properties.iter() { + let object_property_string = object_property_key + .as_text() + .ok_or(DataContractError::KeyWrongType( + "property key must be a string".to_string(), + ))? + .to_string(); + + insert_values_nested( + &mut nested_properties, + &stripped_required, + &stripped_transient, + object_property_string, + object_property_value, + root_schema, + config, + )?; } } - // TODO: Contract indices and new encoding format don't support arrays - // but we still can use them as document fields with current cbor encoding - // This is a temporary workaround to bring back v0.22 behavior and should be - // replaced with a proper array support in future versions - None => DocumentPropertyType::Array(ArrayItemType::Boolean), - } - } - "object" => { - let mut nested_properties = IndexMap::new(); - if let Some(properties_as_value) = inner_properties.get(property_names::PROPERTIES) { - let properties = - properties_as_value - .as_map() - .ok_or(DataContractError::ValueWrongType( - "properties must be a map".to_string(), - ))?; - - let mut sorted_properties: Vec<_> = properties.iter().collect(); - - sorted_properties.sort_by(|(_, value_1), (_, value_2)| { - let pos_1: u64 = value_1 - .get_integer(property_names::POSITION) - .expect("expected a position"); - let pos_2: u64 = value_2 - .get_integer(property_names::POSITION) - .expect("expected a position"); - pos_1.cmp(&pos_2) - }); - - // Create a new set with the prefix removed from the keys - let stripped_required: BTreeSet = known_required - .iter() - .filter_map(|key| { - if key.starts_with(&property_key) && key.len() > property_key.len() { - Some(key[property_key.len() + 1..].to_string()) - } else { - None - } - }) - .collect(); - let stripped_transient: BTreeSet = known_transient - .iter() - .filter_map(|key| { - if key.starts_with(&property_key) && key.len() > property_key.len() { - Some(key[property_key.len() + 1..].to_string()) - } else { - None - } - }) - .collect(); - - for (object_property_key, object_property_value) in properties.iter() { - let object_property_string = object_property_key - .as_text() - .ok_or(DataContractError::KeyWrongType( - "property key must be a string".to_string(), - ))? - .to_string(); - - insert_values_nested( - &mut nested_properties, - &stripped_required, - &stripped_transient, - object_property_string, - object_property_value, - root_schema, - )?; - } + DocumentPropertyType::Object(nested_properties) } - document_properties.insert( - property_key, - DocumentProperty { - property_type: DocumentPropertyType::Object(nested_properties), - required: is_required, - transient: is_transient, - }, - ); - return Ok(()); - } - _ => DocumentPropertyType::try_from_name(type_value)?, - }; + property_type => property_type, + }; document_properties.insert( property_key, DocumentProperty { - property_type: field_type, + property_type, required: is_required, transient: is_transient, }, @@ -942,14 +787,15 @@ mod tests { "additionalProperties": false }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let _result = DocumentTypeV0::try_from_schema_v0( Identifier::new([1; 32]), "valid_name-a-b-123", schema, None, - false, - false, - false, + &config, true, &mut vec![], platform_version, @@ -972,14 +818,15 @@ mod tests { "additionalProperties": false }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let result = DocumentTypeV0::try_from_schema_v0( Identifier::new([1; 32]), "", schema, None, - false, - false, - false, + &config, true, &mut vec![], platform_version, @@ -1013,14 +860,15 @@ mod tests { "additionalProperties": false }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let result = DocumentTypeV0::try_from_schema_v0( Identifier::new([1; 32]), &"a".repeat(65), schema, None, - false, - false, - false, + &config, true, &mut vec![], platform_version, @@ -1054,14 +902,15 @@ mod tests { "additionalProperties": false }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let result = DocumentTypeV0::try_from_schema_v0( Identifier::new([1; 32]), "invalid name", schema.clone(), None, - false, - false, - false, + &config, true, &mut vec![], platform_version, @@ -1079,14 +928,15 @@ mod tests { } ); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let result = DocumentTypeV0::try_from_schema_v0( Identifier::new([1; 32]), "invalid&name", schema, None, - false, - false, - false, + &config, true, &mut vec![], platform_version, diff --git a/packages/rs-dpp/src/data_contract/document_type/methods/validate_update/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/methods/validate_update/v0/mod.rs index fe3980e0aa..1d1613a244 100644 --- a/packages/rs-dpp/src/data_contract/document_type/methods/validate_update/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/methods/validate_update/v0/mod.rs @@ -247,6 +247,7 @@ mod tests { use crate::consensus::state::state_error::StateError; use crate::consensus::ConsensusError; + use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::DocumentType; use assert_matches::assert_matches; use platform_value::platform_value; @@ -273,14 +274,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -299,14 +301,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -343,14 +346,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -369,14 +373,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -413,14 +418,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -439,14 +445,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -483,14 +490,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -509,14 +517,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -553,14 +562,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -579,14 +589,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -623,14 +634,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -649,14 +661,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -693,14 +706,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -724,9 +738,7 @@ mod tests { document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -763,14 +775,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -794,9 +807,7 @@ mod tests { document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -833,14 +844,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -864,9 +876,7 @@ mod tests { document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -908,28 +918,30 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema.clone(), None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, ) .expect("failed to create old document type"); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let new_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -962,14 +974,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let old_document_type = DocumentType::try_from_schema( data_contract_id, document_type_name, schema.clone(), None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, @@ -993,9 +1006,7 @@ mod tests { document_type_name, schema, None, - false, - false, - false, + &config, false, &mut Vec::new(), platform_version, 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 23382dab53..fdded490e5 100644 --- a/packages/rs-dpp/src/data_contract/document_type/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/mod.rs @@ -54,6 +54,7 @@ mod property_names { pub const UPDATED_AT: &str = "$updatedAt"; pub const TRANSFERRED_AT: &str = "$transferredAt"; pub const MINIMUM: &str = "minimum"; + pub const ENUM: &str = "enum"; pub const MAXIMUM: &str = "maximum"; pub const MIN_ITEMS: &str = "minItems"; pub const MAX_ITEMS: &str = "maxItems"; diff --git a/packages/rs-dpp/src/data_contract/document_type/property/mod.rs b/packages/rs-dpp/src/data_contract/document_type/property/mod.rs index fd144701bc..31c9b0a4ca 100644 --- a/packages/rs-dpp/src/data_contract/document_type/property/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/property/mod.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use std::convert::TryInto; use std::io::{BufReader, Cursor, Read}; @@ -5,12 +6,17 @@ use std::io::{BufReader, Cursor, Read}; use crate::data_contract::errors::DataContractError; use crate::consensus::basic::decode::DecodingError; +use crate::data_contract::config::v1::DataContractConfigGettersV1; +use crate::data_contract::config::DataContractConfig; +use crate::data_contract::document_type::property_names; use crate::prelude::TimestampMillis; use crate::ProtocolError; use array::ArrayItemType; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use indexmap::IndexMap; use integer_encoding::{VarInt, VarIntReader}; +use itertools::Itertools; +use platform_value::btreemap_extensions::{BTreeValueMapHelper, BTreeValueMapPathHelper}; use platform_value::{Identifier, Value}; use platform_version::version::PlatformVersion; use rand::distributions::{Alphanumeric, Standard}; @@ -67,6 +73,7 @@ pub enum DocumentPropertyType { } impl DocumentPropertyType { + #[deprecated = "this method is missing required information to create a type. Use TryFrom<&Value> instead."] pub fn try_from_name(name: &str) -> Result { match name { "u128" => Ok(DocumentPropertyType::U128), @@ -2006,6 +2013,98 @@ impl DocumentPropertyType { let mut cursor = Cursor::new(wtr); cursor.read_f64::().ok() } + + pub fn is_integer(&self) -> bool { + matches!( + self, + DocumentPropertyType::I8 + | DocumentPropertyType::I16 + | DocumentPropertyType::I32 + | DocumentPropertyType::I64 + | DocumentPropertyType::U8 + | DocumentPropertyType::U16 + | DocumentPropertyType::U32 + | DocumentPropertyType::U64 + ) + } + + pub fn try_from_value_map( + value_map: &BTreeMap, + options: &DocumentPropertyTypeParsingOptions, + ) -> Result { + let type_value = value_map.get_str(property_names::TYPE)?; + + let property_type = match type_value { + "integer" => { + if options.granular_integer_types { + find_integer_type_for_subschema_value(value_map)? + } else { + DocumentPropertyType::I64 + } + } + "string" => DocumentPropertyType::String(StringPropertySizes { + min_length: value_map.get_optional_integer(property_names::MIN_LENGTH)?, + max_length: value_map.get_optional_integer(property_names::MAX_LENGTH)?, + }), + "array" => { + // Only handling bytearrays for v1 + // Return an error if it is not a byte array + let Some(is_byte_array) = + value_map.get_optional_bool(property_names::BYTE_ARRAY)? + else { + return Err(DataContractError::InvalidContractStructure( + "only byte arrays are supported now".to_string(), + )); + }; + + if !is_byte_array { + return Err(DataContractError::InvalidContractStructure( + "byteArray should always be true if defined".to_string(), + )); + } + + match value_map.get_optional_str(property_names::CONTENT_MEDIA_TYPE)? { + Some("application/x.dash.dpp.identifier") => DocumentPropertyType::Identifier, + Some(_) | None => DocumentPropertyType::ByteArray(ByteArrayPropertySizes { + min_size: value_map.get_optional_integer(property_names::MIN_ITEMS)?, + max_size: value_map.get_optional_integer(property_names::MAX_ITEMS)?, + }), + } + } + "object" => Self::Object(Default::default()), + "boolean" => DocumentPropertyType::Boolean, + "number" => DocumentPropertyType::F64, + _ => { + return Err(DataContractError::InvalidContractStructure(format!( + "unsupported property type: {}", + type_value + ))); + } + }; + + Ok(property_type) + } +} + +#[derive(Debug, Clone)] +pub struct DocumentPropertyTypeParsingOptions { + pub granular_integer_types: bool, +} + +impl Default for DocumentPropertyTypeParsingOptions { + fn default() -> Self { + Self { + granular_integer_types: true, + } + } +} + +impl From<&DataContractConfig> for DocumentPropertyTypeParsingOptions { + fn from(config: &DataContractConfig) -> Self { + Self { + granular_integer_types: config.granular_integer_types(), + } + } } fn get_field_type_matching_error(value: &Value) -> DataContractError { @@ -2014,3 +2113,80 @@ fn get_field_type_matching_error(value: &Value) -> DataContractError { value )) } + +fn find_integer_type_for_subschema_value( + value: &BTreeMap, +) -> Result { + let minimum = value.get_optional_integer::(property_names::MINIMUM)?; + let maximum = value.get_optional_integer::(property_names::MAXIMUM)?; + + let property_type = match (minimum, maximum) { + (Some(min), Some(max)) => find_integer_type_for_min_and_max_values(min, max), + (Some(min), None) => { + if min >= 0 { + DocumentPropertyType::U64 + } else { + DocumentPropertyType::I64 + } + } + (None, Some(max)) => find_unsigned_integer_type_for_max_value(max), + (None, None) => { + // If enum is defined, we can try to figure out type based on minimal and maximal values + let enum_type = if let Some(enum_values) = + value.get_optional_inner_value_array::>(property_names::ENUM)? + { + match enum_values + .into_iter() + .filter_map(|v| v.as_integer()) + .minmax() + { + itertools::MinMaxResult::MinMax(min, max) => { + Some(find_integer_type_for_min_and_max_values(min, max)) + } + itertools::MinMaxResult::OneElement(val) => { + Some(find_unsigned_integer_type_for_max_value(val)) + } + _ => None, + } + } else { + None + }; + + if let Some(enum_type) = enum_type { + enum_type + } else { + DocumentPropertyType::I64 + } + } + }; + + Ok(property_type) +} + +fn find_unsigned_integer_type_for_max_value(max_value: i64) -> DocumentPropertyType { + if max_value <= u8::MAX as i64 { + DocumentPropertyType::U8 + } else if max_value <= u16::MAX as i64 { + DocumentPropertyType::U16 + } else if max_value <= u32::MAX as i64 { + DocumentPropertyType::U32 + } else { + DocumentPropertyType::U64 + } +} + +fn find_integer_type_for_min_and_max_values(min: i64, max: i64) -> DocumentPropertyType { + if min >= 0 { + find_unsigned_integer_type_for_max_value(max) + } else { + if min >= i8::MIN as i64 && max <= i8::MAX as i64 { + DocumentPropertyType::I8 + } else if min >= i16::MIN as i64 && max <= i16::MAX as i64 { + DocumentPropertyType::I16 + } else if min >= i32::MIN as i64 && max <= i32::MAX as i64 { + DocumentPropertyType::I32 + } else { + DocumentPropertyType::I64 + } + } +} diff --git a/packages/rs-dpp/src/data_contract/v0/methods/schema.rs b/packages/rs-dpp/src/data_contract/v0/methods/schema.rs index dddd285a6c..ea8c564923 100644 --- a/packages/rs-dpp/src/data_contract/v0/methods/schema.rs +++ b/packages/rs-dpp/src/data_contract/v0/methods/schema.rs @@ -23,9 +23,7 @@ impl DataContractSchemaMethodsV0 for DataContractV0 { self.id, schemas, defs.as_ref(), - self.config.documents_keep_history_contract_default(), - self.config.documents_mutable_contract_default(), - self.config.documents_can_be_deleted_contract_default(), + &self.config, full_validation, false, validation_operations, @@ -48,9 +46,7 @@ impl DataContractSchemaMethodsV0 for DataContractV0 { name, schema, self.schema_defs.as_ref(), - self.config.documents_keep_history_contract_default(), - self.config.documents_mutable_contract_default(), - self.config.documents_mutable_contract_default(), + &self.config, full_validation, validation_operations, platform_version, diff --git a/packages/rs-dpp/src/data_contract/v0/serialization/mod.rs b/packages/rs-dpp/src/data_contract/v0/serialization/mod.rs index 2a79edd362..eb77303719 100644 --- a/packages/rs-dpp/src/data_contract/v0/serialization/mod.rs +++ b/packages/rs-dpp/src/data_contract/v0/serialization/mod.rs @@ -91,9 +91,7 @@ impl DataContractV0 { id, document_schemas, schema_defs.as_ref(), - config.documents_keep_history_contract_default(), - config.documents_mutable_contract_default(), - config.documents_can_be_deleted_contract_default(), + &config, full_validation, false, validation_operations, @@ -133,9 +131,7 @@ impl DataContractV0 { id, document_schemas, schema_defs.as_ref(), - config.documents_keep_history_contract_default(), - config.documents_mutable_contract_default(), - config.documents_can_be_deleted_contract_default(), + &config, full_validation, false, validation_operations, diff --git a/packages/rs-dpp/src/data_contract/v1/methods/schema.rs b/packages/rs-dpp/src/data_contract/v1/methods/schema.rs index 901813af16..ae44171cb3 100644 --- a/packages/rs-dpp/src/data_contract/v1/methods/schema.rs +++ b/packages/rs-dpp/src/data_contract/v1/methods/schema.rs @@ -22,9 +22,7 @@ impl DataContractSchemaMethodsV0 for DataContractV1 { self.id, schemas, defs.as_ref(), - self.config.documents_keep_history_contract_default(), - self.config.documents_mutable_contract_default(), - self.config.documents_can_be_deleted_contract_default(), + &self.config, full_validation, !self.tokens.is_empty(), validation_operations, @@ -47,9 +45,7 @@ impl DataContractSchemaMethodsV0 for DataContractV1 { name, schema, self.schema_defs.as_ref(), - self.config.documents_keep_history_contract_default(), - self.config.documents_mutable_contract_default(), - self.config.documents_mutable_contract_default(), + &self.config, full_validation, validation_operations, platform_version, diff --git a/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs b/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs index 87825f6c69..9c1ff5fe51 100644 --- a/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs +++ b/packages/rs-dpp/src/data_contract/v1/serialization/mod.rs @@ -90,9 +90,7 @@ impl DataContractV1 { id, document_schemas, schema_defs.as_ref(), - config.documents_keep_history_contract_default(), - config.documents_mutable_contract_default(), - config.documents_can_be_deleted_contract_default(), + &config, full_validation, false, validation_operations, @@ -135,9 +133,7 @@ impl DataContractV1 { id, document_schemas, schema_defs.as_ref(), - config.documents_keep_history_contract_default(), - config.documents_mutable_contract_default(), - config.documents_can_be_deleted_contract_default(), + &config, full_validation, !tokens.is_empty(), validation_operations, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs index 54fc9f55ff..de433c3510 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs @@ -4,21 +4,12 @@ use bincode::{Decode, Encode}; use derive_more::Display; pub use super::super::token_base_transition::IDENTIFIER_FIELDS; -use crate::prelude::{ - DerivationEncryptionKeyIndex, RecipientKeyIndex, RootEncryptionKeyIndex, SenderKeyIndex, -}; use crate::state_transition::batch_transition::token_base_transition::TokenBaseTransition; +use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; use platform_value::Identifier; #[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; -pub type SharedEncryptedNote = (SenderKeyIndex, RecipientKeyIndex, Vec); -pub type PrivateEncryptedNote = ( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, -); - mod property_names { pub const AMOUNT: &str = "$amount"; pub const RECIPIENT_OWNER_ID: &str = "recipientOwnerId"; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs index 5f8875f3df..710f4cfdb0 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs @@ -3,7 +3,7 @@ use crate::prelude::{DerivationEncryptionKeyIndex, RecipientKeyIndex, RootEncryp use crate::state_transition::batch_transition::batched_transition::token_transfer_transition::TokenTransferTransitionV0; use crate::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use crate::state_transition::batch_transition::token_base_transition::TokenBaseTransition; -use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; +use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; impl TokenBaseTransitionAccessors for TokenTransferTransitionV0 { fn base(&self) -> &TokenBaseTransition { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs index 81cd4a1e46..aff9670182 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs @@ -4,7 +4,7 @@ use crate::state_transition::batch_transition::batched_transition::token_transfe use crate::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use crate::state_transition::batch_transition::TokenTransferTransition; use crate::state_transition::batch_transition::token_base_transition::TokenBaseTransition; -use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; +use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; impl TokenBaseTransitionAccessors for TokenTransferTransition { fn base(&self) -> &TokenBaseTransition { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs index 9895e738b9..d243861648 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs @@ -20,9 +20,6 @@ use crate::prelude::UserFeeIncrease; use crate::state_transition::batch_transition::batched_transition::BatchedTransition; use crate::state_transition::batch_transition::methods::v0::DocumentsBatchTransitionMethodsV0; use crate::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; -use crate::state_transition::batch_transition::token_transfer_transition::{ - PrivateEncryptedNote, SharedEncryptedNote, -}; use crate::state_transition::batch_transition::BatchTransition; #[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::{BatchTransitionV0, BatchTransitionV1}; @@ -30,6 +27,7 @@ use crate::state_transition::batch_transition::{BatchTransitionV0, BatchTransiti use crate::state_transition::StateTransition; #[cfg(feature = "state-transition-signing")] use crate::tokens::emergency_action::TokenEmergencyAction; +use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; use crate::ProtocolError; #[cfg(feature = "state-transition-signing")] use platform_value::Identifier; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs index e68792f331..62617d914c 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs @@ -11,13 +11,11 @@ use crate::identity::IdentityPublicKey; #[cfg(feature = "state-transition-signing")] use crate::prelude::{IdentityNonce, UserFeeIncrease}; use crate::state_transition::batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; -use crate::state_transition::batch_transition::token_transfer_transition::{ - PrivateEncryptedNote, SharedEncryptedNote, -}; #[cfg(feature = "state-transition-signing")] use crate::state_transition::StateTransition; #[cfg(feature = "state-transition-signing")] use crate::tokens::emergency_action::TokenEmergencyAction; +use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; #[cfg(feature = "state-transition-signing")] use crate::version::FeatureVersion; #[cfg(feature = "state-transition-signing")] diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs index eff8b16880..3a7454eecb 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs @@ -71,13 +71,12 @@ use crate::state_transition::batch_transition::token_freeze_transition::TokenFre #[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::token_mint_transition::TokenMintTransitionV0; #[cfg(feature = "state-transition-signing")] -use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; -#[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::token_transfer_transition::TokenTransferTransitionV0; #[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::token_unfreeze_transition::TokenUnfreezeTransitionV0; #[cfg(feature = "state-transition-signing")] use crate::tokens::emergency_action::TokenEmergencyAction; +use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; impl DocumentsBatchTransitionAccessorsV0 for BatchTransitionV1 { type IterType<'a> diff --git a/packages/rs-dpp/src/tokens/mod.rs b/packages/rs-dpp/src/tokens/mod.rs index aa8703acbf..b05c9bdbd9 100644 --- a/packages/rs-dpp/src/tokens/mod.rs +++ b/packages/rs-dpp/src/tokens/mod.rs @@ -1,4 +1,7 @@ use crate::data_contract::TokenContractPosition; +use crate::prelude::{ + DerivationEncryptionKeyIndex, RecipientKeyIndex, RootEncryptionKeyIndex, SenderKeyIndex, +}; use crate::util::hash::hash_double; pub mod allowed_currency; @@ -8,6 +11,13 @@ pub mod info; pub mod status; pub mod token_event; +pub type SharedEncryptedNote = (SenderKeyIndex, RecipientKeyIndex, Vec); +pub type PrivateEncryptedNote = ( + RootEncryptionKeyIndex, + DerivationEncryptionKeyIndex, + Vec, +); + pub fn calculate_token_id(contract_id: &[u8; 32], token_pos: TokenContractPosition) -> [u8; 32] { let mut bytes = b"dash_token".to_vec(); bytes.extend_from_slice(contract_id); diff --git a/packages/rs-dpp/src/tokens/token_event.rs b/packages/rs-dpp/src/tokens/token_event.rs index fa5675dc5a..82c72825d7 100644 --- a/packages/rs-dpp/src/tokens/token_event.rs +++ b/packages/rs-dpp/src/tokens/token_event.rs @@ -21,8 +21,8 @@ pub type TokenEventPersonalEncryptedNote = Option<( Vec, )>; use crate::serialization::PlatformSerializableWithPlatformVersion; -use crate::state_transition::batch_transition::token_transfer_transition::SharedEncryptedNote; use crate::tokens::emergency_action::TokenEmergencyAction; +use crate::tokens::SharedEncryptedNote; use crate::ProtocolError; pub type RecipientIdentifier = Identifier; diff --git a/packages/rs-dpp/src/util/json_schema.rs b/packages/rs-dpp/src/util/json_schema.rs index eaf8fb0d90..936b459aa6 100644 --- a/packages/rs-dpp/src/util/json_schema.rs +++ b/packages/rs-dpp/src/util/json_schema.rs @@ -145,6 +145,7 @@ impl JsonSchemaExt for JsonValue { #[cfg(test)] mod test { + use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::accessors::DocumentTypeV0Getters; use crate::data_contract::document_type::DocumentType; @@ -206,14 +207,15 @@ mod test { let platform_value = platform_value::to_value(input).unwrap(); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + let document_type = DocumentType::try_from_schema( Identifier::random(), "doc", platform_value, None, - false, - false, - false, + &config, false, &mut vec![], platform_version, 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 06292c2342..546316bd9d 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -630,7 +630,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2484410); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2484810); let check_result = platform .check_tx( @@ -1141,7 +1141,7 @@ mod tests { // The processing fees should be twice as much as a fee multiplier of 0, // since a fee multiplier of 100 means 100% more of 1 (gives 2) - assert_eq!(processing_result.aggregated_fees().processing_fee, 4968820); + assert_eq!(processing_result.aggregated_fees().processing_fee, 4969620); let check_result = platform .check_tx( @@ -1613,7 +1613,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2484410); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2484810); platform .drive @@ -1699,7 +1699,7 @@ mod tests { assert_eq!( update_processing_result.aggregated_fees().processing_fee, - 2496910 + 2497370 ); let check_result = platform @@ -2069,7 +2069,7 @@ mod tests { ) .expect("expected to process state transition"); - assert_eq!(processing_result.aggregated_fees().processing_fee, 2484410); + assert_eq!(processing_result.aggregated_fees().processing_fee, 2484810); platform .drive diff --git a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs index d4177878bc..26c37964d3 100644 --- a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs @@ -773,10 +773,10 @@ mod tests { owner_id: Identifier::random_with_rng(&mut std_rng), properties: { let mut properties = BTreeMap::new(); - properties.insert("status".to_string(), Value::I64(0)); // Always queued - properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 - properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 - properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("status".to_string(), Value::U8(0)); // Always queued + properties.insert("pooling".to_string(), Value::U8(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::U32(1)); // Always 1 + properties.insert("amount".to_string(), Value::U64(1000)); // Set a minimum amount of 1000 properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script properties }, @@ -822,7 +822,7 @@ mod tests { WhereClause { field: "status".to_string(), operator: WhereOperator::Equal, - value: Value::I64(0), + value: Value::U8(0), }, ), ( @@ -830,7 +830,7 @@ mod tests { WhereClause { field: "pooling".to_string(), operator: WhereOperator::Equal, - value: Value::I64(0), + value: Value::U8(0), }, ), ( @@ -838,7 +838,7 @@ mod tests { WhereClause { field: "coreFeePerByte".to_string(), operator: WhereOperator::Equal, - value: Value::I64(1), + value: Value::U32(1), }, ), ]), @@ -937,10 +937,10 @@ mod tests { owner_id: Identifier::random_with_rng(&mut std_rng), properties: { let mut properties = BTreeMap::new(); - properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued - properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 - properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 - properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("status".to_string(), Value::U8(i as u8 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::U8(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::U32(1)); // Always 1 + properties.insert("amount".to_string(), Value::U64(1000)); // Set a minimum amount of 1000 properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script properties }, @@ -986,7 +986,7 @@ mod tests { WhereClause { field: "status".to_string(), operator: WhereOperator::Equal, - value: Value::I64(0), + value: Value::U8(0), }, ), ( @@ -994,7 +994,7 @@ mod tests { WhereClause { field: "pooling".to_string(), operator: WhereOperator::Equal, - value: Value::I64(0), + value: Value::U8(0), }, ), ( @@ -1002,7 +1002,7 @@ mod tests { WhereClause { field: "coreFeePerByte".to_string(), operator: WhereOperator::Equal, - value: Value::I64(1), + value: Value::U32(1), }, ), ]), @@ -1101,10 +1101,10 @@ mod tests { owner_id: Identifier::random_with_rng(&mut std_rng), properties: { let mut properties = BTreeMap::new(); - properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued - properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 - properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 - properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("status".to_string(), Value::U8(i as u8 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::U8(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::U32(1)); // Always 1 + properties.insert("amount".to_string(), Value::U64(1000)); // Set a minimum amount of 1000 properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script properties }, @@ -1140,11 +1140,11 @@ mod tests { field: "status".to_string(), operator: WhereOperator::In, value: Value::Array(vec![ - Value::I64(0), - Value::I64(1), - Value::I64(2), - Value::I64(3), - Value::I64(4), + Value::U8(0), + Value::U8(1), + Value::U8(2), + Value::U8(3), + Value::U8(4), ]), }), range_clause: None, @@ -1257,10 +1257,10 @@ mod tests { owner_id: Identifier::random_with_rng(&mut std_rng), properties: { let mut properties = BTreeMap::new(); - properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued - properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 - properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 - properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("status".to_string(), Value::U8(i as u8 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::U8(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::U32(1)); // Always 1 + properties.insert("amount".to_string(), Value::U64(1000)); // Set a minimum amount of 1000 properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script properties }, @@ -1302,11 +1302,11 @@ mod tests { field: "status".to_string(), operator: WhereOperator::In, value: Value::Array(vec![ - Value::I64(0), - Value::I64(1), - Value::I64(2), - Value::I64(3), - Value::I64(4), + Value::U8(0), + Value::U8(1), + Value::U8(2), + Value::U8(3), + Value::U8(4), ]), }), range_clause: None, @@ -1428,10 +1428,10 @@ mod tests { owner_id: Identifier::random_with_rng(&mut std_rng), properties: { let mut properties = BTreeMap::new(); - properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued - properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 - properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 - properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("status".to_string(), Value::U8(i as u8 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::U8(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::U32(1)); // Always 1 + properties.insert("amount".to_string(), Value::U64(1000)); // Set a minimum amount of 1000 properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script properties }, @@ -1473,11 +1473,11 @@ mod tests { field: "status".to_string(), operator: WhereOperator::In, value: Value::Array(vec![ - Value::I64(0), - Value::I64(1), - Value::I64(2), - Value::I64(3), - Value::I64(4), + Value::U8(0), + Value::U8(1), + Value::U8(2), + Value::U8(3), + Value::U8(4), ]), }), range_clause: None, @@ -1487,7 +1487,7 @@ mod tests { WhereClause { field: "pooling".to_string(), operator: WhereOperator::Equal, - value: Value::I64(0), + value: Value::U8(0), }, ), ( @@ -1495,7 +1495,7 @@ mod tests { WhereClause { field: "coreFeePerByte".to_string(), operator: WhereOperator::Equal, - value: Value::I64(1), + value: Value::U32(1), }, ), ]), diff --git a/packages/rs-drive/src/query/test_index.rs b/packages/rs-drive/src/query/test_index.rs index df368eb5c8..6e2576d19d 100644 --- a/packages/rs-drive/src/query/test_index.rs +++ b/packages/rs-drive/src/query/test_index.rs @@ -1,15 +1,15 @@ #[cfg(feature = "server")] #[cfg(test)] mod tests { - use dpp::data_contract::document_type::DocumentType; - use dpp::platform_value::{platform_value, Identifier}; - use dpp::util::cbor_serializer; - use serde_json::json; - use crate::config::DriveConfig; use crate::error::{query::QuerySyntaxError, Error}; use crate::query::DriveDocumentQuery; + use dpp::data_contract::config::DataContractConfig; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; + use dpp::data_contract::document_type::DocumentType; + use dpp::platform_value::{platform_value, Identifier}; + use dpp::util::cbor_serializer; + use serde_json::json; use dpp::tests::fixtures::get_dpns_data_contract_fixture; use dpp::version::PlatformVersion; @@ -77,14 +77,15 @@ mod tests { "additionalProperties": false, }); + let config = DataContractConfig::default_for_version(platform_version) + .expect("should create a default config"); + DocumentType::try_from_schema( Identifier::random(), "indexed_type", schema, None, - false, - false, - false, + &config, true, &mut vec![], platform_version, diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs index 6fd5f24a8e..eb9fc96519 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs @@ -3,7 +3,7 @@ use derive_more::From; use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::TokenBaseTransitionAction; use dpp::identifier::Identifier; use dpp::prelude::{DerivationEncryptionKeyIndex, RootEncryptionKeyIndex}; -use dpp::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; +use dpp::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; /// transformer module pub mod transformer; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs index 7cec7fc2be..4df8b2e93a 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs @@ -6,7 +6,7 @@ use dpp::identifier::Identifier; use dpp::prelude::{ DerivationEncryptionKeyIndex, IdentityNonce, RootEncryptionKeyIndex, }; -use dpp::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; +use dpp::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; use crate::drive::contract::DataContractFetchInfo; use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::{ TokenBaseTransitionAction, TokenBaseTransitionActionAccessorsV0, diff --git a/packages/rs-drive/tests/deterministic_root_hash.rs b/packages/rs-drive/tests/deterministic_root_hash.rs index 690fce9609..17cc57f0f9 100644 --- a/packages/rs-drive/tests/deterministic_root_hash.rs +++ b/packages/rs-drive/tests/deterministic_root_hash.rs @@ -302,7 +302,8 @@ mod tests { // We expect a different app hash because data contract is not serialized the same way let expected_app_hash = match platform_version.protocol_version { 0..7 => "1b80f4a9f00597b3f1ddca904b3cee67576868adcdd802c0a3f91e14209bb402", - _ => "387fe8e2298bb33e0ff79fd377eccb14109fb2534c7338c535bd74b5b8580580", + 7..9 => "387fe8e2298bb33e0ff79fd377eccb14109fb2534c7338c535bd74b5b8580580", + _ => "bd6560b17460a653077af58097e0c111d84696f25fd1c8f252b2a1af3fc5f122", }; assert_eq!(hex::encode(app_hash), expected_app_hash); diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index 8451908d68..537be44938 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -59,6 +59,7 @@ use base64::Engine; #[cfg(feature = "server")] use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::config::v1::DataContractConfigSettersV1; use dpp::data_contract::conversion::value::v0::DataContractValueConversionMethodsV0; use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; use dpp::document::serialization_traits::{ @@ -76,12 +77,11 @@ use dpp::tests::json_document::json_document_to_contract; use dpp::util::cbor_serializer; use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; -use once_cell::sync::Lazy; -use rand::prelude::StdRng; - #[cfg(feature = "server")] use drive::drive::contract::test_helpers::add_init_contracts_structure_operations; use drive::util::batch::grovedb_op_batch::GroveDbOpBatchV0Methods; +use once_cell::sync::Lazy; +use rand::prelude::StdRng; use drive::drive::document::query::QueryDocumentsOutcomeV0Methods; #[cfg(feature = "server")] @@ -880,7 +880,7 @@ pub fn setup_withdrawal_tests( .expect("expected to create contracts tree successfully"); // setup code - let contract = setup_contract( + let mut contract = setup_contract( &drive, "tests/supporting_files/contract/withdrawals/withdrawals-contract.json", None, @@ -890,6 +890,10 @@ pub fn setup_withdrawal_tests( None, ); + contract + .config_mut() + .set_granular_integer_types_enabled(false); + add_withdrawals_to_contract( &drive, &contract, 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 854a3dc331..04de060d85 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 @@ -14,7 +14,7 @@ pub const CONTRACT_VERSIONS_V2: DPPContractVersions = DPPContractVersions { }, contract_structure_version: 1, //changed created_data_contract_structure: 0, - config: 0, + config: 1, // changed to enable granular number types methods: DataContractMethodVersions { validate_document: 0, validate_update: 0, diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs index 6908c8864d..281907b079 100644 --- a/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs @@ -9,12 +9,9 @@ use dpp::identity::signer::Signer; use dpp::identity::IdentityPublicKey; use dpp::prelude::UserFeeIncrease; use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; -use dpp::state_transition::batch_transition::token_transfer_transition::{ - PrivateEncryptedNote, SharedEncryptedNote, -}; use dpp::state_transition::batch_transition::BatchTransition; use dpp::state_transition::StateTransition; -use dpp::tokens::calculate_token_id; +use dpp::tokens::{calculate_token_id, PrivateEncryptedNote, SharedEncryptedNote}; use dpp::version::PlatformVersion; /// A builder to configure and broadcast token transfer transitions diff --git a/packages/rs-sdk/tests/fetch/common.rs b/packages/rs-sdk/tests/fetch/common.rs index da109c4da0..676f7e2c7c 100644 --- a/packages/rs-sdk/tests/fetch/common.rs +++ b/packages/rs-sdk/tests/fetch/common.rs @@ -1,4 +1,5 @@ use dash_sdk::{mock::Mockable, platform::Query, Sdk}; +use dpp::data_contract::config::DataContractConfig; use dpp::{data_contract::DataContractFactory, prelude::Identifier}; use hex::ToHex; use rs_dapi_client::transport::TransportRequest; @@ -30,14 +31,15 @@ pub fn mock_document_type() -> dpp::data_contract::document_type::DocumentType { "additionalProperties": false, }); + let config = + DataContractConfig::default_for_version(platform_version).expect("create a default config"); + DocumentType::try_from_schema( Identifier::random(), "document_type_name", schema, None, - false, - false, - false, + &config, true, &mut vec![], platform_version, diff --git a/packages/strategy-tests/src/operations.rs b/packages/strategy-tests/src/operations.rs index 4dcebb9f62..ca22237f2a 100644 --- a/packages/strategy-tests/src/operations.rs +++ b/packages/strategy-tests/src/operations.rs @@ -424,16 +424,13 @@ impl PlatformDeserializableWithPotentialValidationFromVersionedStructure for Dat let name_str = name.to_str().expect( "Couldn't convert document type name to str in deserialization", ); - let schema = Value::try_from(schema_json).unwrap(); let owner_id = contract.owner_id(); // Assuming you have a method to get the owner_id from the contract DocumentType::try_from_schema( owner_id, name_str, - schema, + schema_json, None, - true, - true, - true, + contract.config(), full_validation, &mut vec![], platform_version, diff --git a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js index dc394aee3c..59cc00c885 100644 --- a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js +++ b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js @@ -66,7 +66,7 @@ describe('DataContractCreateTransition', () => { it('should return serialized State Transition', () => { const result = stateTransition.toBuffer(); expect(result).to.be.instanceOf(Buffer); - expect(result).to.have.lengthOf(2359); + expect(result).to.have.lengthOf(2360); }); it('should be able to restore contract config from bytes', () => { diff --git a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js index 444f695113..0931b62a1f 100644 --- a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js +++ b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js @@ -65,7 +65,7 @@ describe('DataContractUpdateTransition', () => { it('should return serialized State Transition', () => { const result = stateTransition.toBuffer(); expect(result).to.be.instanceOf(Buffer); - expect(result).to.have.lengthOf(2359); + expect(result).to.have.lengthOf(2360); }); it('should be able to restore contract config from bytes', () => {