snarkvm_circuit_account/signature/helpers/
to_bits.rs

1// Copyright 2024-2025 Aleo Network Foundation
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
18#[cfg(feature = "console")]
19impl<A: Aleo> ToBits for Signature<A> {
20    type Boolean = Boolean<A>;
21
22    /// Outputs the little-endian bit representation of the signature *without* trailing zeros.
23    fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
24        (&self).write_bits_le(vec);
25    }
26
27    /// Outputs the big-endian bit representation of the signature *without* leading zeros.
28    fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
29        (&self).write_bits_be(vec);
30    }
31}
32
33#[cfg(feature = "console")]
34impl<A: Aleo> ToBits for &Signature<A> {
35    type Boolean = Boolean<A>;
36
37    /// Outputs the little-endian bit representation of the signature *without* trailing zeros.
38    fn write_bits_le(&self, vec: &mut Vec<Self::Boolean>) {
39        // Write the challenge bits.
40        self.challenge.write_bits_le(vec);
41        // Write the response bits.
42        self.response.write_bits_le(vec);
43        // Write the compute key bits.
44        self.compute_key.write_bits_le(vec);
45    }
46
47    /// Outputs the big-endian bit representation of the signature *without* leading zeros.
48    fn write_bits_be(&self, vec: &mut Vec<Self::Boolean>) {
49        // Write the challenge bits.
50        self.challenge.write_bits_be(vec);
51        // Write the response bits.
52        self.response.write_bits_be(vec);
53        // Write the compute key bits.
54        self.compute_key.write_bits_be(vec);
55    }
56}
57
58#[cfg(all(test, feature = "console"))]
59mod tests {
60    use super::*;
61    use crate::Circuit;
62    use snarkvm_circuit_network::AleoV0;
63    use snarkvm_utilities::TestRng;
64
65    type CurrentAleo = AleoV0;
66
67    const ITERATIONS: u64 = 100;
68
69    fn check_to_bits_le(mode: Mode, num_constants: u64, num_public: u64, num_private: u64, num_constraints: u64) {
70        let expected_number_of_bits = console::Signature::<<CurrentAleo as Environment>::Network>::size_in_bits();
71
72        let rng = &mut TestRng::default();
73
74        for i in 0..ITERATIONS {
75            // Sample a random signature.
76            let expected = crate::helpers::generate_signature(i, rng);
77            let candidate = Signature::<CurrentAleo>::new(mode, expected);
78
79            CurrentAleo::scope(format!("{mode} {i}"), || {
80                let candidate = candidate.to_bits_le();
81                assert_eq!(expected_number_of_bits, candidate.len());
82
83                // Construct the expected bits.
84                let mut expected_bits = Vec::new();
85                expected_bits.extend(expected.challenge().to_bits_le());
86                expected_bits.extend(expected.response().to_bits_le());
87                expected_bits.extend(expected.compute_key().to_bits_le());
88
89                for (expected_bit, candidate_bit) in expected_bits.iter().zip_eq(candidate.iter()) {
90                    assert_eq!(*expected_bit, candidate_bit.eject_value());
91                }
92                assert_scope!(num_constants, num_public, num_private, num_constraints);
93            });
94        }
95    }
96
97    fn check_to_bits_be(mode: Mode, num_constants: u64, num_public: u64, num_private: u64, num_constraints: u64) {
98        let expected_number_of_bits = console::Signature::<<CurrentAleo as Environment>::Network>::size_in_bits();
99
100        let rng = &mut TestRng::default();
101
102        for i in 0..ITERATIONS {
103            // Sample a random signature.
104            let expected = crate::helpers::generate_signature(i, rng);
105            let candidate = Signature::<CurrentAleo>::new(mode, expected);
106
107            CurrentAleo::scope(format!("{mode} {i}"), || {
108                let candidate = candidate.to_bits_be();
109                assert_eq!(expected_number_of_bits, candidate.len());
110
111                // Construct the expected bits.
112                let mut expected_bits = Vec::new();
113                expected_bits.extend(expected.challenge().to_bits_be());
114                expected_bits.extend(expected.response().to_bits_be());
115                expected_bits.extend(expected.compute_key().to_bits_be());
116
117                for (expected_bit, candidate_bit) in expected_bits.iter().zip_eq(candidate.iter()) {
118                    assert_eq!(*expected_bit, candidate_bit.eject_value());
119                }
120                assert_scope!(num_constants, num_public, num_private, num_constraints);
121            });
122        }
123    }
124
125    #[test]
126    fn test_to_bits_le_constant() {
127        check_to_bits_le(Mode::Constant, 1008, 0, 0, 0);
128    }
129
130    #[test]
131    fn test_to_bits_le_public() {
132        check_to_bits_le(Mode::Public, 0, 0, 2012, 2020);
133    }
134
135    #[test]
136    fn test_to_bits_le_private() {
137        check_to_bits_le(Mode::Private, 0, 0, 2012, 2020);
138    }
139
140    #[test]
141    fn test_to_bits_be_constant() {
142        check_to_bits_be(Mode::Constant, 1008, 0, 0, 0);
143    }
144
145    #[test]
146    fn test_to_bits_be_public() {
147        check_to_bits_be(Mode::Public, 0, 0, 2012, 2020);
148    }
149
150    #[test]
151    fn test_to_bits_be_private() {
152        check_to_bits_be(Mode::Private, 0, 0, 2012, 2020);
153    }
154}