dpp/data_contract/created_data_contract/
mod.rs1mod fields;
2pub mod v0;
3
4use crate::data_contract::created_data_contract::v0::{
5 CreatedDataContractInSerializationFormatV0, CreatedDataContractV0,
6};
7use crate::prelude::{DataContract, IdentityNonce};
8use crate::version::PlatformVersion;
9use crate::ProtocolError;
10use bincode::{Decode, DecodeUntrusted, Encode};
11use derive_more::From;
12
13use crate::data_contract::serialized_version::DataContractInSerializationFormat;
14use crate::serialization::{
15 PlatformDeserializableWithPotentialValidationFromVersionedStructureTrusted,
16 PlatformDeserializableWithPotentialValidationFromVersionedStructureUntrusted,
17 PlatformSerializableWithPlatformVersion,
18};
19use crate::ProtocolError::{PlatformDeserializationError, PlatformSerializationError};
20use platform_serialization::PLATFORM_BINCODE_CONFIG;
21use platform_version::TryIntoPlatformVersioned;
22
23#[derive(Clone, Debug, PartialEq, From)]
29pub enum CreatedDataContract {
30 V0(CreatedDataContractV0),
31}
32
33#[derive(Clone, Debug, Encode, Decode, From, DecodeUntrusted)]
34pub enum CreatedDataContractInSerializationFormat {
35 V0(CreatedDataContractInSerializationFormatV0),
36}
37
38impl PlatformSerializableWithPlatformVersion for CreatedDataContract {
39 type Error = ProtocolError;
40
41 fn serialize_to_bytes_with_platform_version(
42 &self,
43 platform_version: &PlatformVersion,
44 ) -> Result<Vec<u8>, ProtocolError> {
45 self.clone()
46 .serialize_consume_to_bytes_with_platform_version(platform_version)
47 }
48
49 fn serialize_consume_to_bytes_with_platform_version(
50 self,
51 platform_version: &PlatformVersion,
52 ) -> Result<Vec<u8>, ProtocolError> {
53 let (data_contract, identity_nonce) = self.data_contract_and_identity_nonce();
54 let data_contract_serialization_format: DataContractInSerializationFormat =
55 data_contract.try_into_platform_versioned(platform_version)?;
56 let created_data_contract_in_serialization_format = match platform_version
57 .dpp
58 .contract_versions
59 .created_data_contract_structure
60 {
61 0 => Ok(CreatedDataContractInSerializationFormat::V0(
62 CreatedDataContractInSerializationFormatV0 {
63 data_contract: data_contract_serialization_format,
64 identity_nonce,
65 },
66 )),
67 version => Err(ProtocolError::UnknownVersionMismatch {
68 method: "CreatedDataContract::serialize_to_bytes_with_platform_version".to_string(),
69 known_versions: vec![0],
70 received: version,
71 }),
72 }?;
73 let config = PLATFORM_BINCODE_CONFIG;
74 bincode::encode_to_vec(created_data_contract_in_serialization_format, config).map_err(|e| {
75 PlatformSerializationError(format!("unable to serialize CreatedDataContract: {}", e))
76 })
77 }
78}
79
80impl CreatedDataContract {
81 fn from_serialization_format(
85 created_data_contract_in_serialization_format: CreatedDataContractInSerializationFormat,
86 full_validation: bool,
87 platform_version: &PlatformVersion,
88 method: &str,
89 ) -> Result<Self, ProtocolError> {
90 let (data_contract_in_serialization_format, identity_nonce) =
91 created_data_contract_in_serialization_format.data_contract_and_identity_nonce_owned();
92 let data_contract = DataContract::try_from_platform_versioned(
94 data_contract_in_serialization_format.into_schema_form(),
95 full_validation,
96 &mut vec![],
97 platform_version,
98 )?;
99 match platform_version
100 .dpp
101 .contract_versions
102 .created_data_contract_structure
103 {
104 0 => Ok(CreatedDataContract::V0(CreatedDataContractV0 {
105 data_contract,
106 identity_nonce,
107 })),
108 version => Err(ProtocolError::UnknownVersionMismatch {
109 method: method.to_string(),
110 known_versions: vec![0],
111 received: version,
112 }),
113 }
114 }
115}
116
117impl PlatformDeserializableWithPotentialValidationFromVersionedStructureTrusted
118 for CreatedDataContract
119{
120 fn versioned_deserialize_trusted(
121 data: &[u8],
122 full_validation: bool,
123 platform_version: &PlatformVersion,
124 ) -> Result<Self, ProtocolError>
125 where
126 Self: Sized,
127 {
128 let config = PLATFORM_BINCODE_CONFIG;
129 let created_data_contract_in_serialization_format: CreatedDataContractInSerializationFormat =
130 bincode::borrow_decode_from_slice(data, config)
131 .map_err(|e| {
132 PlatformDeserializationError(format!(
133 "unable to deserialize DataContract: {}",
134 e
135 ))
136 })?
137 .0;
138 Self::from_serialization_format(
139 created_data_contract_in_serialization_format,
140 full_validation,
141 platform_version,
142 "CreatedDataContract::versioned_deserialize_trusted",
143 )
144 }
145}
146
147impl PlatformDeserializableWithPotentialValidationFromVersionedStructureUntrusted
148 for CreatedDataContract
149{
150 fn versioned_deserialize_untrusted(
151 data: &[u8],
152 full_validation: bool,
153 platform_version: &PlatformVersion,
154 ) -> Result<Self, ProtocolError>
155 where
156 Self: Sized,
157 {
158 let config = PLATFORM_BINCODE_CONFIG;
159 let created_data_contract_in_serialization_format: CreatedDataContractInSerializationFormat =
160 bincode::borrow_decode_from_slice_untrusted(data, config)
161 .map_err(|e| {
162 PlatformDeserializationError(format!(
163 "unable to deserialize DataContract: {}",
164 e
165 ))
166 })?
167 .0;
168 Self::from_serialization_format(
169 created_data_contract_in_serialization_format,
170 full_validation,
171 platform_version,
172 "CreatedDataContract::versioned_deserialize_untrusted",
173 )
174 }
175}
176
177impl From<CreatedDataContract> for DataContract {
178 fn from(value: CreatedDataContract) -> Self {
179 match value {
180 CreatedDataContract::V0(created_data_contract) => created_data_contract.data_contract,
181 }
182 }
183}
184
185impl CreatedDataContract {
186 pub fn data_contract_owned(self) -> DataContract {
187 match self {
188 CreatedDataContract::V0(v0) => v0.data_contract,
189 }
190 }
191
192 pub fn data_contract_and_identity_nonce(self) -> (DataContract, IdentityNonce) {
193 match self {
194 CreatedDataContract::V0(v0) => (v0.data_contract, v0.identity_nonce),
195 }
196 }
197
198 pub fn data_contract(&self) -> &DataContract {
199 match self {
200 CreatedDataContract::V0(v0) => &v0.data_contract,
201 }
202 }
203
204 pub fn data_contract_mut(&mut self) -> &mut DataContract {
205 match self {
206 CreatedDataContract::V0(v0) => &mut v0.data_contract,
207 }
208 }
209
210 pub fn identity_nonce(&self) -> IdentityNonce {
211 match self {
212 CreatedDataContract::V0(v0) => v0.identity_nonce,
213 }
214 }
215
216 #[cfg(test)]
217 pub fn set_identity_nonce(&mut self, identity_nonce: IdentityNonce) {
218 match self {
219 CreatedDataContract::V0(v0) => v0.identity_nonce = identity_nonce,
220 }
221 }
222
223 pub fn from_contract_and_identity_nonce(
224 data_contract: DataContract,
225 identity_nonce: IdentityNonce,
226 platform_version: &PlatformVersion,
227 ) -> Result<CreatedDataContract, ProtocolError> {
228 match platform_version
229 .dpp
230 .contract_versions
231 .created_data_contract_structure
232 {
233 0 => Ok(CreatedDataContractV0 {
234 data_contract,
235 identity_nonce,
236 }
237 .into()),
238 version => Err(ProtocolError::UnknownVersionMismatch {
239 method: "CreatedDataContract::from_contract_and_entropy".to_string(),
240 known_versions: vec![0],
241 received: version,
242 }),
243 }
244 }
245}
246
247impl CreatedDataContractInSerializationFormat {
248 pub fn data_contract_and_identity_nonce_owned(
249 self,
250 ) -> (DataContractInSerializationFormat, IdentityNonce) {
251 match self {
252 CreatedDataContractInSerializationFormat::V0(v0) => {
253 (v0.data_contract, v0.identity_nonce)
254 }
255 }
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 use crate::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters};
263 use crate::tests::fixtures::get_data_contract_fixture;
264 use crate::version::PlatformVersion;
265 use platform_serialization::PLATFORM_BINCODE_CONFIG;
266
267 fn sample_created() -> CreatedDataContract {
268 get_data_contract_fixture(None, 42, 1)
269 }
270
271 #[test]
276 fn from_contract_and_identity_nonce_wraps_v0() {
277 let platform_version = PlatformVersion::latest();
278 let created = sample_created();
279 let contract = created.data_contract().clone();
280 let wrapped = CreatedDataContract::from_contract_and_identity_nonce(
281 contract.clone(),
282 99,
283 platform_version,
284 )
285 .expect("should wrap successfully on latest version");
286 assert_eq!(wrapped.identity_nonce(), 99);
287 assert_eq!(wrapped.data_contract().id(), contract.id());
288 assert!(matches!(wrapped, CreatedDataContract::V0(_)));
290 }
291
292 #[test]
293 fn identity_nonce_getter_returns_underlying_value() {
294 let created = sample_created();
295 assert_eq!(created.identity_nonce(), 42);
296 }
297
298 #[test]
299 fn data_contract_getter_returns_same_id() {
300 let created = sample_created();
301 let via_getter = created.data_contract();
302 let expected_id = via_getter.id();
303 let owned = created.clone().data_contract_owned();
305 assert_eq!(owned.id(), expected_id);
306 }
307
308 #[test]
309 fn data_contract_mut_allows_mutation() {
310 let mut created = sample_created();
311 let original_id = created.data_contract().id();
312 let new_id = platform_value::Identifier::from([7u8; 32]);
313 created.data_contract_mut().set_id(new_id);
315 assert_ne!(created.data_contract().id(), original_id);
316 assert_eq!(created.data_contract().id(), new_id);
317 }
318
319 #[test]
320 fn data_contract_and_identity_nonce_extracts_both() {
321 let created = sample_created();
322 let (contract, nonce) = created.clone().data_contract_and_identity_nonce();
323 assert_eq!(nonce, 42);
324 assert_eq!(contract.id(), created.data_contract().id());
325 }
326
327 #[test]
328 fn set_identity_nonce_updates_value() {
329 let mut created = sample_created();
330 created.set_identity_nonce(777);
331 assert_eq!(created.identity_nonce(), 777);
332 }
333
334 #[test]
339 fn from_created_to_data_contract() {
340 let created = sample_created();
341 let expected_id = created.data_contract().id();
342 let dc: DataContract = created.into();
343 assert_eq!(dc.id(), expected_id);
344 }
345
346 #[test]
353 fn serialize_roundtrip_via_platform_version() {
354 let platform_version = PlatformVersion::latest();
355 let created = sample_created();
356 let bytes = created
357 .serialize_to_bytes_with_platform_version(platform_version)
358 .expect("serialize should succeed");
359 assert!(!bytes.is_empty());
360
361 let restored =
362 CreatedDataContract::versioned_deserialize_untrusted(&bytes, false, platform_version)
363 .expect("deserialize should succeed");
364 assert_eq!(restored.identity_nonce(), created.identity_nonce());
365 assert_eq!(restored.data_contract().id(), created.data_contract().id());
366 }
367
368 #[test]
369 fn serialize_consume_to_bytes_matches_clone_path() {
370 let platform_version = PlatformVersion::latest();
371 let created = sample_created();
372 let via_ref = created
373 .serialize_to_bytes_with_platform_version(platform_version)
374 .expect("ref serialize should succeed");
375 let via_consume = created
376 .clone()
377 .serialize_consume_to_bytes_with_platform_version(platform_version)
378 .expect("consume serialize should succeed");
379 assert_eq!(via_ref, via_consume);
382 }
383
384 #[test]
385 fn versioned_deserialize_rejects_garbage() {
386 let platform_version = PlatformVersion::latest();
387 let garbage = vec![0xFFu8; 16];
388 let err =
389 CreatedDataContract::versioned_deserialize_untrusted(&garbage, false, platform_version)
390 .expect_err("random bytes should not deserialize");
391 match err {
392 ProtocolError::PlatformDeserializationError(_) => {}
393 other => panic!("expected PlatformDeserializationError, got {other:?}"),
394 }
395 }
396
397 #[test]
398 fn versioned_deserialize_rejects_empty_input() {
399 let platform_version = PlatformVersion::latest();
400 let err =
401 CreatedDataContract::versioned_deserialize_untrusted(&[], false, platform_version)
402 .expect_err("empty input should not deserialize");
403 assert!(matches!(
404 err,
405 ProtocolError::PlatformDeserializationError(_)
406 ));
407 }
408
409 #[test]
410 fn versioned_deserialize_trusted_agrees_with_untrusted() {
411 let platform_version = PlatformVersion::latest();
412 let created = sample_created();
413 let bytes = created
414 .serialize_to_bytes_with_platform_version(platform_version)
415 .expect("serialize should succeed");
416
417 let trusted =
418 CreatedDataContract::versioned_deserialize_trusted(&bytes, false, platform_version)
419 .expect("trusted deserialize should succeed");
420 let untrusted =
421 CreatedDataContract::versioned_deserialize_untrusted(&bytes, false, platform_version)
422 .expect("untrusted deserialize should succeed");
423 assert_eq!(trusted, untrusted);
424 assert_eq!(trusted.identity_nonce(), created.identity_nonce());
425 assert_eq!(trusted.data_contract().id(), created.data_contract().id());
426 }
427
428 #[test]
429 fn versioned_deserialize_trusted_rejects_garbage_and_empty_input() {
430 let platform_version = PlatformVersion::latest();
431 for input in [vec![0xFFu8; 16], vec![]] {
432 let err =
433 CreatedDataContract::versioned_deserialize_trusted(&input, false, platform_version)
434 .expect_err("malformed input should not deserialize");
435 assert!(matches!(
436 err,
437 ProtocolError::PlatformDeserializationError(_)
438 ));
439 }
440 }
441
442 #[test]
447 fn in_serialization_format_data_contract_and_identity_nonce_owned() {
448 let platform_version = PlatformVersion::latest();
449 let created = sample_created();
450 let bytes = created
453 .clone()
454 .serialize_consume_to_bytes_with_platform_version(platform_version)
455 .expect("serialize");
456 let config = PLATFORM_BINCODE_CONFIG;
457 let (decoded, _consumed) = bincode::borrow_decode_from_slice_untrusted::<
458 CreatedDataContractInSerializationFormat,
459 _,
460 >(&bytes, config)
461 .expect("raw bincode decode should succeed");
462 let (_contract_fmt, nonce) = decoded.data_contract_and_identity_nonce_owned();
463 assert_eq!(nonce, created.identity_nonce());
464 }
465
466 #[test]
472 fn clone_and_equality() {
473 let a = sample_created();
474 let b = a.clone();
475 assert_eq!(a, b);
476 }
477
478 #[test]
479 fn different_nonce_breaks_equality() {
480 let a = sample_created();
481 let mut b = a.clone();
482 b.set_identity_nonce(a.identity_nonce().wrapping_add(1));
483 assert_ne!(a, b);
484 }
485}