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