snarkvm_ledger_block/transition/
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 Transition<N> {
19    /// Reads the output from a buffer.
20    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21        // Read the version.
22        let version = u8::read_le(&mut reader)?;
23        // Ensure the version is valid.
24        if version != 1 {
25            return Err(error("Invalid transition version"));
26        }
27
28        // Read the transition ID.
29        let transition_id = N::TransitionID::read_le(&mut reader)?;
30        // Read the program ID.
31        let program_id = FromBytes::read_le(&mut reader)?;
32        // Read the function name.
33        let function_name = FromBytes::read_le(&mut reader)?;
34
35        // Read the number of inputs.
36        let num_inputs: u8 = FromBytes::read_le(&mut reader)?;
37        // Ensure the number of inputs is within bounds.
38        if num_inputs as usize > N::MAX_INPUTS {
39            return Err(error(format!(
40                "Transition (from 'read_le') has too many inputs ({} > {})",
41                num_inputs,
42                N::MAX_INPUTS
43            )));
44        }
45        // Read the inputs.
46        let mut inputs = Vec::with_capacity(num_inputs as usize);
47        for _ in 0..num_inputs {
48            // Read the input.
49            inputs.push(FromBytes::read_le(&mut reader)?);
50        }
51
52        // Read the number of outputs.
53        let num_outputs: u8 = FromBytes::read_le(&mut reader)?;
54        // Ensure the number of outputs is within bounds.
55        if num_outputs as usize > N::MAX_OUTPUTS {
56            return Err(error(format!(
57                "Transition (from 'read_le') has too many outputs ({} > {})",
58                num_outputs,
59                N::MAX_OUTPUTS
60            )));
61        }
62        // Read the outputs.
63        let mut outputs = Vec::with_capacity(num_outputs as usize);
64        for _ in 0..num_outputs {
65            // Read the output.
66            outputs.push(FromBytes::read_le(&mut reader)?);
67        }
68
69        // Read the transition public key.
70        let tpk = FromBytes::read_le(&mut reader)?;
71        // Read the transition commitment.
72        let tcm = FromBytes::read_le(&mut reader)?;
73        // Read the signer commitment.
74        let scm = FromBytes::read_le(&mut reader)?;
75
76        // Construct the candidate transition.
77        let transition =
78            Self::new(program_id, function_name, inputs, outputs, tpk, tcm, scm).map_err(|e| error(e.to_string()))?;
79        // Ensure the transition ID matches the expected ID.
80        match transition_id == *transition.id() {
81            true => Ok(transition),
82            false => Err(error("Transition ID is incorrect, possible data corruption")),
83        }
84    }
85}
86
87impl<N: Network> ToBytes for Transition<N> {
88    /// Writes the literal to a buffer.
89    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
90        // Write the version.
91        1u8.write_le(&mut writer)?;
92
93        // Write the transition ID.
94        self.id.write_le(&mut writer)?;
95        // Write the program ID.
96        self.program_id.write_le(&mut writer)?;
97        // Write the function name.
98        self.function_name.write_le(&mut writer)?;
99
100        // Write the number of inputs.
101        (u8::try_from(self.inputs.len()).map_err(|e| error(e.to_string()))?).write_le(&mut writer)?;
102        // Write the inputs.
103        self.inputs.write_le(&mut writer)?;
104
105        // Write the number of outputs.
106        (u8::try_from(self.outputs.len()).map_err(|e| error(e.to_string()))?).write_le(&mut writer)?;
107        // Write the outputs.
108        self.outputs.write_le(&mut writer)?;
109
110        // Write the transition public key.
111        self.tpk.write_le(&mut writer)?;
112        // Write the transition commitment.
113        self.tcm.write_le(&mut writer)?;
114        // Write the signer commitment.
115        self.scm.write_le(&mut writer)
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_bytes() -> Result<()> {
125        let rng = &mut TestRng::default();
126
127        // Sample the transition.
128        let expected = crate::transition::test_helpers::sample_transition(rng);
129
130        // Check the byte representation.
131        let expected_bytes = expected.to_bytes_le()?;
132        assert_eq!(expected, Transition::read_le(&expected_bytes[..])?);
133
134        Ok(())
135    }
136}