equal.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the alphavm 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 16 use super::*; 17 18 impl<E: Environment> Equal<Self> for StringType<E> { 19 type Output = Boolean<E>; 20 21 /// Returns `true` if `self` and `other` are equal. 22 fn is_equal(&self, other: &Self) -> Self::Output { 23 // Convert each string type into fields. 24 let this = self.to_fields(); 25 let that = other.to_fields(); 26 27 // Check that the size in bytes of the two strings are equal. 28 self.size_in_bytes.is_equal(&other.size_in_bytes) 29 // Check that the string contents are equal. 30 & this.iter().zip(&that).fold(Boolean::constant(true), |acc, (a, b)| acc & a.is_equal(b)) 31 } 32 33 /// Returns `true` if `self` and `other` are *not* equal. 34 fn is_not_equal(&self, other: &Self) -> Self::Output { 35 !self.is_equal(other) 36 } 37 } 38 39 #[cfg(test)] 40 mod tests { 41 use super::*; 42 use alphavm_circuit_environment::Circuit; 43 44 fn sample_string(mode: Mode, rng: &mut TestRng) -> StringType<Circuit> { 45 // Sample a random string. Take 1/4th to ensure we fit for all code points. 46 let given = rng.next_string(Circuit::MAX_STRING_BYTES / 4, true); 47 StringType::<Circuit>::new(mode, console::StringType::new(&given)) 48 } 49 50 fn check_is_equal( 51 mode: Mode, 52 num_constants: u64, 53 num_public: u64, 54 num_private: u64, 55 num_constraints: u64, 56 ) -> Result<()> { 57 let mut rng = TestRng::default(); 58 59 // Sample two strings. 60 let string_a = sample_string(mode, &mut rng); 61 let string_b = sample_string(mode, &mut rng); 62 63 Circuit::scope(format!("{mode}"), || { 64 let candidate = string_a.is_equal(&string_a); 65 assert!(candidate.eject_value()); 66 assert_scope!(<=num_constants, <=num_public, <=num_private, <=num_constraints); 67 }); 68 69 Circuit::scope(format!("{mode}"), || { 70 let candidate = string_a.is_equal(&string_b); 71 assert!(!candidate.eject_value()); 72 assert_scope!(<=num_constants, <=num_public, <=num_private, <=num_constraints); 73 }); 74 75 Circuit::reset(); 76 Ok(()) 77 } 78 79 fn check_is_not_equal( 80 mode: Mode, 81 num_constants: u64, 82 num_public: u64, 83 num_private: u64, 84 num_constraints: u64, 85 ) -> Result<()> { 86 let mut rng = TestRng::default(); 87 88 // Sample two strings. 89 let string_a = sample_string(mode, &mut rng); 90 let string_b = sample_string(mode, &mut rng); 91 92 Circuit::scope(format!("{mode}"), || { 93 let candidate = string_a.is_not_equal(&string_b); 94 assert!(candidate.eject_value()); 95 assert_scope!(<=num_constants, <=num_public, <=num_private, <=num_constraints); 96 }); 97 98 Circuit::scope(format!("{mode}"), || { 99 let candidate = string_a.is_not_equal(&string_a); 100 assert!(!candidate.eject_value()); 101 assert_scope!(<=num_constants, <=num_public, <=num_private, <=num_constraints); 102 }); 103 104 Circuit::reset(); 105 Ok(()) 106 } 107 108 #[test] 109 fn test_is_equal_constant() -> Result<()> { 110 check_is_equal(Mode::Constant, 9, 0, 0, 0) 111 } 112 113 #[test] 114 fn test_is_equal_public() -> Result<()> { 115 check_is_equal(Mode::Public, 9, 0, 26, 26) 116 } 117 118 #[test] 119 fn test_is_equal_private() -> Result<()> { 120 check_is_equal(Mode::Private, 9, 0, 26, 26) 121 } 122 123 #[test] 124 fn test_is_not_equal_constant() -> Result<()> { 125 check_is_not_equal(Mode::Constant, 9, 0, 0, 0) 126 } 127 128 #[test] 129 fn test_is_not_equal_public() -> Result<()> { 130 check_is_not_equal(Mode::Public, 9, 0, 26, 26) 131 } 132 133 #[test] 134 fn test_is_not_equal_private() -> Result<()> { 135 check_is_not_equal(Mode::Private, 9, 0, 26, 36) 136 } 137 }