snarkvm_ledger_block/transaction/execution/
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 Execution<N> {
19    /// Reads the execution 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 execution version"));
26        }
27        // Read the number of transitions.
28        let num_transitions = u8::read_le(&mut reader)?;
29        // Ensure the number of transitions is nonzero.
30        if num_transitions == 0 {
31            return Err(error("Execution (from 'read_le') has no transitions"));
32        }
33        // Ensure the number of transitions is within bounds.
34        if num_transitions as usize > Transaction::<N>::MAX_TRANSITIONS {
35            return Err(error(format!(
36                "Execution (from 'read_le') has too many transitions ({} > {})",
37                num_transitions,
38                Transaction::<N>::MAX_TRANSITIONS
39            )));
40        }
41        // Read the transitions.
42        let transitions =
43            (0..num_transitions).map(|_| Transition::read_le(&mut reader)).collect::<IoResult<Vec<_>>>()?;
44        // Read the global state root.
45        let global_state_root = N::StateRoot::read_le(&mut reader)?;
46        // Read the proof variant.
47        let proof_variant = u8::read_le(&mut reader)?;
48        // Read the proof.
49        let proof = match proof_variant {
50            0 => None,
51            1 => Some(Proof::read_le(&mut reader)?),
52            _ => return Err(error(format!("Invalid proof variant '{proof_variant}'"))),
53        };
54        // Return the new `Execution` instance.
55        Self::from(transitions.into_iter(), global_state_root, proof).map_err(|e| error(e.to_string()))
56    }
57}
58
59impl<N: Network> ToBytes for Execution<N> {
60    /// Writes the execution to a buffer.
61    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
62        // Write the version.
63        1u8.write_le(&mut writer)?;
64        // Write the number of transitions.
65        (u8::try_from(self.transitions.len()).map_err(|e| error(e.to_string()))?).write_le(&mut writer)?;
66        // Write the transitions.
67        for transition in self.transitions.values() {
68            transition.write_le(&mut writer)?;
69        }
70        // Write the global state root.
71        self.global_state_root.write_le(&mut writer)?;
72        // Write the proof.
73        match self.proof {
74            None => 0u8.write_le(&mut writer)?,
75            Some(ref proof) => {
76                1u8.write_le(&mut writer)?;
77                proof.write_le(&mut writer)?;
78            }
79        }
80        Ok(())
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn test_bytes() -> Result<()> {
90        let rng = &mut TestRng::default();
91
92        // Construct a new execution.
93        let expected = crate::transaction::execution::test_helpers::sample_execution(rng, 0);
94
95        // Check the byte representation.
96        let expected_bytes = expected.to_bytes_le()?;
97        assert_eq!(expected, Execution::read_le(&expected_bytes[..])?);
98        Ok(())
99    }
100}