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