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