snarkvm_circuit_account/compute_key/
equal.rs

1// Copyright (c) 2019-2025 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
18#[cfg(feature = "console")]
19impl<A: Aleo> Equal<Self> for ComputeKey<A> {
20    type Output = Boolean<A>;
21
22    ///
23    /// Returns `true` if `self` and `other` are equal.
24    ///
25    fn is_equal(&self, other: &Self) -> Self::Output {
26        // Determine if this operation is constant or variable.
27        match self.is_constant() && other.is_constant() {
28            true => Boolean::constant(self.eject_value() == other.eject_value()),
29            false => {
30                self.pk_sig.is_equal(other.pk_sig())
31                    & self.pr_sig.is_equal(other.pr_sig())
32                    & self.sk_prf.is_equal(other.sk_prf())
33            }
34        }
35    }
36
37    ///
38    /// Returns `true` if `self` and `other` are *not* equal.
39    ///
40    /// This method constructs a boolean that indicates if
41    /// `self` and `other ` are *not* equal to each other.
42    ///
43    fn is_not_equal(&self, other: &Self) -> Self::Output {
44        !self.is_equal(other)
45    }
46}
47
48impl<A: Aleo> Metrics<dyn Equal<ComputeKey<A>, Output = Boolean<A>>> for ComputeKey<A> {
49    type Case = (Mode, Mode);
50
51    fn count(case: &Self::Case) -> Count {
52        match case.0.is_constant() && case.1.is_constant() {
53            true => Count::is(0, 0, 0, 0),
54            false => Count::is(0, 0, 14, 19),
55        }
56    }
57}
58
59impl<A: Aleo> OutputMode<dyn Equal<ComputeKey<A>, Output = Boolean<A>>> for ComputeKey<A> {
60    type Case = (Mode, Mode);
61
62    fn output_mode(case: &Self::Case) -> Mode {
63        match case.0.is_constant() && case.1.is_constant() {
64            true => Mode::Constant,
65            false => Mode::Private,
66        }
67    }
68}
69
70#[cfg(all(test, feature = "console"))]
71mod tests {
72    use super::*;
73    use crate::Circuit;
74    use snarkvm_circuit_network::AleoV0;
75    use snarkvm_utilities::TestRng;
76
77    type CurrentAleo = AleoV0;
78
79    const ITERATIONS: u64 = 10;
80
81    fn check_is_equal(
82        mode_a: Mode,
83        mode_b: Mode,
84        num_constants: u64,
85        num_public: u64,
86        num_private: u64,
87        num_constraints: u64,
88        rng: &mut TestRng,
89    ) {
90        for i in 0..ITERATIONS {
91            // Sample two random compute keys.
92            let a = ComputeKey::<CurrentAleo>::new(
93                mode_a,
94                console::ComputeKey::try_from(console::PrivateKey::new(rng).unwrap()).unwrap(),
95            );
96            let b = ComputeKey::<CurrentAleo>::new(
97                mode_b,
98                console::ComputeKey::try_from(console::PrivateKey::new(rng).unwrap()).unwrap(),
99            );
100
101            CurrentAleo::scope(format!("{mode_a} {mode_a} {i}"), || {
102                let equals = a.is_equal(&a);
103                assert!(equals.eject_value());
104            });
105
106            CurrentAleo::scope(format!("{mode_a} {mode_b} {i}"), || {
107                let equals = a.is_equal(&b);
108                assert!(!equals.eject_value());
109                assert_scope!(num_constants, num_public, num_private, num_constraints);
110            });
111        }
112    }
113
114    fn check_is_not_equal(
115        mode_a: Mode,
116        mode_b: Mode,
117        num_constants: u64,
118        num_public: u64,
119        num_private: u64,
120        num_constraints: u64,
121        rng: &mut TestRng,
122    ) {
123        for i in 0..ITERATIONS {
124            // Sample two random compute keys.
125            let a = ComputeKey::<CurrentAleo>::new(
126                mode_a,
127                console::ComputeKey::try_from(console::PrivateKey::new(rng).unwrap()).unwrap(),
128            );
129            let b = ComputeKey::<CurrentAleo>::new(
130                mode_b,
131                console::ComputeKey::try_from(console::PrivateKey::new(rng).unwrap()).unwrap(),
132            );
133
134            CurrentAleo::scope(format!("{mode_a} {mode_a} {i}"), || {
135                let equals = a.is_not_equal(&a);
136                assert!(!equals.eject_value());
137            });
138
139            CurrentAleo::scope(format!("{mode_a} {mode_b} {i}"), || {
140                let equals = a.is_not_equal(&b);
141                assert!(equals.eject_value());
142                assert_scope!(num_constants, num_public, num_private, num_constraints);
143            });
144        }
145    }
146
147    #[test]
148    fn test_is_equal() {
149        let mut rng = TestRng::default();
150
151        check_is_equal(Mode::Constant, Mode::Constant, 0, 0, 0, 0, &mut rng);
152        check_is_equal(Mode::Constant, Mode::Public, 0, 0, 14, 14, &mut rng);
153        check_is_equal(Mode::Constant, Mode::Private, 0, 0, 14, 14, &mut rng);
154        check_is_equal(Mode::Public, Mode::Constant, 0, 0, 14, 14, &mut rng);
155        check_is_equal(Mode::Private, Mode::Constant, 0, 0, 14, 14, &mut rng);
156        check_is_equal(Mode::Public, Mode::Public, 0, 0, 14, 14, &mut rng);
157        check_is_equal(Mode::Public, Mode::Private, 0, 0, 14, 14, &mut rng);
158        check_is_equal(Mode::Private, Mode::Public, 0, 0, 14, 14, &mut rng);
159        check_is_equal(Mode::Private, Mode::Private, 0, 0, 14, 14, &mut rng);
160    }
161
162    #[test]
163    fn test_is_not_equal() {
164        let mut rng = TestRng::default();
165
166        check_is_not_equal(Mode::Constant, Mode::Constant, 0, 0, 0, 0, &mut rng);
167        check_is_not_equal(Mode::Constant, Mode::Public, 0, 0, 14, 14, &mut rng);
168        check_is_not_equal(Mode::Constant, Mode::Private, 0, 0, 14, 14, &mut rng);
169        check_is_not_equal(Mode::Public, Mode::Constant, 0, 0, 14, 14, &mut rng);
170        check_is_not_equal(Mode::Private, Mode::Constant, 0, 0, 14, 14, &mut rng);
171        check_is_not_equal(Mode::Public, Mode::Public, 0, 0, 14, 14, &mut rng);
172        check_is_not_equal(Mode::Public, Mode::Private, 0, 0, 14, 14, &mut rng);
173        check_is_not_equal(Mode::Private, Mode::Public, 0, 0, 14, 14, &mut rng);
174        check_is_not_equal(Mode::Private, Mode::Private, 0, 0, 14, 14, &mut rng);
175    }
176}