snarkvm_console_program/data/record/to_bits.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> ToBits for Record<N, Plaintext<N>> {
19 /// Returns this data as a list of **little-endian** bits.
20 fn write_bits_le(&self, vec: &mut Vec<bool>) {
21 // Construct the owner visibility bit.
22 vec.push(self.owner.is_private());
23
24 // Construct the owner bits.
25 match &self.owner {
26 Owner::Public(public) => public.write_bits_le(vec),
27 Owner::Private(Plaintext::Literal(Literal::Address(address), ..)) => address.write_bits_le(vec),
28 _ => N::halt("Internal error: plaintext to_bits_le corrupted in record owner"),
29 };
30
31 // Compute the data bits.
32 let mut data_bits_le = vec![];
33 for (identifier, entry) in &self.data {
34 identifier.write_bits_le(&mut data_bits_le);
35 entry.write_bits_le(&mut data_bits_le);
36 }
37
38 // Ensure the data length is less than 2^31 bits.
39 if data_bits_le.len() >= (1 << 31) {
40 N::halt("Record data exceeds (1 << 31) bits")
41 }
42
43 // Write the first 31 bits of the data length (as we know it is less than 2^31).
44 // Note: In order to introduce a hiding bitflag, we repurpose the last bit as the hiding bit.
45 let data_bits_len = u32::try_from(data_bits_le.len()).or_halt_with::<N>("Record data exceeds u32::MAX bits");
46 vec.extend_from_slice(&data_bits_len.to_bits_le()[..31]);
47
48 // Construct the hiding bit.
49 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
50 vec.push(self.is_hiding());
51
52 // Construct the data bits.
53 vec.extend_from_slice(&data_bits_le);
54
55 // Construct the nonce bits.
56 self.nonce.write_bits_le(vec);
57
58 // Construct the version bits.
59 self.version.write_bits_le(vec);
60 }
61
62 /// Returns this data as a list of **big-endian** bits.
63 fn write_bits_be(&self, vec: &mut Vec<bool>) {
64 // Construct the owner visibility bit.
65 vec.push(self.owner.is_private());
66
67 // Construct the owner bits.
68 match &self.owner {
69 Owner::Public(public) => public.write_bits_be(vec),
70 Owner::Private(Plaintext::Literal(Literal::Address(address), ..)) => address.write_bits_be(vec),
71 _ => N::halt("Internal error: plaintext to_bits_be corrupted in record owner"),
72 };
73
74 // Compute the data bits.
75 let mut data_bits_be = vec![];
76 for (identifier, entry) in &self.data {
77 identifier.write_bits_be(&mut data_bits_be);
78 entry.write_bits_be(&mut data_bits_be);
79 }
80
81 // Ensure the data length is less than 2^31 bits.
82 if data_bits_be.len() >= (1 << 31) {
83 N::halt("Record data exceeds (1 << 31) bits")
84 }
85
86 // Construct the hiding bit.
87 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
88 vec.push(self.is_hiding());
89
90 // Write the last 31 bits of the data length (as we know it is less than 2^31).
91 // Note: In order to introduce a hiding bitflag, we repurpose the first bit as the hiding bit.
92 let data_bits_len = u32::try_from(data_bits_be.len()).or_halt_with::<N>("Record data exceeds u32::MAX bits");
93 vec.extend_from_slice(&data_bits_len.to_bits_be()[1..]);
94
95 // Construct the data bits.
96 vec.extend_from_slice(&data_bits_be);
97
98 // Construct the nonce bits.
99 self.nonce.write_bits_be(vec);
100
101 // Construct the version bits.
102 self.version.write_bits_be(vec);
103 }
104}
105
106impl<N: Network> ToBits for Record<N, Ciphertext<N>> {
107 /// Returns this data as a list of **little-endian** bits.
108 fn write_bits_le(&self, vec: &mut Vec<bool>) {
109 // Construct the owner visibility bit.
110 vec.push(self.owner.is_private());
111
112 // Construct the owner bits.
113 match &self.owner {
114 Owner::Public(public) => public.write_bits_le(vec),
115 Owner::Private(ciphertext) => {
116 // Ensure there is exactly one field element in the ciphertext.
117 match ciphertext.len() == 1 {
118 true => ciphertext[0].write_bits_le(vec),
119 false => N::halt("Internal error: ciphertext to_bits_le corrupted in record owner"),
120 }
121 }
122 };
123
124 // Compute the data bits.
125 let mut data_bits_le = vec![];
126 for (identifier, entry) in &self.data {
127 identifier.write_bits_le(&mut data_bits_le);
128 entry.write_bits_le(&mut data_bits_le);
129 }
130
131 // Ensure the data length is less than 2^31 bits.
132 if data_bits_le.len() >= (1 << 31) {
133 N::halt("Record data exceeds (1 << 31) bits")
134 }
135
136 // Write the first 31 bits of the data length (as we know it is less than 2^31).
137 // Note: In order to introduce a hiding bitflag, we repurpose the last bit as the hiding bit.
138 let data_bits_len = u32::try_from(data_bits_le.len()).or_halt_with::<N>("Record data exceeds u32::MAX bits");
139 vec.extend_from_slice(&data_bits_len.to_bits_le()[..31]);
140
141 // Construct the hiding bit.
142 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
143 vec.push(self.is_hiding());
144
145 // Construct the data bits.
146 vec.extend_from_slice(&data_bits_le);
147
148 // Construct the nonce bits.
149 self.nonce.write_bits_le(vec);
150
151 // Construct the version bits.
152 self.version.write_bits_le(vec);
153 }
154
155 /// Returns this data as a list of **big-endian** bits.
156 fn write_bits_be(&self, vec: &mut Vec<bool>) {
157 // Construct the owner visibility bit.
158 vec.push(self.owner.is_private());
159
160 // Construct the owner bits.
161 match &self.owner {
162 Owner::Public(public) => public.write_bits_be(vec),
163 Owner::Private(ciphertext) => {
164 // Ensure there is exactly one field element in the ciphertext.
165 match ciphertext.len() == 1 {
166 true => ciphertext[0].write_bits_be(vec),
167 false => N::halt("Internal error: ciphertext to_bits_be corrupted in record owner"),
168 }
169 }
170 };
171
172 // Compute the data bits.
173 let mut data_bits_be = vec![];
174 for (identifier, entry) in &self.data {
175 identifier.write_bits_be(&mut data_bits_be);
176 entry.write_bits_be(&mut data_bits_be);
177 }
178
179 // Ensure the data length is less than 2^31 bits.
180 if data_bits_be.len() >= (1 << 31) {
181 N::halt("Record data exceeds (1 << 31) bits")
182 }
183
184 // Construct the hiding bit.
185 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
186 vec.push(self.is_hiding());
187
188 // Write the last 31 bits of the data length (as we know it is less than 2^31).
189 // Note: In order to introduce a hiding bitflag, we repurpose the first bit as the hiding bit.
190 let data_bits_len = u32::try_from(data_bits_be.len()).or_halt_with::<N>("Record data exceeds u32::MAX bits");
191 vec.extend_from_slice(&data_bits_len.to_bits_be()[1..]);
192
193 // Construct the data bits.
194 vec.extend_from_slice(&data_bits_be);
195
196 // Construct the nonce bits.
197 self.nonce.write_bits_be(vec);
198
199 // Construct the version bits.
200 self.version.write_bits_be(vec);
201 }
202}