Skip to main content

snarkvm_ledger_block/transaction/deployment/
serialize.rs

1// Copyright (c) 2019-2026 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18impl<N: Network> Serialize for Deployment<N> {
19    /// Serializes the deployment into string or bytes.
20    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
21        match serializer.is_human_readable() {
22            true => {
23                // Note: `Deployment::version` checks optional fields to determine the version.
24                // V1: edition, program, verifying_keys (3 fields)
25                // V2: + program_checksum, program_owner (5 fields)
26                // V3: + program_checksum (4 fields, no owner)
27                let len = match self.version().map_err(ser::Error::custom)? {
28                    DeploymentVersion::V1 => 3,
29                    DeploymentVersion::V2 => 5,
30                    DeploymentVersion::V3 => 4,
31                };
32                let mut deployment = serializer.serialize_struct("Deployment", len)?;
33                deployment.serialize_field("edition", &self.edition)?;
34                deployment.serialize_field("program", &self.program)?;
35                deployment.serialize_field("verifying_keys", &self.verifying_keys)?;
36                if let Some(program_checksum) = &self.program_checksum {
37                    deployment.serialize_field("program_checksum", program_checksum)?;
38                }
39                if let Some(program_owner) = &self.program_owner {
40                    deployment.serialize_field("program_owner", program_owner)?;
41                }
42                deployment.end()
43            }
44            false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
45        }
46    }
47}
48
49impl<'de, N: Network> Deserialize<'de> for Deployment<N> {
50    /// Deserializes the deployment from a string or bytes.
51    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
52        match deserializer.is_human_readable() {
53            true => {
54                // Parse the deployment from a string into a value.
55                let mut deployment = serde_json::Value::deserialize(deserializer)?;
56
57                // Recover the deployment.
58                let deployment = Self::new(
59                    // Retrieve the edition.
60                    DeserializeExt::take_from_value::<D>(&mut deployment, "edition")?,
61                    // Retrieve the program.
62                    DeserializeExt::take_from_value::<D>(&mut deployment, "program")?,
63                    // Retrieve the verifying keys.
64                    DeserializeExt::take_from_value::<D>(&mut deployment, "verifying_keys")?,
65                    // Retrieve the program checksum, if it exists.
66                    serde_json::from_value(
67                        deployment.get_mut("program_checksum").unwrap_or(&mut serde_json::Value::Null).take(),
68                    )
69                    .map_err(de::Error::custom)?,
70                    // Retrieve the owner, if it exists.
71                    serde_json::from_value(
72                        deployment.get_mut("program_owner").unwrap_or(&mut serde_json::Value::Null).take(),
73                    )
74                    .map_err(de::Error::custom)?,
75                )
76                .map_err(de::Error::custom)?;
77
78                Ok(deployment)
79            }
80            false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "deployment"),
81        }
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_serde_json() -> Result<()> {
91        let rng = &mut TestRng::default();
92
93        // Sample the deployments.
94        for expected in [
95            test_helpers::sample_deployment_v1(Uniform::rand(rng), rng),
96            test_helpers::sample_deployment_v2_without_translation_keys(Uniform::rand(rng), rng),
97            test_helpers::sample_deployment_v2_with_translation_keys(Uniform::rand(rng), rng),
98            test_helpers::sample_deployment_v3(Uniform::rand(rng), rng),
99        ] {
100            // Serialize
101            let expected_string = &expected.to_string();
102            let candidate_string = serde_json::to_string(&expected)?;
103            assert_eq!(expected, serde_json::from_str(&candidate_string)?);
104
105            // Deserialize
106            assert_eq!(expected, Deployment::from_str(expected_string)?);
107            assert_eq!(expected, serde_json::from_str(&candidate_string)?);
108        }
109
110        Ok(())
111    }
112
113    #[test]
114    fn test_bincode() -> Result<()> {
115        let rng = &mut TestRng::default();
116
117        // Sample the deployments
118        for expected in [
119            test_helpers::sample_deployment_v1(Uniform::rand(rng), rng),
120            test_helpers::sample_deployment_v2_without_translation_keys(Uniform::rand(rng), rng),
121            test_helpers::sample_deployment_v2_with_translation_keys(Uniform::rand(rng), rng),
122            test_helpers::sample_deployment_v3(Uniform::rand(rng), rng),
123        ] {
124            // Serialize
125            let expected_bytes = expected.to_bytes_le()?;
126            let expected_bytes_with_size_encoding = bincode::serialize(&expected)?;
127            assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
128
129            // Deserialize
130            assert_eq!(expected, Deployment::read_le(&expected_bytes[..])?);
131            assert_eq!(expected, bincode::deserialize(&expected_bytes_with_size_encoding[..])?);
132        }
133
134        Ok(())
135    }
136}