snarkvm_ledger_block/transaction/deployment/bytes.rs
1// Copyright (c) 2019-2025 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> FromBytes for Deployment<N> {
19 /// Reads the deployment from a buffer.
20 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21 // Read the version and ensure the version is valid.
22 let version = match u8::read_le(&mut reader)? {
23 1 => DeploymentVersion::V1,
24 2 => DeploymentVersion::V2,
25 version => return Err(error(format!("Invalid deployment version: {version}"))),
26 };
27
28 // Read the edition.
29 let edition = u16::read_le(&mut reader)?;
30 // Read the program.
31 let program = Program::read_le(&mut reader)?;
32
33 // Read the number of entries in the bundle.
34 let num_entries = u16::read_le(&mut reader)?;
35 // Ensure the number of entries is within bounds.
36 if num_entries as usize > N::MAX_FUNCTIONS {
37 return Err(error(format!(
38 "Deployment (from 'read_le') has too many entries ({} > {})",
39 num_entries,
40 N::MAX_FUNCTIONS
41 )));
42 }
43 // Read the verifying keys.
44 let mut verifying_keys = Vec::with_capacity(num_entries as usize);
45 for _ in 0..num_entries {
46 // Read the identifier.
47 let identifier = Identifier::<N>::read_le(&mut reader)?;
48 // Read the verifying key.
49 let verifying_key = VerifyingKey::<N>::read_le(&mut reader)?;
50 // Read the certificate.
51 let certificate = Certificate::<N>::read_le(&mut reader)?;
52 // Add the entry.
53 verifying_keys.push((identifier, (verifying_key, certificate)));
54 }
55
56 // If the deployment version is 2, read the program checksum and verify it.
57 let program_checksum = match version {
58 DeploymentVersion::V1 => None,
59 DeploymentVersion::V2 => {
60 // Read the program checksum.
61 let bytes: [u8; 32] = FromBytes::read_le(&mut reader)?;
62 let checksum = bytes.map(U8::new);
63 // Verify the checksum.
64 if checksum != program.to_checksum() {
65 return Err(error(format!(
66 "Invalid checksum in the deployment: expected [{}], got [{}]",
67 program.to_checksum().iter().join(", "),
68 checksum.iter().join(", ")
69 )));
70 }
71 Some(checksum)
72 }
73 };
74 // If the deployment version is 2, read the program owner.
75 let program_owner = match version {
76 DeploymentVersion::V1 => None,
77 DeploymentVersion::V2 => {
78 // Read the program owner.
79 let owner = Address::<N>::read_le(&mut reader)?;
80 Some(owner)
81 }
82 };
83
84 // Return the deployment.
85 Self::new(edition, program, verifying_keys, program_checksum, program_owner)
86 .map_err(|err| error(format!("{err}")))
87 }
88}
89
90impl<N: Network> ToBytes for Deployment<N> {
91 /// Writes the deployment to a buffer.
92 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
93 // Determine the version.
94 // Note: This method checks that either both or neither of the program checksum and program owner are present.
95 let version = self.version().map_err(error)?;
96 // Write the version.
97 (version as u8).write_le(&mut writer)?;
98 // Write the edition.
99 self.edition.write_le(&mut writer)?;
100 // Write the program.
101 self.program.write_le(&mut writer)?;
102 // Write the number of entries in the bundle.
103 (u16::try_from(self.verifying_keys.len()).map_err(|e| error(e.to_string()))?).write_le(&mut writer)?;
104 // Write each entry.
105 for (function_name, (verifying_key, certificate)) in &self.verifying_keys {
106 // Write the function name.
107 function_name.write_le(&mut writer)?;
108 // Write the verifying key.
109 verifying_key.write_le(&mut writer)?;
110 // Write the certificate.
111 certificate.write_le(&mut writer)?;
112 }
113 // If the deployment version is 2, write the program checksum and program owner.
114 // Note: The unwraps are safe because `Deployment::version` only returns `V2` if both the checksum and owner is present.
115 if version == DeploymentVersion::V2 {
116 // Write the bytes of the checksum.
117 for byte in &self.program_checksum.unwrap() {
118 byte.write_le(&mut writer)?;
119 }
120 // Write the bytes of the owner.
121 self.program_owner.unwrap().write_le(&mut writer)?;
122 }
123 Ok(())
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn test_bytes() -> Result<()> {
133 let rng = &mut TestRng::default();
134
135 // Construct the deployments.
136 for expected in [
137 test_helpers::sample_deployment_v1(Uniform::rand(rng), rng),
138 test_helpers::sample_deployment_v2(Uniform::rand(rng), rng),
139 ] {
140 // Check the byte representation.
141 let expected_bytes = expected.to_bytes_le()?;
142 assert_eq!(expected, Deployment::read_le(&expected_bytes[..])?);
143 }
144
145 Ok(())
146 }
147}