snarkvm_ledger_block/transactions/confirmed/
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 ConfirmedTransaction<N> {
19    /// Reads the confirmed transaction from a buffer.
20    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21        let variant = u8::read_le(&mut reader)?;
22        match variant {
23            0 => {
24                // Read the index.
25                let index = u32::read_le(&mut reader)?;
26                // Read the transaction.
27                let transaction = Transaction::<N>::read_le(&mut reader)?;
28                // Read the number of finalize operations.
29                let num_finalize = NumFinalizeSize::read_le(&mut reader)?;
30                // Ensure the number of finalize operations is within bounds.
31                if num_finalize as usize > N::MAX_COMMANDS {
32                    return Err(error(format!(
33                        "ConfirmedTransaction (from 'read_le') has too many finalize operations ({} > {})",
34                        num_finalize,
35                        N::MAX_COMMANDS
36                    )));
37                }
38                // Read the finalize operations.
39                let finalize =
40                    (0..num_finalize).map(|_| FromBytes::read_le(&mut reader)).collect::<Result<Vec<_>, _>>()?;
41                // Return the confirmed transaction.
42                Self::accepted_deploy(index, transaction, finalize).map_err(error)
43            }
44            1 => {
45                // Read the index.
46                let index = u32::read_le(&mut reader)?;
47                // Read the transaction.
48                let transaction = Transaction::<N>::read_le(&mut reader)?;
49                // Read the number of finalize operations.
50                let num_finalize = NumFinalizeSize::read_le(&mut reader)?;
51                // Ensure the number of finalize operations is within bounds.
52                if num_finalize as usize > N::MAX_COMMANDS {
53                    return Err(error(format!(
54                        "ConfirmedTransaction (from 'read_le') has too many finalize operations ({} > {})",
55                        num_finalize,
56                        N::MAX_COMMANDS
57                    )));
58                }
59                // Read the finalize operations.
60                let finalize =
61                    (0..num_finalize).map(|_| FromBytes::read_le(&mut reader)).collect::<Result<Vec<_>, _>>()?;
62                // Return the confirmed transaction.
63                Self::accepted_execute(index, transaction, finalize).map_err(error)
64            }
65            2 => {
66                // Read the index.
67                let index = u32::read_le(&mut reader)?;
68                // Read the transaction.
69                let transaction = Transaction::<N>::read_le(&mut reader)?;
70                // Read the rejected deployment.
71                let rejected = Rejected::<N>::read_le(&mut reader)?;
72                // Read the number of finalize operations.
73                let num_finalize = NumFinalizeSize::read_le(&mut reader)?;
74                // Ensure the number of finalize operations is within bounds.
75                if num_finalize as usize > N::MAX_COMMANDS {
76                    return Err(error(format!(
77                        "ConfirmedTransaction (from 'read_le') has too many finalize operations ({} > {})",
78                        num_finalize,
79                        N::MAX_COMMANDS
80                    )));
81                }
82                // Read the finalize operations.
83                let finalize =
84                    (0..num_finalize).map(|_| FromBytes::read_le(&mut reader)).collect::<Result<Vec<_>, _>>()?;
85                // Return the confirmed transaction.
86                Self::rejected_deploy(index, transaction, rejected, finalize).map_err(error)
87            }
88            3 => {
89                // Read the index.
90                let index = u32::read_le(&mut reader)?;
91                // Read the transaction.
92                let transaction = Transaction::<N>::read_le(&mut reader)?;
93                // Read the rejected execution.
94                let rejected = Rejected::<N>::read_le(&mut reader)?;
95                // Read the number of finalize operations.
96                let num_finalize = NumFinalizeSize::read_le(&mut reader)?;
97                // Ensure the number of finalize operations is within bounds.
98                if num_finalize as usize > N::MAX_COMMANDS {
99                    return Err(error(format!(
100                        "ConfirmedTransaction (from 'read_le') has too many finalize operations ({} > {})",
101                        num_finalize,
102                        N::MAX_COMMANDS
103                    )));
104                }
105                // Read the finalize operations.
106                let finalize =
107                    (0..num_finalize).map(|_| FromBytes::read_le(&mut reader)).collect::<Result<Vec<_>, _>>()?;
108                // Return the confirmed transaction.
109                Self::rejected_execute(index, transaction, rejected, finalize).map_err(error)
110            }
111            4.. => Err(error(format!("Failed to decode confirmed transaction variant {variant}"))),
112        }
113    }
114}
115
116impl<N: Network> ToBytes for ConfirmedTransaction<N> {
117    /// Writes the confirmed transaction to a buffer.
118    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
119        match self {
120            Self::AcceptedDeploy(index, transaction, finalize) => {
121                // Write the variant.
122                0u8.write_le(&mut writer)?;
123                // Write the index.
124                index.write_le(&mut writer)?;
125                // Write the transaction.
126                transaction.write_le(&mut writer)?;
127                // Write the number of finalize operations.
128                NumFinalizeSize::try_from(finalize.len()).map_err(error)?.write_le(&mut writer)?;
129                // Write the finalize operations.
130                finalize.iter().try_for_each(|finalize| finalize.write_le(&mut writer))
131            }
132            Self::AcceptedExecute(index, transaction, finalize) => {
133                // Write the variant.
134                1u8.write_le(&mut writer)?;
135                // Write the index.
136                index.write_le(&mut writer)?;
137                // Write the transaction.
138                transaction.write_le(&mut writer)?;
139                // Write the number of finalize operations.
140                NumFinalizeSize::try_from(finalize.len()).map_err(error)?.write_le(&mut writer)?;
141                // Write the finalize operations.
142                finalize.iter().try_for_each(|finalize| finalize.write_le(&mut writer))
143            }
144            Self::RejectedDeploy(index, transaction, rejected, finalize) => {
145                // Write the variant.
146                2u8.write_le(&mut writer)?;
147                // Write the index.
148                index.write_le(&mut writer)?;
149                // Write the transaction.
150                transaction.write_le(&mut writer)?;
151                // Write the rejected deployment.
152                rejected.write_le(&mut writer)?;
153                // Write the number of finalize operations.
154                NumFinalizeSize::try_from(finalize.len()).map_err(error)?.write_le(&mut writer)?;
155                // Write the finalize operations.
156                finalize.iter().try_for_each(|finalize| finalize.write_le(&mut writer))
157            }
158            Self::RejectedExecute(index, transaction, rejected, finalize) => {
159                // Write the variant.
160                3u8.write_le(&mut writer)?;
161                // Write the index.
162                index.write_le(&mut writer)?;
163                // Write the transaction.
164                transaction.write_le(&mut writer)?;
165                // Write the rejected execution.
166                rejected.write_le(&mut writer)?;
167                // Write the number of finalize operations.
168                NumFinalizeSize::try_from(finalize.len()).map_err(error)?.write_le(&mut writer)?;
169                // Write the finalize operations.
170                finalize.iter().try_for_each(|finalize| finalize.write_le(&mut writer))
171            }
172        }
173    }
174}
175
176#[cfg(test)]
177mod tests {
178    use super::*;
179
180    #[test]
181    fn test_bytes() {
182        for expected in crate::transactions::confirmed::test_helpers::sample_confirmed_transactions() {
183            // Check the byte representation.
184            let expected_bytes = expected.to_bytes_le().unwrap();
185            assert_eq!(expected, ConfirmedTransaction::read_le(&expected_bytes[..]).unwrap());
186        }
187    }
188}