Skip to main content

dpp/data_contract/config/v0/
mod.rs

1use crate::data_contract::config;
2use crate::data_contract::config::v1::DataContractConfigV1;
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,
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 DataContractConfigV0 {
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}
49
50/// Trait representing getters for `DataContractConfigV0`
51pub trait DataContractConfigGettersV0 {
52    /// Returns whether the contract can be deleted.
53    fn can_be_deleted(&self) -> bool;
54
55    /// Returns whether the contract is read-only.
56    fn readonly(&self) -> bool;
57
58    /// Returns whether the contract keeps history.
59    fn keeps_history(&self) -> bool;
60
61    /// Returns whether documents in the contract keep history by default.
62    fn documents_keep_history_contract_default(&self) -> bool;
63
64    /// Returns whether documents in the contract are mutable by default.
65    fn documents_mutable_contract_default(&self) -> bool;
66    fn documents_can_be_deleted_contract_default(&self) -> bool;
67
68    /// Encryption key storage requirements
69    fn requires_identity_encryption_bounded_key(&self) -> Option<StorageKeyRequirements>;
70
71    /// Decryption key storage requirements
72    fn requires_identity_decryption_bounded_key(&self) -> Option<StorageKeyRequirements>;
73}
74
75/// Trait representing setters for `DataContractConfigV0`
76pub trait DataContractConfigSettersV0 {
77    /// Sets whether the contract can be deleted.
78    fn set_can_be_deleted(&mut self, value: bool);
79
80    /// Sets whether the contract is read-only.
81    fn set_readonly(&mut self, value: bool);
82
83    /// Sets whether the contract keeps history.
84    fn set_keeps_history(&mut self, value: bool);
85
86    /// Sets whether documents in the contract keep history by default.
87    fn set_documents_keep_history_contract_default(&mut self, value: bool);
88
89    /// Sets whether documents in the contract are mutable by default.
90    fn set_documents_mutable_contract_default(&mut self, value: bool);
91
92    /// Sets whether documents in the contract can be deleted by default.
93    fn set_documents_can_be_deleted_contract_default(&mut self, value: bool);
94
95    /// Sets Encryption key storage requirements.
96    fn set_requires_identity_encryption_bounded_key(
97        &mut self,
98        value: Option<StorageKeyRequirements>,
99    );
100
101    /// Sets Decryption key storage requirements.
102    fn set_requires_identity_decryption_bounded_key(
103        &mut self,
104        value: Option<StorageKeyRequirements>,
105    );
106}
107
108impl Default for DataContractConfigV0 {
109    fn default() -> Self {
110        DataContractConfigV0 {
111            can_be_deleted: DEFAULT_CONTRACT_CAN_BE_DELETED,
112            readonly: !DEFAULT_CONTRACT_MUTABILITY,
113            keeps_history: DEFAULT_CONTRACT_KEEPS_HISTORY,
114            documents_keep_history_contract_default: DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY,
115            documents_mutable_contract_default: DEFAULT_CONTRACT_DOCUMENT_MUTABILITY,
116            documents_can_be_deleted_contract_default: DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED,
117            requires_identity_encryption_bounded_key: None,
118            requires_identity_decryption_bounded_key: None,
119        }
120    }
121}
122
123impl DataContractConfigV0 {
124    pub fn default_with_version() -> DataContractConfig {
125        Self::default().into()
126    }
127}
128
129impl DataContractConfigV0 {
130    /// Retrieve contract configuration properties.
131    ///
132    /// This method takes a BTreeMap representing a contract and retrieves
133    /// the configuration properties based on the values found in the map.
134    ///
135    /// The process of retrieving contract configuration properties is versioned,
136    /// and the version is determined by the platform version parameter.
137    /// If the version is not supported, an error is returned.
138    ///
139    /// # Parameters
140    ///
141    /// * `contract`: BTreeMap representing the contract.
142    /// * `platform_version`: The platform version being used.
143    ///
144    /// # Returns
145    ///
146    /// * `Result<ContractConfig, ProtocolError>`: On success, a ContractConfig.
147    ///   On failure, a ProtocolError.
148    #[inline(always)]
149    pub(super) fn get_contract_configuration_properties_v0(
150        contract: &BTreeMap<String, Value>,
151    ) -> Result<DataContractConfigV0, ProtocolError> {
152        let keeps_history = contract
153            .get_optional_bool(config::property::KEEPS_HISTORY)?
154            .unwrap_or(DEFAULT_CONTRACT_KEEPS_HISTORY);
155        let can_be_deleted = contract
156            .get_optional_bool(config::property::CAN_BE_DELETED)?
157            .unwrap_or(DEFAULT_CONTRACT_CAN_BE_DELETED);
158
159        let readonly = contract
160            .get_optional_bool(config::property::READONLY)?
161            .unwrap_or(!DEFAULT_CONTRACT_MUTABILITY);
162
163        let documents_keep_history_contract_default = contract
164            .get_optional_bool(config::property::DOCUMENTS_KEEP_HISTORY_CONTRACT_DEFAULT)?
165            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY);
166
167        let documents_mutable_contract_default = contract
168            .get_optional_bool(config::property::DOCUMENTS_MUTABLE_CONTRACT_DEFAULT)?
169            .unwrap_or(DEFAULT_CONTRACT_DOCUMENT_MUTABILITY);
170
171        let documents_can_be_deleted_contract_default = contract
172            .get_optional_bool(config::property::DOCUMENTS_CAN_BE_DELETED_CONTRACT_DEFAULT)?
173            .unwrap_or(DEFAULT_CONTRACT_DOCUMENTS_CAN_BE_DELETED);
174
175        let requires_identity_encryption_bounded_key = contract
176            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)?
177            .map(|int| int.try_into())
178            .transpose()?;
179
180        // CONSENSUS-FROZEN BUG: this intentionally reads from
181        // `REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY` (not the matching
182        // DECRYPTION constant). The V0 parser shipped this way and its output
183        // is part of V0 protocol behavior, so it must not be changed even
184        // though it looks like a copy-paste typo. V1 reads from the correct
185        // DECRYPTION key — see v1/mod.rs. Do not "fix" this line.
186        let requires_identity_decryption_bounded_key = contract
187            .get_optional_integer::<u8>(config::property::REQUIRES_IDENTITY_ENCRYPTION_BOUNDED_KEY)?
188            .map(|int| int.try_into())
189            .transpose()?;
190
191        Ok(DataContractConfigV0 {
192            can_be_deleted,
193            readonly,
194            keeps_history,
195            documents_keep_history_contract_default,
196            documents_mutable_contract_default,
197            documents_can_be_deleted_contract_default,
198            requires_identity_encryption_bounded_key,
199            requires_identity_decryption_bounded_key,
200        })
201    }
202}
203
204impl From<DataContractConfigV1> for DataContractConfigV0 {
205    fn from(value: DataContractConfigV1) -> Self {
206        DataContractConfigV0 {
207            can_be_deleted: value.can_be_deleted,
208            readonly: value.readonly,
209            keeps_history: value.keeps_history,
210            documents_keep_history_contract_default: value.documents_keep_history_contract_default,
211            documents_mutable_contract_default: value.documents_mutable_contract_default,
212            documents_can_be_deleted_contract_default: value
213                .documents_can_be_deleted_contract_default,
214            requires_identity_encryption_bounded_key: value
215                .requires_identity_encryption_bounded_key,
216            requires_identity_decryption_bounded_key: value
217                .requires_identity_decryption_bounded_key,
218        }
219    }
220}