snarkvm_circuit_account/signature/helpers/
from_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> FromBits for Signature<A> {
20    type Boolean = Boolean<A>;
21
22    /// Initializes a new signature from a list of **little-endian** bits.
23    fn from_bits_le(bits_le: &[Self::Boolean]) -> Self {
24        let scalar_size_in_bits = console::Scalar::<A::Network>::size_in_bits();
25        let compute_key_size_in_bits = console::ComputeKey::<A::Network>::size_in_bits();
26
27        let (challenge_start, challenge_end) = (0, scalar_size_in_bits);
28        let (response_start, response_end) = (challenge_end, challenge_end + scalar_size_in_bits);
29        let (compute_key_start, compute_key_end) = (response_end, response_end + compute_key_size_in_bits);
30
31        let Some(challenge_bits) = bits_le.get(challenge_start..challenge_end) else {
32            A::halt("Unable to recover the signature challenge from (LE) bits")
33        };
34        let Some(response_bits) = bits_le.get(response_start..response_end) else {
35            A::halt("Unable to recover the signature response from (LE) bits")
36        };
37        let Some(compute_key_bits) = bits_le.get(compute_key_start..compute_key_end) else {
38            A::halt("Unable to recover the signature compute key from (LE) bits")
39        };
40
41        Self {
42            challenge: Scalar::from_bits_le(challenge_bits),
43            response: Scalar::from_bits_le(response_bits),
44            compute_key: ComputeKey::from_bits_le(compute_key_bits),
45        }
46    }
47
48    /// Initializes a new signature from a list of **big-endian** bits.
49    fn from_bits_be(bits_be: &[Self::Boolean]) -> Self {
50        let scalar_size_in_bits = console::Scalar::<A::Network>::size_in_bits();
51        let compute_key_size_in_bits = console::ComputeKey::<A::Network>::size_in_bits();
52
53        let (challenge_start, challenge_end) = (0, scalar_size_in_bits);
54        let (response_start, response_end) = (challenge_end, challenge_end + scalar_size_in_bits);
55        let (compute_key_start, compute_key_end) = (response_end, response_end + compute_key_size_in_bits);
56
57        let Some(challenge_bits) = bits_be.get(challenge_start..challenge_end) else {
58            A::halt("Unable to recover the signature challenge from (BE) bits")
59        };
60        let Some(response_bits) = bits_be.get(response_start..response_end) else {
61            A::halt("Unable to recover the signature response from (BE) bits")
62        };
63        let Some(compute_key_bits) = bits_be.get(compute_key_start..compute_key_end) else {
64            A::halt("Unable to recover the signature compute key from (BE) bits")
65        };
66
67        Self {
68            challenge: Scalar::from_bits_be(challenge_bits),
69            response: Scalar::from_bits_be(response_bits),
70            compute_key: ComputeKey::from_bits_be(compute_key_bits),
71        }
72    }
73}
74
75#[cfg(all(test, feature = "console"))]
76mod tests {
77    use super::*;
78    use crate::Circuit;
79    use snarkvm_circuit_network::AleoV0;
80    use snarkvm_utilities::TestRng;
81
82    type CurrentAleo = AleoV0;
83
84    const ITERATIONS: u64 = 100;
85
86    fn check_from_bits_le(mode: Mode, num_constants: u64, num_public: u64, num_private: u64, num_constraints: u64) {
87        let rng = &mut TestRng::default();
88
89        for i in 0..ITERATIONS {
90            // Sample a random signature.
91            let expected = crate::helpers::generate_signature(i, rng);
92            let candidate = Signature::<CurrentAleo>::new(mode, expected).to_bits_le();
93
94            CurrentAleo::scope(format!("{mode} {i}"), || {
95                let candidate = Signature::<CurrentAleo>::from_bits_le(&candidate);
96                assert_eq!(expected, candidate.eject_value());
97                assert_scope!(num_constants, num_public, num_private, num_constraints);
98            });
99            CurrentAleo::reset();
100        }
101    }
102
103    fn check_from_bits_be(mode: Mode, num_constants: u64, num_public: u64, num_private: u64, num_constraints: u64) {
104        let rng = &mut TestRng::default();
105
106        for i in 0..ITERATIONS {
107            // Sample a random signature.
108            let expected = crate::helpers::generate_signature(i, rng);
109            let candidate = Signature::<CurrentAleo>::new(mode, expected).to_bits_be();
110
111            CurrentAleo::scope(format!("{mode} {i}"), || {
112                let candidate = Signature::<CurrentAleo>::from_bits_be(&candidate);
113                assert_eq!(expected, candidate.eject_value());
114                assert_scope!(num_constants, num_public, num_private, num_constraints);
115            });
116            CurrentAleo::reset();
117        }
118    }
119
120    #[test]
121    fn test_from_bits_le_constant() {
122        check_from_bits_le(Mode::Constant, 272, 0, 0, 0);
123    }
124
125    #[test]
126    fn test_from_bits_le_public() {
127        check_from_bits_le(Mode::Public, 9, 0, 1875, 1881);
128    }
129
130    #[test]
131    fn test_from_bits_le_private() {
132        check_from_bits_le(Mode::Private, 9, 0, 1875, 1881);
133    }
134
135    #[test]
136    fn test_from_bits_be_constant() {
137        check_from_bits_be(Mode::Constant, 272, 0, 0, 0);
138    }
139
140    #[test]
141    fn test_from_bits_be_public() {
142        check_from_bits_be(Mode::Public, 9, 0, 1875, 1881);
143    }
144
145    #[test]
146    fn test_from_bits_be_private() {
147        check_from_bits_be(Mode::Private, 9, 0, 1875, 1881);
148    }
149}