Skip to main content

snarkvm_circuit_account/compute_key/helpers/
from_bits.rs

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