Skip to main content

snarkvm_ledger_block/transition/input/
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 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 => Self::DynamicRecord(FromBytes::read_le(&mut reader)?),
61            6 => {
62                // Read the serial number.
63                let serial_number: Field<N> = FromBytes::read_le(&mut reader)?;
64                // Read the tag.
65                let tag: Field<N> = FromBytes::read_le(&mut reader)?;
66                // Read the dynamic ID.
67                let dynamic_id: Field<N> = FromBytes::read_le(&mut reader)?;
68                // Return the record with dynamic ID.
69                Self::RecordWithDynamicID(serial_number, tag, dynamic_id)
70            }
71            7 => {
72                // Read the external record hash.
73                let external_hash: Field<N> = FromBytes::read_le(&mut reader)?;
74                // Read the dynamic ID.
75                let dynamic_id: Field<N> = FromBytes::read_le(&mut reader)?;
76                // Return the external record with dynamic ID.
77                Self::ExternalRecordWithDynamicID(external_hash, dynamic_id)
78            }
79            8.. => return Err(error(format!("Failed to decode transition input variant {variant}"))),
80        };
81        Ok(literal)
82    }
83}
84
85impl<N: Network> ToBytes for Input<N> {
86    /// Writes the input to a buffer.
87    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
88        match self {
89            Self::Constant(plaintext_hash, plaintext) => {
90                (0 as Variant).write_le(&mut writer)?;
91                plaintext_hash.write_le(&mut writer)?;
92                match plaintext {
93                    Some(plaintext) => {
94                        true.write_le(&mut writer)?;
95                        plaintext.write_le(&mut writer)
96                    }
97                    None => false.write_le(&mut writer),
98                }
99            }
100            Self::Public(plaintext_hash, plaintext) => {
101                (1 as Variant).write_le(&mut writer)?;
102                plaintext_hash.write_le(&mut writer)?;
103                match plaintext {
104                    Some(plaintext) => {
105                        true.write_le(&mut writer)?;
106                        plaintext.write_le(&mut writer)
107                    }
108                    None => false.write_le(&mut writer),
109                }
110            }
111            Self::Private(ciphertext_hash, ciphertext) => {
112                (2 as Variant).write_le(&mut writer)?;
113                ciphertext_hash.write_le(&mut writer)?;
114                match ciphertext {
115                    Some(ciphertext) => {
116                        true.write_le(&mut writer)?;
117                        ciphertext.write_le(&mut writer)
118                    }
119                    None => false.write_le(&mut writer),
120                }
121            }
122            Self::Record(serial_number, tag) => {
123                (3 as Variant).write_le(&mut writer)?;
124                serial_number.write_le(&mut writer)?;
125                tag.write_le(&mut writer)
126            }
127            Self::ExternalRecord(input_commitment) => {
128                (4 as Variant).write_le(&mut writer)?;
129                input_commitment.write_le(&mut writer)
130            }
131            Self::DynamicRecord(hash) => {
132                (5 as Variant).write_le(&mut writer)?;
133                hash.write_le(&mut writer)
134            }
135            Self::RecordWithDynamicID(serial_number, tag, dynamic_id) => {
136                (6 as Variant).write_le(&mut writer)?;
137                serial_number.write_le(&mut writer)?;
138                tag.write_le(&mut writer)?;
139                dynamic_id.write_le(&mut writer)
140            }
141            Self::ExternalRecordWithDynamicID(external_hash, dynamic_id) => {
142                (7 as Variant).write_le(&mut writer)?;
143                external_hash.write_le(&mut writer)?;
144                dynamic_id.write_le(&mut writer)
145            }
146        }
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153
154    #[test]
155    fn test_bytes() {
156        for (_, expected) in crate::transition::input::test_helpers::sample_inputs() {
157            // Check the byte representation.
158            let expected_bytes = expected.to_bytes_le().unwrap();
159            assert_eq!(expected, Input::read_le(&expected_bytes[..]).unwrap());
160        }
161    }
162}