Skip to main content

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