dpp/data_contract/v1/serialization/
mod.rs1use crate::data_contract::document_type::DocumentType;
2use crate::data_contract::serialized_version::v0::DataContractInSerializationFormatV0;
3use crate::data_contract::serialized_version::DataContractInSerializationFormat;
4use crate::data_contract::{DataContract, DataContractV1};
5use crate::version::{PlatformVersion, PlatformVersionCurrentVersion};
6use crate::ProtocolError;
7use std::collections::BTreeMap;
8
9use crate::data_contract::serialized_version::v1::DataContractInSerializationFormatV1;
10use crate::validation::operations::ProtocolValidationOperation;
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13impl Serialize for DataContractV1 {
14 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
15 where
16 S: Serializer,
17 {
18 let data_contract: DataContract = self.clone().into();
19 let serialization_format = DataContractInSerializationFormatV1::from(data_contract);
20 serialization_format.serialize(serializer)
21 }
22}
23
24impl<'de> Deserialize<'de> for DataContractV1 {
25 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
26 where
27 D: Deserializer<'de>,
28 {
29 let serialization_format = DataContractInSerializationFormatV1::deserialize(deserializer)?;
30 let current_version = PlatformVersion::get_version_or_current_or_latest(None)
31 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
32 DataContractV1::try_from_platform_versioned_v1(
34 serialization_format,
35 true,
36 &mut vec![],
37 current_version,
38 )
39 .map_err(serde::de::Error::custom)
40 }
41}
42
43impl DataContractV1 {
44 pub(in crate::data_contract) fn try_from_platform_versioned(
45 value: DataContractInSerializationFormat,
46 full_validation: bool,
47 validation_operations: &mut Vec<ProtocolValidationOperation>,
48 platform_version: &PlatformVersion,
49 ) -> Result<Self, ProtocolError> {
50 match value {
51 DataContractInSerializationFormat::V0(serialization_format_v0) => {
52 let data_contract = DataContractV1::try_from_platform_versioned_v0(
53 serialization_format_v0,
54 full_validation,
55 validation_operations,
56 platform_version,
57 )?;
58
59 Ok(data_contract)
60 }
61 DataContractInSerializationFormat::V1(serialization_format_v1) => {
62 let data_contract = DataContractV1::try_from_platform_versioned_v1(
63 serialization_format_v1,
64 full_validation,
65 validation_operations,
66 platform_version,
67 )?;
68
69 Ok(data_contract)
70 }
71 }
72 }
73
74 pub(in crate::data_contract) fn try_from_platform_versioned_v0(
75 data_contract_data: DataContractInSerializationFormatV0,
76 full_validation: bool,
77 validation_operations: &mut Vec<ProtocolValidationOperation>,
78 platform_version: &PlatformVersion,
79 ) -> Result<Self, ProtocolError> {
80 let DataContractInSerializationFormatV0 {
81 id,
82 config,
83 version,
84 owner_id,
85 document_schemas,
86 schema_defs,
87 } = data_contract_data;
88
89 let document_types = DocumentType::create_document_types_from_document_schemas(
90 id,
91 1,
92 data_contract_data.config.version(),
93 document_schemas,
94 schema_defs.as_ref(),
95 &BTreeMap::new(),
96 &config,
97 full_validation,
98 false,
99 validation_operations,
100 platform_version,
101 )?;
102
103 let data_contract = DataContractV1 {
104 id,
105 version,
106 owner_id,
107 document_types,
108 config,
109 schema_defs,
110 created_at: None,
111 updated_at: None,
112 created_at_block_height: None,
113 updated_at_block_height: None,
114 created_at_epoch: None,
115 updated_at_epoch: None,
116 groups: Default::default(),
117 tokens: Default::default(),
118 keywords: Default::default(),
119 description: None,
120 };
121
122 Ok(data_contract)
123 }
124
125 pub(in crate::data_contract) fn try_from_platform_versioned_v1(
126 data_contract_data: DataContractInSerializationFormatV1,
127 full_validation: bool,
128 validation_operations: &mut Vec<ProtocolValidationOperation>,
129 platform_version: &PlatformVersion,
130 ) -> Result<Self, ProtocolError> {
131 let DataContractInSerializationFormatV1 {
132 id,
133 config,
134 version,
135 owner_id,
136 document_schemas,
137 schema_defs,
138 created_at,
139 updated_at,
140 created_at_block_height,
141 updated_at_block_height,
142 created_at_epoch,
143 updated_at_epoch,
144 groups,
145 tokens,
146 keywords,
147 description,
148 } = data_contract_data;
149
150 let document_types = DocumentType::create_document_types_from_document_schemas(
151 id,
152 1,
153 data_contract_data.config.version(),
154 document_schemas,
155 schema_defs.as_ref(),
156 &tokens,
157 &config,
158 full_validation,
159 !tokens.is_empty(),
160 validation_operations,
161 platform_version,
162 )?;
163
164 let data_contract = DataContractV1 {
165 id,
166 version,
167 owner_id,
168 document_types,
169 config,
170 schema_defs,
171 created_at,
172 updated_at,
173 created_at_block_height,
174 updated_at_block_height,
175 created_at_epoch,
176 updated_at_epoch,
177 groups,
178 tokens,
179 keywords: keywords
180 .into_iter()
181 .map(|keyword| keyword.to_lowercase())
182 .collect(),
183 description,
184 };
185
186 Ok(data_contract)
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use crate::data_contract::DataContract;
193 use crate::identity::accessors::IdentityGettersV0;
194 use crate::identity::Identity;
195 use crate::serialization::{
196 PlatformDeserializableWithPotentialValidationFromVersionedStructure,
197 PlatformSerializableWithPlatformVersion,
198 };
199 use crate::tests::fixtures::get_data_contract_fixture;
200 use crate::version::PlatformVersion;
201 use platform_version::version::LATEST_PLATFORM_VERSION;
202
203 #[test]
204 #[cfg(feature = "random-identities")]
205 fn data_contract_ser_de() {
206 let platform_version = PlatformVersion::get(7).expect("expected protocol version 7");
208 let identity = Identity::random_identity(5, Some(5), platform_version)
209 .expect("expected a random identity");
210 let contract =
211 get_data_contract_fixture(Some(identity.id()), 0, platform_version.protocol_version)
212 .data_contract_owned();
213 let bytes = contract
214 .serialize_to_bytes_with_platform_version(LATEST_PLATFORM_VERSION)
215 .expect("expected to serialize");
216 let recovered_contract =
217 DataContract::versioned_deserialize(&bytes, false, platform_version)
218 .expect("expected to deserialize state transition");
219 assert_eq!(contract, recovered_contract);
220 }
221
222 #[test]
223 #[cfg(feature = "random-identities")]
224 fn data_contract_v1_serde_json_roundtrip() {
225 use crate::data_contract::accessors::v0::DataContractV0Getters;
226 use crate::data_contract::DataContractV1;
227
228 let platform_version = PlatformVersion::get(9).expect("expected protocol version 9");
230 let identity = Identity::random_identity(5, Some(5), platform_version)
231 .expect("expected a random identity");
232 let contract =
233 get_data_contract_fixture(Some(identity.id()), 0, platform_version.protocol_version)
234 .data_contract_owned();
235 let v1 = contract.into_v1().expect("expected V1 contract");
236
237 let json = serde_json::to_string(&v1).expect("expected to serialize to JSON");
238 let recovered: DataContractV1 =
239 serde_json::from_str(&json).expect("expected to deserialize from JSON");
240
241 assert_eq!(v1.id(), recovered.id());
244 assert_eq!(v1.owner_id(), recovered.owner_id());
245 assert_eq!(v1.version(), recovered.version());
246 }
247}