nand.rs
1 // Copyright (c) 2025 ADnet Contributors 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> Nand<Self> for Boolean<E> { 19 type Output = Boolean<E>; 20 21 /// Returns `NOT (a AND b)`. 22 fn nand(&self, other: &Self) -> Self::Output { 23 // Constant `self` 24 if self.is_constant() { 25 match self.eject_value() { 26 true => !other.clone(), 27 false => !self.clone(), 28 } 29 } 30 // Constant `other` 31 else if other.is_constant() { 32 match other.eject_value() { 33 true => !self.clone(), 34 false => !other.clone(), 35 } 36 } 37 // Variable NAND Variable 38 else { 39 // Declare a new variable with the expected output as witness. 40 // Note: The constraint below will ensure `output` is either 0 or 1, 41 // assuming `self` and `other` are well-formed (they are either 0 or 1). 42 let output = Boolean( 43 E::new_variable( 44 Mode::Private, 45 match !(self.eject_value() & other.eject_value()) { 46 true => E::BaseField::one(), 47 false => E::BaseField::zero(), 48 }, 49 ) 50 .into(), 51 ); 52 53 // Ensure `self` * `other` = (1 - `output`) 54 // `output` is `1` iff `self` or `other` is `0`, otherwise `output` is `0`. 55 E::enforce(|| (self, other, E::one() - &output.0)); 56 57 output 58 } 59 } 60 } 61 62 #[cfg(test)] 63 mod tests { 64 use super::*; 65 use alphavm_circuit_environment::Circuit; 66 67 fn check_nand( 68 name: &str, 69 expected: bool, 70 a: Boolean<Circuit>, 71 b: Boolean<Circuit>, 72 num_constants: u64, 73 num_public: u64, 74 num_private: u64, 75 num_constraints: u64, 76 ) { 77 Circuit::scope(name, || { 78 let candidate = a.nand(&b); 79 assert_eq!(expected, candidate.eject_value(), "({} NAND {})", a.eject_value(), b.eject_value()); 80 assert_scope!(num_constants, num_public, num_private, num_constraints); 81 }); 82 } 83 84 #[test] 85 fn test_constant_nand_constant() { 86 // false NAND false 87 let expected = true; 88 let a = Boolean::<Circuit>::new(Mode::Constant, false); 89 let b = Boolean::<Circuit>::new(Mode::Constant, false); 90 check_nand("false NAND false", expected, a, b, 0, 0, 0, 0); 91 92 // false NAND true 93 let expected = true; 94 let a = Boolean::<Circuit>::new(Mode::Constant, false); 95 let b = Boolean::<Circuit>::new(Mode::Constant, true); 96 check_nand("false NAND true", expected, a, b, 0, 0, 0, 0); 97 98 // true NAND false 99 let expected = true; 100 let a = Boolean::<Circuit>::new(Mode::Constant, true); 101 let b = Boolean::<Circuit>::new(Mode::Constant, false); 102 check_nand("true NAND false", expected, a, b, 0, 0, 0, 0); 103 104 // true NAND true 105 let expected = false; 106 let a = Boolean::<Circuit>::new(Mode::Constant, true); 107 let b = Boolean::<Circuit>::new(Mode::Constant, true); 108 check_nand("true NAND true", expected, a, b, 0, 0, 0, 0); 109 } 110 111 #[test] 112 fn test_constant_nand_public() { 113 // false NAND false 114 let expected = true; 115 let a = Boolean::<Circuit>::new(Mode::Constant, false); 116 let b = Boolean::<Circuit>::new(Mode::Public, false); 117 check_nand("false NAND false", expected, a, b, 0, 0, 0, 0); 118 119 // false NAND true 120 let expected = true; 121 let a = Boolean::<Circuit>::new(Mode::Constant, false); 122 let b = Boolean::<Circuit>::new(Mode::Public, true); 123 check_nand("false NAND true", expected, a, b, 0, 0, 0, 0); 124 125 // true NAND false 126 let expected = true; 127 let a = Boolean::<Circuit>::new(Mode::Constant, true); 128 let b = Boolean::<Circuit>::new(Mode::Public, false); 129 check_nand("true NAND false", expected, a, b, 0, 0, 0, 0); 130 131 // true NAND true 132 let expected = false; 133 let a = Boolean::<Circuit>::new(Mode::Constant, true); 134 let b = Boolean::<Circuit>::new(Mode::Public, true); 135 check_nand("true NAND true", expected, a, b, 0, 0, 0, 0); 136 } 137 138 #[test] 139 fn test_constant_nand_private() { 140 // false NAND false 141 let expected = true; 142 let a = Boolean::<Circuit>::new(Mode::Constant, false); 143 let b = Boolean::<Circuit>::new(Mode::Private, false); 144 check_nand("false NAND false", expected, a, b, 0, 0, 0, 0); 145 146 // false NAND true 147 let expected = true; 148 let a = Boolean::<Circuit>::new(Mode::Constant, false); 149 let b = Boolean::<Circuit>::new(Mode::Private, true); 150 check_nand("false NAND true", expected, a, b, 0, 0, 0, 0); 151 152 // true NAND false 153 let expected = true; 154 let a = Boolean::<Circuit>::new(Mode::Constant, true); 155 let b = Boolean::<Circuit>::new(Mode::Private, false); 156 check_nand("true NAND false", expected, a, b, 0, 0, 0, 0); 157 158 // true NAND true 159 let expected = false; 160 let a = Boolean::<Circuit>::new(Mode::Constant, true); 161 let b = Boolean::<Circuit>::new(Mode::Private, true); 162 check_nand("true NAND true", expected, a, b, 0, 0, 0, 0); 163 } 164 165 #[test] 166 fn test_public_nand_constant() { 167 // false NAND false 168 let expected = true; 169 let a = Boolean::<Circuit>::new(Mode::Public, false); 170 let b = Boolean::<Circuit>::new(Mode::Constant, false); 171 check_nand("false NAND false", expected, a, b, 0, 0, 0, 0); 172 173 // false NAND true 174 let expected = true; 175 let a = Boolean::<Circuit>::new(Mode::Public, false); 176 let b = Boolean::<Circuit>::new(Mode::Constant, true); 177 check_nand("false NAND true", expected, a, b, 0, 0, 0, 0); 178 179 // true NAND false 180 let expected = true; 181 let a = Boolean::<Circuit>::new(Mode::Public, true); 182 let b = Boolean::<Circuit>::new(Mode::Constant, false); 183 check_nand("true NAND false", expected, a, b, 0, 0, 0, 0); 184 185 // true NAND true 186 let expected = false; 187 let a = Boolean::<Circuit>::new(Mode::Public, true); 188 let b = Boolean::<Circuit>::new(Mode::Constant, true); 189 check_nand("true NAND true", expected, a, b, 0, 0, 0, 0); 190 } 191 192 #[test] 193 fn test_public_nand_public() { 194 // false NAND false 195 let expected = true; 196 let a = Boolean::<Circuit>::new(Mode::Public, false); 197 let b = Boolean::<Circuit>::new(Mode::Public, false); 198 check_nand("false NAND false", expected, a, b, 0, 0, 1, 1); 199 200 // false NAND true 201 let expected = true; 202 let a = Boolean::<Circuit>::new(Mode::Public, false); 203 let b = Boolean::<Circuit>::new(Mode::Public, true); 204 check_nand("false NAND true", expected, a, b, 0, 0, 1, 1); 205 206 // true NAND false 207 let expected = true; 208 let a = Boolean::<Circuit>::new(Mode::Public, true); 209 let b = Boolean::<Circuit>::new(Mode::Public, false); 210 check_nand("true NAND false", expected, a, b, 0, 0, 1, 1); 211 212 // true NAND true 213 let expected = false; 214 let a = Boolean::<Circuit>::new(Mode::Public, true); 215 let b = Boolean::<Circuit>::new(Mode::Public, true); 216 check_nand("true NAND true", expected, a, b, 0, 0, 1, 1); 217 } 218 219 #[test] 220 fn test_public_nand_private() { 221 // false NAND false 222 let expected = true; 223 let a = Boolean::<Circuit>::new(Mode::Public, false); 224 let b = Boolean::<Circuit>::new(Mode::Private, false); 225 check_nand("false NAND false", expected, a, b, 0, 0, 1, 1); 226 227 // false NAND true 228 let expected = true; 229 let a = Boolean::<Circuit>::new(Mode::Public, false); 230 let b = Boolean::<Circuit>::new(Mode::Private, true); 231 check_nand("false NAND true", expected, a, b, 0, 0, 1, 1); 232 233 // true NAND false 234 let expected = true; 235 let a = Boolean::<Circuit>::new(Mode::Public, true); 236 let b = Boolean::<Circuit>::new(Mode::Private, false); 237 check_nand("true NAND false", expected, a, b, 0, 0, 1, 1); 238 239 // true NAND true 240 let expected = false; 241 let a = Boolean::<Circuit>::new(Mode::Public, true); 242 let b = Boolean::<Circuit>::new(Mode::Private, true); 243 check_nand("true NAND true", expected, a, b, 0, 0, 1, 1); 244 } 245 246 #[test] 247 fn test_private_nand_constant() { 248 // false NAND false 249 let expected = true; 250 let a = Boolean::<Circuit>::new(Mode::Private, false); 251 let b = Boolean::<Circuit>::new(Mode::Constant, false); 252 check_nand("false NAND false", expected, a, b, 0, 0, 0, 0); 253 254 // false NAND true 255 let expected = true; 256 let a = Boolean::<Circuit>::new(Mode::Private, false); 257 let b = Boolean::<Circuit>::new(Mode::Constant, true); 258 check_nand("false NAND true", expected, a, b, 0, 0, 0, 0); 259 260 // true NAND false 261 let expected = true; 262 let a = Boolean::<Circuit>::new(Mode::Private, true); 263 let b = Boolean::<Circuit>::new(Mode::Constant, false); 264 check_nand("true NAND false", expected, a, b, 0, 0, 0, 0); 265 266 // true NAND true 267 let expected = false; 268 let a = Boolean::<Circuit>::new(Mode::Private, true); 269 let b = Boolean::<Circuit>::new(Mode::Constant, true); 270 check_nand("true NAND true", expected, a, b, 0, 0, 0, 0); 271 } 272 273 #[test] 274 fn test_private_nand_public() { 275 // false NAND false 276 let expected = true; 277 let a = Boolean::<Circuit>::new(Mode::Private, false); 278 let b = Boolean::<Circuit>::new(Mode::Public, false); 279 check_nand("false NAND false", expected, a, b, 0, 0, 1, 1); 280 281 // false NAND true 282 let expected = true; 283 let a = Boolean::<Circuit>::new(Mode::Private, false); 284 let b = Boolean::<Circuit>::new(Mode::Public, true); 285 check_nand("false NAND true", expected, a, b, 0, 0, 1, 1); 286 287 // true NAND false 288 let expected = true; 289 let a = Boolean::<Circuit>::new(Mode::Private, true); 290 let b = Boolean::<Circuit>::new(Mode::Public, false); 291 check_nand("true NAND false", expected, a, b, 0, 0, 1, 1); 292 293 // true NAND true 294 let expected = false; 295 let a = Boolean::<Circuit>::new(Mode::Private, true); 296 let b = Boolean::<Circuit>::new(Mode::Public, true); 297 check_nand("true NAND true", expected, a, b, 0, 0, 1, 1); 298 } 299 300 #[test] 301 fn test_private_nand_private() { 302 // false NAND false 303 let expected = true; 304 let a = Boolean::<Circuit>::new(Mode::Private, false); 305 let b = Boolean::<Circuit>::new(Mode::Private, false); 306 check_nand("false NAND false", expected, a, b, 0, 0, 1, 1); 307 308 // false NAND true 309 let expected = true; 310 let a = Boolean::<Circuit>::new(Mode::Private, false); 311 let b = Boolean::<Circuit>::new(Mode::Private, true); 312 check_nand("false NAND true", expected, a, b, 0, 0, 1, 1); 313 314 // true NAND false 315 let expected = true; 316 let a = Boolean::<Circuit>::new(Mode::Private, true); 317 let b = Boolean::<Circuit>::new(Mode::Private, false); 318 check_nand("true NAND false", expected, a, b, 0, 0, 1, 1); 319 320 // true NAND true 321 let expected = false; 322 let a = Boolean::<Circuit>::new(Mode::Private, true); 323 let b = Boolean::<Circuit>::new(Mode::Private, true); 324 check_nand("true NAND true", expected, a, b, 0, 0, 1, 1); 325 } 326 }