snarkvm_circuit_account/compute_key/
mod.rs

1// Copyright 2024 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
16mod equal;
17mod from;
18mod from_private_key;
19mod helpers;
20mod ternary;
21mod to_address;
22
23#[cfg(test)]
24use snarkvm_circuit_types::environment::{assert_count, assert_output_mode, assert_scope};
25
26use crate::PrivateKey;
27use snarkvm_circuit_network::Aleo;
28use snarkvm_circuit_types::{Address, Boolean, Field, Group, Scalar, environment::prelude::*};
29
30#[derive(Clone)]
31pub struct ComputeKey<A: Aleo> {
32    /// The signature public key `pk_sig` := G^sk_sig.
33    pk_sig: Group<A>,
34    /// The signature public randomizer `pr_sig` := G^r_sig.
35    pr_sig: Group<A>,
36    /// The PRF secret key `sk_prf` := RO(G^sk_sig || G^r_sig).
37    sk_prf: Scalar<A>,
38}
39
40#[cfg(feature = "console")]
41impl<A: Aleo> Inject for ComputeKey<A> {
42    type Primitive = console::ComputeKey<A::Network>;
43
44    /// Initializes an account compute key from the given mode and native compute key.
45    fn new(mode: Mode, compute_key: Self::Primitive) -> Self {
46        // Inject `pk_sig`.
47        let pk_sig = Group::new(mode, compute_key.pk_sig());
48        // Inject `pr_sig`.
49        let pr_sig = Group::new(mode, compute_key.pr_sig());
50        // Output the compute key.
51        Self::from((pk_sig, pr_sig))
52    }
53}
54
55impl<A: Aleo> ComputeKey<A> {
56    /// Returns the signature public key.
57    pub const fn pk_sig(&self) -> &Group<A> {
58        &self.pk_sig
59    }
60
61    /// Returns the signature public randomizer.
62    pub const fn pr_sig(&self) -> &Group<A> {
63        &self.pr_sig
64    }
65
66    /// Returns the PRF secret key.
67    pub const fn sk_prf(&self) -> &Scalar<A> {
68        &self.sk_prf
69    }
70}
71
72#[cfg(feature = "console")]
73impl<A: Aleo> Eject for ComputeKey<A> {
74    type Primitive = console::ComputeKey<A::Network>;
75
76    /// Ejects the mode of the compute key.
77    fn eject_mode(&self) -> Mode {
78        (&self.pk_sig, &self.pr_sig, &self.sk_prf).eject_mode()
79    }
80
81    /// Ejects the compute key.
82    fn eject_value(&self) -> Self::Primitive {
83        match Self::Primitive::try_from((&self.pk_sig, &self.pr_sig).eject_value()) {
84            Ok(compute_key) => compute_key,
85            Err(error) => A::halt(format!("Failed to eject the compute key: {error}")),
86        }
87    }
88}
89
90#[cfg(all(test, feature = "console"))]
91pub(crate) mod tests {
92    use super::*;
93    use crate::{Circuit, helpers::generate_account};
94
95    use anyhow::Result;
96
97    const ITERATIONS: u64 = 250;
98
99    fn check_new(
100        mode: Mode,
101        num_constants: u64,
102        num_public: u64,
103        num_private: u64,
104        num_constraints: u64,
105    ) -> Result<()> {
106        for i in 0..ITERATIONS {
107            // Generate a private key, compute key, view key, and address.
108            let (_private_key, compute_key, _view_key, _address) = generate_account()?;
109
110            Circuit::scope(format!("New {mode}"), || {
111                let candidate = ComputeKey::<Circuit>::new(mode, compute_key);
112                match mode.is_constant() {
113                    true => assert_eq!(Mode::Constant, candidate.eject_mode()),
114                    false => assert_eq!(Mode::Private, candidate.eject_mode()),
115                };
116                assert_eq!(compute_key, candidate.eject_value());
117                // TODO (howardwu): Resolve skipping the cost count checks for the burn-in round.
118                if i > 0 {
119                    assert_scope!(num_constants, num_public, num_private, num_constraints);
120                }
121            });
122            Circuit::reset();
123        }
124        Ok(())
125    }
126
127    #[test]
128    fn test_compute_key_new_constant() -> Result<()> {
129        check_new(Mode::Constant, 274, 0, 0, 0)
130    }
131
132    #[test]
133    fn test_compute_key_new_public() -> Result<()> {
134        check_new(Mode::Public, 9, 4, 869, 873)
135    }
136
137    #[test]
138    fn test_compute_key_new_private() -> Result<()> {
139        check_new(Mode::Private, 9, 0, 873, 873)
140    }
141}