Skip to main content

dpp/data_contract/conversion/value/
mod.rs

1pub mod v0;
2
3use crate::data_contract::conversion::value::v0::DataContractValueConversionMethodsV0;
4use crate::data_contract::v0::DataContractV0;
5use crate::data_contract::v1::DataContractV1;
6use crate::data_contract::DataContract;
7use crate::version::PlatformVersion;
8use crate::ProtocolError;
9use platform_value::Value;
10
11impl DataContractValueConversionMethodsV0 for DataContract {
12    fn from_value(
13        raw_object: Value,
14        full_validation: bool,
15        platform_version: &PlatformVersion,
16    ) -> Result<Self, ProtocolError> {
17        match platform_version
18            .dpp
19            .contract_versions
20            .contract_structure_version
21        {
22            0 => Ok(
23                DataContractV0::from_value(raw_object, full_validation, platform_version)?.into(),
24            ),
25            1 => Ok(
26                DataContractV1::from_value(raw_object, full_validation, platform_version)?.into(),
27            ),
28            version => Err(ProtocolError::UnknownVersionMismatch {
29                method: "DataContract::from_value".to_string(),
30                known_versions: vec![0, 1],
31                received: version,
32            }),
33        }
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    //! Pins for the explicit-version `to_value` path: the serialization format
40    //! must be selected by the *passed* platform version, never by the
41    //! process-global current version (which parallel tests may mutate — see
42    //! the serde module doc for the race this guards against).
43    use super::*;
44    use crate::data_contract::accessors::v0::DataContractV0Getters;
45    use crate::tests::fixtures::get_data_contract_fixture;
46
47    /// A protocol version whose contract serialization default is format 0
48    /// (frozen behavior; latest defaults to format 1).
49    const FORMAT_0_PROTOCOL_VERSION: u32 = 8;
50
51    fn format_0_platform_version() -> &'static PlatformVersion {
52        let platform_version =
53            PlatformVersion::get(FORMAT_0_PROTOCOL_VERSION).expect("expected platform version 8");
54        assert_eq!(
55            platform_version
56                .dpp
57                .contract_versions
58                .contract_serialization_version
59                .default_current_version,
60            0,
61            "test premise: protocol version 8 serializes contracts in format 0"
62        );
63        platform_version
64    }
65
66    #[test]
67    fn to_value_selects_format_by_explicit_platform_version() {
68        let contract =
69            get_data_contract_fixture(None, 0, PlatformVersion::latest().protocol_version)
70                .data_contract()
71                .clone();
72
73        let old_value = contract
74            .to_value(format_0_platform_version())
75            .expect("to_value at format-0 version");
76        assert_eq!(old_value.get_str("$formatVersion"), Ok("0"));
77
78        let new_value = contract
79            .to_value(PlatformVersion::latest())
80            .expect("to_value at latest");
81        assert_eq!(new_value.get_str("$formatVersion"), Ok("1"));
82    }
83
84    #[test]
85    fn concrete_v0_and_v1_to_value_select_format_by_explicit_platform_version() {
86        let old_platform_version = format_0_platform_version();
87
88        let DataContract::V0(v0) = get_data_contract_fixture(None, 0, FORMAT_0_PROTOCOL_VERSION)
89            .data_contract()
90            .clone()
91        else {
92            panic!("fixture at protocol version 8 should be a DataContractV0");
93        };
94        let DataContract::V1(v1) =
95            get_data_contract_fixture(None, 0, PlatformVersion::latest().protocol_version)
96                .data_contract()
97                .clone()
98        else {
99            panic!("fixture at latest should be a DataContractV1");
100        };
101
102        let v0_old = v0.to_value(old_platform_version).expect("v0 at format 0");
103        assert_eq!(v0_old.get_str("$formatVersion"), Ok("0"));
104        let v0_new = v0
105            .to_value(PlatformVersion::latest())
106            .expect("v0 at latest");
107        assert_eq!(v0_new.get_str("$formatVersion"), Ok("1"));
108
109        let v1_old = v1.to_value(old_platform_version).expect("v1 at format 0");
110        assert_eq!(v1_old.get_str("$formatVersion"), Ok("0"));
111        let v1_new = v1
112            .to_value(PlatformVersion::latest())
113            .expect("v1 at latest");
114        assert_eq!(v1_new.get_str("$formatVersion"), Ok("1"));
115    }
116
117    #[test]
118    fn to_value_round_trips_through_from_value_at_the_same_version() {
119        for platform_version in [format_0_platform_version(), PlatformVersion::latest()] {
120            let original = get_data_contract_fixture(None, 0, platform_version.protocol_version)
121                .data_contract()
122                .clone();
123
124            let value = original.to_value(platform_version).expect("to_value");
125            let recovered = DataContract::from_value(value, true, platform_version)
126                .expect("from_value at the same version");
127
128            assert_eq!(original.id(), recovered.id());
129            assert_eq!(original.owner_id(), recovered.owner_id());
130            assert_eq!(original.version(), recovered.version());
131        }
132    }
133}