Skip to main content

dpp/data_contract/config/v1/
mod.rs

1use crate::data_contract::config;
2use crate::data_contract::config::v0::{DataContractConfigGettersV0, DataContractConfigSettersV0};
3use crate::data_contract::config::{
4    DataContractConfig, DEFAULT_CONTRACT_CAN_BE_DELETED, DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED,
5    DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY, DEFAULT_CONTRACT_DOCUMENT_MUTABILITY,
6    DEFAULT_CONTRACT_KEEPS_HISTORY, DEFAULT_CONTRACT_MUTABILITY, DEFAULT_SIZED_INTEGER_TYPES,
7};
8use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements;
9#[cfg(feature = "json-conversion")]
10use crate::serialization::json_safe_fields;
11use crate::ProtocolError;
12use bincode::{Decode, DecodeUntrusted, Encode};
13use platform_value::btreemap_extensions::BTreeValueMapHelper;
14use platform_value::Value;
15use serde::{Deserialize, Serialize};
16use std::collections::BTreeMap;
17
18#[cfg_attr(feature = "json-conversion", json_safe_fields)]
19#[derive(
20    Serialize, Deserialize, Decode, Encode, Debug, Clone, Copy, PartialEq, Eq, DecodeUntrusted,
21)]
22#[serde(rename_all = "camelCase", default)]
23pub struct DataContractConfigV1 {
24    /// Can the contract ever be deleted. If the contract is deleted, so should be all
25    /// documents associated with it. TODO: There should also be a way to "stop" the contract -
26    /// contract and documents are kept in the system, but no new documents can be added to it
27    pub can_be_deleted: bool,
28    /// Is the contract mutable. Means that the document definitions can be changed or new
29    /// document definitions can be added to the contract
30    pub readonly: bool,
31    /// Does the contract keep history when the contract itself changes
32    pub keeps_history: bool,
33    /// Do documents in the contract keep history. This is a default for all documents in
34    /// the contract, but can be overridden by the document itself
35    pub documents_keep_history_contract_default: bool,
36    /// Are documents in the contract mutable? This specifies whether the documents can be
37    /// changed. This is a default for all document types in the contract, but can be
38    /// overridden by the document type config.
39    pub documents_mutable_contract_default: bool,
40    /// Can documents in the contract be deleted? This specifies whether the documents can be
41    /// deleted. This is a default for all document types in the contract, but can be
42    /// overridden by the document types itself.
43    pub documents_can_be_deleted_contract_default: bool,
44    /// Encryption key storage requirements
45    pub requires_identity_encryption_bounded_key: Option<StorageKeyRequirements>,
46    /// Decryption key storage requirements
47    pub requires_identity_decryption_bounded_key: Option<StorageKeyRequirements>,
48    /// Use sized integer Rust types for `integer` property type based on validation rules
49    pub sized_integer_types: bool,
50}
51
52/// Trait representing getters for `DataContractConfigV1`
53pub trait DataContractConfigGettersV1: DataContractConfigGettersV0 {
54    /// Use sized integer Rust types for `integer` property type based on validation rules
55    fn sized_integer_types(&self) -> bool;
56}
57
58/// Trait representing setters for `DataContractConfigV1`
59pub trait DataContractConfigSettersV1: DataContractConfigSettersV0 {
60    /// Enable/disable sized integer Rust types for `integer` property type
61    fn set_sized_integer_types_enabled(&mut self, enable: bool);
62}
63
64impl Default for DataContractConfigV1 {
65    fn default() -> Self {
66        DataContractConfigV1 {
67            can_be_deleted: DEFAULT_CONTRACT_CAN_BE_DELETED,
68            readonly: !DEFAULT_CONTRACT_MUTABILITY,
69            keeps_history: DEFAULT_CONTRACT_KEEPS_HISTORY,
70            documents_keep_history_contract_default: DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY,
71            documents_mutable_contract_default: DEFAULT_CONTRACT_DOCUMENT_MUTABILITY,
72            documents_can_be_deleted_contract_default: DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED,
73            requires_identity_encryption_bounded_key: None,
74            requires_identity_decryption_bounded_key: None,
75            sized_integer_types: true,
76        }
77    }
78}
79
80impl DataContractConfigV1 {
81    pub fn default_with_version() -> DataContractConfig {
82        Self::default().into()
83    }
84}
85
86impl DataContractConfigV1 {
87    /// Retrieve contract configuration properties.
88    ///
89    /// This method takes a BTreeMap representing a contract and retrieves
90    /// the configuration properties based on the values found in the map.
91    ///
92    /// The process of retrieving contract configuration properties is versioned,
93    /// and the version is determined by the platform version parameter.
94    /// If the version is not supported, an error is returned.
95    ///
96    /// # Parameters
97    ///
98    /// * `contract`: BTreeMap representing the contract.
99    /// * `platform_version`: The platform version being used.
100    ///
101    /// # Returns
102    ///
103    /// * `Result<ContractConfig, ProtocolError>`: On success, a ContractConfig.
104    ///   On failure, a ProtocolError.
105    #[inline(always)]
106    pub(super) fn get_contract_configuration_properties_v1(
107        contract: &BTreeMap<String, Value>,
108    ) -> Result<DataContractConfigV1, ProtocolError> {
109        let keeps_history = contract
110            .get_optional_bool(config::property::KEEPS_HISTORY)?
111            .unwrap_or(DEFAULT_CONTRACT_KEEPS_HISTORY);
112        let can_be_deleted = contract
113            .get_optional_bool(config::property::CAN_BE_DELETED)?
114            .unwrap_or(DEFAULT_CONTRACT_CAN_BE_DELETED);
115
116        let readonly = contract
117            .get_optional_bool(config::property::READONLY)?
118            .unwrap_or(!DEFAULT_CONTRACT_MUTABILITY);
119
120        let documents_keep_history_contract_default = contract
121            .get_optional_bool(config::property::DOCUMENTS_KEEP_HISTORY_CONTRACT_DEFAULT)?
122            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY);
123
124        let documents_mutable_contract_default = contract
125            .get_optional_bool(config::property::DOCUMENTS_MUTABLE_CONTRACT_DEFAULT)?
126            .unwrap_or(DEFAULT_CONTRACT_DOCUMENT_MUTABILITY);
127
128        let documents_can_be_deleted_contract_default = contract
129            .get_optional_bool(config::property::DOCUMENTS_CAN_BE_DELETED_CONTRACT_DEFAULT)?
130            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED);
131
132        let requires_identity_encryption_bounded_key = contract
133            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)?
134            .map(|int| int.try_into())
135            .transpose()?;
136
137        let requires_identity_decryption_bounded_key = contract
138            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_DECRYPTION_BOUNDED_KEY)?
139            .map(|int| int.try_into())
140            .transpose()?;
141
142        let sized_integer_types = contract
143            .get_optional_bool(config::property::SIZED_INTEGER_TYPES)?
144            .unwrap_or(DEFAULT_SIZED_INTEGER_TYPES);
145
146        Ok(DataContractConfigV1 {
147            can_be_deleted,
148            readonly,
149            keeps_history,
150            documents_keep_history_contract_default,
151            documents_mutable_contract_default,
152            documents_can_be_deleted_contract_default,
153            requires_identity_encryption_bounded_key,
154            requires_identity_decryption_bounded_key,
155            sized_integer_types,
156        })
157    }
158}