Skip to main content

snarkvm_ledger_block/transactions/rejected_reason/
bytes.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> FromBytes for RejectedReason<N> {
19    /// Reads the rejected reason from a buffer.
20    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21        // Read the variant.
22        let variant = u8::read_le(&mut reader)?;
23        match variant {
24            0 => {
25                let program_id = ProgramID::<N>::read_le(&mut reader)?;
26                Ok(Self::DuplicateProgramID(program_id))
27            }
28            1 => {
29                let program_id = ProgramID::<N>::read_le(&mut reader)?;
30                let edition = u16::read_le(&mut reader)?;
31                let resource = Identifier::<N>::read_le(&mut reader)?;
32                let index = u32::read_le(&mut reader)? as usize;
33                let command = Command::<N>::read_le(&mut reader)?;
34                Ok(Self::Finalize { program_id, edition, resource, index, command: Box::new(command) })
35            }
36            2 => {
37                // Read the optional program ID and edition.
38                let program_id = match u8::read_le(&mut reader)? {
39                    0 => None,
40                    1 => {
41                        let id = ProgramID::<N>::read_le(&mut reader)?;
42                        let edition = u16::read_le(&mut reader)?;
43                        Some((id, edition))
44                    }
45                    flag => return Err(error(format!("Invalid program_id presence flag {flag}"))),
46                };
47                // Read the optional resource.
48                let resource = match u8::read_le(&mut reader)? {
49                    0 => None,
50                    1 => Some(Identifier::<N>::read_le(&mut reader)?),
51                    flag => return Err(error(format!("Invalid resource presence flag {flag}"))),
52                };
53                Ok(Self::VM(program_id, resource))
54            }
55            3.. => Err(error(format!("Failed to decode rejected reason variant {variant}"))),
56        }
57    }
58}
59
60impl<N: Network> ToBytes for RejectedReason<N> {
61    /// Writes the rejected reason to a buffer.
62    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
63        match self {
64            Self::DuplicateProgramID(program_id) => {
65                0u8.write_le(&mut writer)?;
66                program_id.write_le(&mut writer)
67            }
68            Self::Finalize { program_id, edition, resource, index, command } => {
69                1u8.write_le(&mut writer)?;
70                program_id.write_le(&mut writer)?;
71                edition.write_le(&mut writer)?;
72                resource.write_le(&mut writer)?;
73                u32::try_from(*index).map_err(|_| error("Command index exceeds u32::MAX"))?.write_le(&mut writer)?;
74                command.write_le(&mut writer)
75            }
76            Self::VM(program_id, resource) => {
77                2u8.write_le(&mut writer)?;
78                // Write the optional program ID and edition.
79                match program_id {
80                    None => 0u8.write_le(&mut writer)?,
81                    Some((id, edition)) => {
82                        1u8.write_le(&mut writer)?;
83                        id.write_le(&mut writer)?;
84                        edition.write_le(&mut writer)?;
85                    }
86                }
87                // Write the optional resource.
88                match resource {
89                    None => 0u8.write_le(&mut writer),
90                    Some(resource) => {
91                        1u8.write_le(&mut writer)?;
92                        resource.write_le(&mut writer)
93                    }
94                }
95            }
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    type CurrentNetwork = console::network::MainnetV0;
105
106    #[test]
107    fn test_bytes() {
108        for expected in test_helpers::sample_rejected_reasons::<CurrentNetwork>() {
109            // Check the byte representation.
110            let expected_bytes = expected.to_bytes_le().unwrap();
111            assert_eq!(expected, RejectedReason::read_le(&expected_bytes[..]).unwrap());
112        }
113    }
114}