snarkvm_ledger_block/transition/input/
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 Input<N> {
19    /// Reads the input from a buffer.
20    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21        let variant = Variant::read_le(&mut reader)?;
22        let literal = match variant {
23            0 => {
24                let plaintext_hash: Field<N> = FromBytes::read_le(&mut reader)?;
25                let plaintext_exists: bool = FromBytes::read_le(&mut reader)?;
26                let plaintext = match plaintext_exists {
27                    true => Some(FromBytes::read_le(&mut reader)?),
28                    false => None,
29                };
30
31                Self::Constant(plaintext_hash, plaintext)
32            }
33            1 => {
34                let plaintext_hash: Field<N> = FromBytes::read_le(&mut reader)?;
35                let plaintext_exists: bool = FromBytes::read_le(&mut reader)?;
36                let plaintext = match plaintext_exists {
37                    true => Some(FromBytes::read_le(&mut reader)?),
38                    false => None,
39                };
40                Self::Public(plaintext_hash, plaintext)
41            }
42            2 => {
43                let ciphertext_hash: Field<N> = FromBytes::read_le(&mut reader)?;
44                let ciphertext_exists: bool = FromBytes::read_le(&mut reader)?;
45                let ciphertext = match ciphertext_exists {
46                    true => Some(FromBytes::read_le(&mut reader)?),
47                    false => None,
48                };
49                Self::Private(ciphertext_hash, ciphertext)
50            }
51            3 => {
52                // Read the serial number.
53                let serial_number: Field<N> = FromBytes::read_le(&mut reader)?;
54                // Read the tag.
55                let tag: Field<N> = FromBytes::read_le(&mut reader)?;
56                // Return the record.
57                Self::Record(serial_number, tag)
58            }
59            4 => Self::ExternalRecord(FromBytes::read_le(&mut reader)?),
60            5.. => return Err(error(format!("Failed to decode transition input variant {variant}"))),
61        };
62        Ok(literal)
63    }
64}
65
66impl<N: Network> ToBytes for Input<N> {
67    /// Writes the input to a buffer.
68    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
69        match self {
70            Self::Constant(plaintext_hash, plaintext) => {
71                (0 as Variant).write_le(&mut writer)?;
72                plaintext_hash.write_le(&mut writer)?;
73                match plaintext {
74                    Some(plaintext) => {
75                        true.write_le(&mut writer)?;
76                        plaintext.write_le(&mut writer)
77                    }
78                    None => false.write_le(&mut writer),
79                }
80            }
81            Self::Public(plaintext_hash, plaintext) => {
82                (1 as Variant).write_le(&mut writer)?;
83                plaintext_hash.write_le(&mut writer)?;
84                match plaintext {
85                    Some(plaintext) => {
86                        true.write_le(&mut writer)?;
87                        plaintext.write_le(&mut writer)
88                    }
89                    None => false.write_le(&mut writer),
90                }
91            }
92            Self::Private(ciphertext_hash, ciphertext) => {
93                (2 as Variant).write_le(&mut writer)?;
94                ciphertext_hash.write_le(&mut writer)?;
95                match ciphertext {
96                    Some(ciphertext) => {
97                        true.write_le(&mut writer)?;
98                        ciphertext.write_le(&mut writer)
99                    }
100                    None => false.write_le(&mut writer),
101                }
102            }
103            Self::Record(serial_number, tag) => {
104                (3 as Variant).write_le(&mut writer)?;
105                serial_number.write_le(&mut writer)?;
106                tag.write_le(&mut writer)
107            }
108            Self::ExternalRecord(input_commitment) => {
109                (4 as Variant).write_le(&mut writer)?;
110                input_commitment.write_le(&mut writer)
111            }
112        }
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119
120    #[test]
121    fn test_bytes() {
122        for (_, expected) in crate::transition::input::test_helpers::sample_inputs() {
123            // Check the byte representation.
124            let expected_bytes = expected.to_bytes_le().unwrap();
125            assert_eq!(expected, Input::read_le(&expected_bytes[..]).unwrap());
126        }
127    }
128}