snarkvm_circuit_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<A: Aleo> ToBits for Record<A, Plaintext<A>> {
19 type Boolean = Boolean<A>;
20
21 /// Returns this data as a list of **little-endian** bits.
22 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
23 // Construct the owner visibility bit.
24 vec.push(self.owner.is_private());
25
26 // Construct the owner bits.
27 match &self.owner {
28 Owner::Public(public) => public.write_bits_le(vec),
29 Owner::Private(Plaintext::Literal(Literal::Address(address), ..)) => address.write_bits_le(vec),
30 _ => A::halt("Internal error: plaintext to_bits_le corrupted in record owner"),
31 };
32
33 // Compute the data bits.
34 let mut data_bits_le = vec![];
35 for (identifier, entry) in &self.data {
36 identifier.write_bits_le(&mut data_bits_le);
37 entry.write_bits_le(&mut data_bits_le);
38 }
39 // Ensure the data length is less than 2^31 bits.
40 if data_bits_le.len() >= (1 << 31) {
41 A::halt("Record data exceeds (1 << 31) bits")
42 }
43
44 // Write the first 31 bits of the data length (as we know it is less than 2^31).
45 // Note: In order to introduce a hiding bitflag, we repurpose the last bit as the hiding bit.
46 vec.extend_from_slice(&U32::constant(console::U32::new(data_bits_le.len() as u32)).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<Self::Boolean>) {
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 _ => A::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 // Ensure the data length is less than 2^31 bits.
81 if data_bits_be.len() >= (1 << 31) {
82 A::halt("Record data exceeds (1 << 31) bits")
83 }
84
85 // Construct the hiding bit.
86 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
87 vec.push(self.is_hiding());
88
89 // Write the last 31 bits of the data length (as we know it is less than 2^31).
90 // Note: In order to introduce a hiding bitflag, we repurpose the first bit as the hiding bit.
91 vec.extend_from_slice(&U32::constant(console::U32::new(data_bits_be.len() as u32)).to_bits_be()[1..]);
92
93 // Construct the data bits.
94 vec.extend_from_slice(&data_bits_be);
95
96 // Construct the nonce bits.
97 self.nonce.write_bits_be(vec);
98
99 // Construct the version bits.
100 self.version.write_bits_be(vec);
101 }
102}
103
104impl<A: Aleo> ToBits for Record<A, Ciphertext<A>> {
105 type Boolean = Boolean<A>;
106
107 /// Returns this data as a list of **little-endian** bits.
108 fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
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 => A::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 // Ensure the data length is less than 2^31 bits.
131 if data_bits_le.len() >= (1 << 31) {
132 A::halt("Record data exceeds (1 << 31) bits")
133 }
134
135 // Write the first 31 bits of the data length (as we know it is less than 2^31).
136 // Note: In order to introduce a hiding bitflag, we repurpose the last bit as the hiding bit.
137 vec.extend_from_slice(&U32::constant(console::U32::new(data_bits_le.len() as u32)).to_bits_le()[..31]);
138
139 // Construct the hiding bit.
140 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
141 vec.push(self.is_hiding());
142
143 // Construct the data bits.
144 vec.extend_from_slice(&data_bits_le);
145
146 // Construct the nonce bits.
147 self.nonce.write_bits_le(vec);
148
149 // Construct the version bits.
150 self.version.write_bits_le(vec);
151 }
152
153 /// Returns this data as a list of **big-endian** bits.
154 fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
155 // Construct the owner visibility bit.
156 vec.push(self.owner.is_private());
157
158 // Construct the owner bits.
159 match &self.owner {
160 Owner::Public(public) => public.write_bits_be(vec),
161 Owner::Private(ciphertext) => {
162 // Ensure there is exactly one field element in the ciphertext.
163 match ciphertext.len() == 1 {
164 true => ciphertext[0].write_bits_be(vec),
165 false => A::halt("Internal error: ciphertext to_bits_be corrupted in record owner"),
166 }
167 }
168 };
169
170 // Compute the data bits.
171 let mut data_bits_be = vec![];
172 for (identifier, entry) in &self.data {
173 identifier.write_bits_be(&mut data_bits_be);
174 entry.write_bits_be(&mut data_bits_be);
175 }
176
177 // Ensure the data length is less than 2^31 bits.
178 if data_bits_be.len() >= (1 << 31) {
179 A::halt("Record data exceeds (1 << 31) bits")
180 }
181
182 // Construct the hiding bit.
183 // Note: While this bitflag is redundant, it is necessary for backwards compatibility.
184 vec.push(self.is_hiding());
185
186 // Write the last 31 bits of the data length (as we know it is less than 2^31).
187 // Note: In order to introduce a hiding bitflag, we repurpose the first bit as the hiding bit.
188 vec.extend_from_slice(&U32::constant(console::U32::new(data_bits_be.len() as u32)).to_bits_be()[1..]);
189
190 // Construct the data bits.
191 vec.extend_from_slice(&data_bits_be);
192
193 // Construct the nonce bits.
194 self.nonce.write_bits_be(vec);
195
196 // Construct the version bits.
197 self.version.write_bits_be(vec);
198 }
199}