ternary.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> Ternary for Group<E> { 19 type Boolean = Boolean<E>; 20 type Output = Group<E>; 21 22 /// Returns `first` if `condition` is `true`, otherwise returns `second`. 23 fn ternary(condition: &Self::Boolean, first: &Self, second: &Self) -> Self::Output { 24 let x = Ternary::ternary(condition, &first.x, &second.x); 25 let y = Ternary::ternary(condition, &first.y, &second.y); 26 Group { x, y } 27 } 28 } 29 30 impl<E: Environment> Metrics<dyn Ternary<Boolean = Boolean<E>, Output = Group<E>>> for Group<E> { 31 type Case = (Mode, Mode, Mode); 32 33 fn count(case: &Self::Case) -> Count { 34 match case { 35 (Mode::Constant, _, _) 36 | (Mode::Public, Mode::Constant, Mode::Constant) 37 | (Mode::Private, Mode::Constant, Mode::Constant) => Count::is(0, 0, 0, 0), 38 _ => Count::is(0, 0, 2, 2), 39 } 40 } 41 } 42 43 impl<E: Environment> OutputMode<dyn Ternary<Boolean = Boolean<E>, Output = Self>> for Group<E> { 44 type Case = (CircuitType<Boolean<E>>, Mode, Mode); 45 46 fn output_mode(parameter: &Self::Case) -> Mode { 47 match parameter.0.mode().is_constant() { 48 true => match ¶meter.0 { 49 CircuitType::Constant(constant) => match constant.eject_value() { 50 true => parameter.1, 51 false => parameter.2, 52 }, 53 _ => E::halt("The constant condition is required to determine output mode."), 54 }, 55 false => Mode::Private, 56 } 57 } 58 } 59 60 #[cfg(test)] 61 mod tests { 62 use super::*; 63 use alphavm_circuit_environment::Circuit; 64 65 fn check_ternary( 66 name: &str, 67 expected: console::Group<<Circuit as Environment>::Network>, 68 condition: Boolean<Circuit>, 69 a: Group<Circuit>, 70 b: Group<Circuit>, 71 ) { 72 Circuit::scope(name, || { 73 let case = format!("({} ? {} : {})", condition.eject_value(), a.eject_value(), b.eject_value()); 74 let candidate = Group::ternary(&condition, &a, &b); 75 assert_eq!(expected, candidate.eject_value(), "{case}"); 76 assert_count!(Ternary(Boolean, Group, Group) => Group, &(condition.eject_mode(), a.eject_mode(), b.eject_mode())); 77 assert_output_mode!(Ternary(Boolean, Group, Group) => Group, &(CircuitType::from(&condition), a.eject_mode(), b.eject_mode()), candidate); 78 }); 79 } 80 81 #[test] 82 fn test_constant_condition() { 83 let mut rng = TestRng::default(); 84 85 let first = Uniform::rand(&mut rng); 86 let second = Uniform::rand(&mut rng); 87 88 // false ? Constant : Constant 89 let expected = second; 90 let condition = Boolean::<Circuit>::new(Mode::Constant, false); 91 let a = Group::<Circuit>::new(Mode::Constant, first); 92 let b = Group::<Circuit>::new(Mode::Constant, second); 93 check_ternary("false ? Constant : Constant", expected, condition, a, b); 94 95 // false ? Constant : Public 96 let expected = second; 97 let condition = Boolean::<Circuit>::new(Mode::Constant, false); 98 let a = Group::<Circuit>::new(Mode::Constant, first); 99 let b = Group::<Circuit>::new(Mode::Public, second); 100 check_ternary("false ? Constant : Public", expected, condition, a, b); 101 102 // false ? Public : Constant 103 let expected = second; 104 let condition = Boolean::<Circuit>::new(Mode::Constant, false); 105 let a = Group::<Circuit>::new(Mode::Public, first); 106 let b = Group::<Circuit>::new(Mode::Constant, second); 107 check_ternary("false ? Public : Constant", expected, condition, a, b); 108 109 // false ? Public : Public 110 let expected = second; 111 let condition = Boolean::<Circuit>::new(Mode::Constant, false); 112 let a = Group::<Circuit>::new(Mode::Public, first); 113 let b = Group::<Circuit>::new(Mode::Public, second); 114 check_ternary("false ? Public : Public", expected, condition, a, b); 115 116 // false ? Public : Private 117 let expected = second; 118 let condition = Boolean::<Circuit>::new(Mode::Constant, false); 119 let a = Group::<Circuit>::new(Mode::Public, first); 120 let b = Group::<Circuit>::new(Mode::Private, second); 121 check_ternary("false ? Public : Private", expected, condition, a, b); 122 123 // false ? Private : Private 124 let expected = second; 125 let condition = Boolean::<Circuit>::new(Mode::Constant, false); 126 let a = Group::<Circuit>::new(Mode::Private, first); 127 let b = Group::<Circuit>::new(Mode::Private, second); 128 check_ternary("false ? Private : Private", expected, condition, a, b); 129 130 // true ? Constant : Constant 131 let expected = first; 132 let condition = Boolean::<Circuit>::new(Mode::Constant, true); 133 let a = Group::<Circuit>::new(Mode::Constant, first); 134 let b = Group::<Circuit>::new(Mode::Constant, second); 135 check_ternary("true ? Constant : Constant", expected, condition, a, b); 136 137 // true ? Constant : Public 138 let expected = first; 139 let condition = Boolean::<Circuit>::new(Mode::Constant, true); 140 let a = Group::<Circuit>::new(Mode::Constant, first); 141 let b = Group::<Circuit>::new(Mode::Public, second); 142 check_ternary("true ? Constant : Public", expected, condition, a, b); 143 144 // true ? Public : Constant 145 let expected = first; 146 let condition = Boolean::<Circuit>::new(Mode::Constant, true); 147 let a = Group::<Circuit>::new(Mode::Public, first); 148 let b = Group::<Circuit>::new(Mode::Constant, second); 149 check_ternary("true ? Public : Constant", expected, condition, a, b); 150 151 // true ? Public : Public 152 let expected = first; 153 let condition = Boolean::<Circuit>::new(Mode::Constant, true); 154 let a = Group::<Circuit>::new(Mode::Public, first); 155 let b = Group::<Circuit>::new(Mode::Public, second); 156 check_ternary("true ? Public : Public", expected, condition, a, b); 157 158 // true ? Public : Private 159 let expected = first; 160 let condition = Boolean::<Circuit>::new(Mode::Constant, true); 161 let a = Group::<Circuit>::new(Mode::Public, first); 162 let b = Group::<Circuit>::new(Mode::Private, second); 163 check_ternary("true ? Public : Private", expected, condition, a, b); 164 165 // true ? Private : Private 166 let expected = first; 167 let condition = Boolean::<Circuit>::new(Mode::Constant, true); 168 let a = Group::<Circuit>::new(Mode::Private, first); 169 let b = Group::<Circuit>::new(Mode::Private, second); 170 check_ternary("true ? Private : Private", expected, condition, a, b); 171 } 172 173 #[test] 174 fn test_public_condition_and_constant_inputs() { 175 let mut rng = TestRng::default(); 176 177 let first = Uniform::rand(&mut rng); 178 let second = Uniform::rand(&mut rng); 179 180 // false ? Constant : Constant 181 let expected = second; 182 let condition = Boolean::<Circuit>::new(Mode::Public, false); 183 let a = Group::<Circuit>::new(Mode::Constant, first); 184 let b = Group::<Circuit>::new(Mode::Constant, second); 185 check_ternary("false ? Constant : Constant", expected, condition, a, b); 186 187 // true ? Constant : Constant 188 let expected = first; 189 let condition = Boolean::<Circuit>::new(Mode::Public, true); 190 let a = Group::<Circuit>::new(Mode::Constant, first); 191 let b = Group::<Circuit>::new(Mode::Constant, second); 192 check_ternary("true ? Constant : Constant", expected, condition, a, b); 193 } 194 195 #[test] 196 fn test_public_condition_and_mixed_inputs() { 197 let mut rng = TestRng::default(); 198 199 let first = Uniform::rand(&mut rng); 200 let second = Uniform::rand(&mut rng); 201 202 // false ? Constant : Public 203 let expected = second; 204 let condition = Boolean::<Circuit>::new(Mode::Public, false); 205 let a = Group::<Circuit>::new(Mode::Constant, first); 206 let b = Group::<Circuit>::new(Mode::Public, second); 207 check_ternary("false ? Constant : Public", expected, condition, a, b); 208 209 // false ? Public : Constant 210 let expected = second; 211 let condition = Boolean::<Circuit>::new(Mode::Public, false); 212 let a = Group::<Circuit>::new(Mode::Public, first); 213 let b = Group::<Circuit>::new(Mode::Constant, second); 214 check_ternary("false ? Public : Constant", expected, condition, a, b); 215 216 // true ? Constant : Public 217 let expected = first; 218 let condition = Boolean::<Circuit>::new(Mode::Public, true); 219 let a = Group::<Circuit>::new(Mode::Constant, first); 220 let b = Group::<Circuit>::new(Mode::Public, second); 221 check_ternary("true ? Constant : Public", expected, condition, a, b); 222 223 // true ? Public : Constant 224 let expected = first; 225 let condition = Boolean::<Circuit>::new(Mode::Public, true); 226 let a = Group::<Circuit>::new(Mode::Public, first); 227 let b = Group::<Circuit>::new(Mode::Constant, second); 228 check_ternary("true ? Public : Constant", expected, condition, a, b); 229 } 230 231 #[test] 232 fn test_private_condition_and_constant_inputs() { 233 let mut rng = TestRng::default(); 234 235 let first = Uniform::rand(&mut rng); 236 let second = Uniform::rand(&mut rng); 237 238 // false ? Constant : Constant 239 let expected = second; 240 let condition = Boolean::<Circuit>::new(Mode::Private, false); 241 let a = Group::<Circuit>::new(Mode::Constant, first); 242 let b = Group::<Circuit>::new(Mode::Constant, second); 243 check_ternary("false ? Constant : Constant", expected, condition, a, b); 244 245 // true ? Constant : Constant 246 let expected = first; 247 let condition = Boolean::<Circuit>::new(Mode::Private, true); 248 let a = Group::<Circuit>::new(Mode::Constant, first); 249 let b = Group::<Circuit>::new(Mode::Constant, second); 250 check_ternary("true ? Constant : Constant", expected, condition, a, b); 251 } 252 253 #[test] 254 fn test_private_condition_and_mixed_inputs() { 255 let mut rng = TestRng::default(); 256 257 let first = Uniform::rand(&mut rng); 258 let second = Uniform::rand(&mut rng); 259 260 // false ? Constant : Public 261 let expected = second; 262 let condition = Boolean::<Circuit>::new(Mode::Private, false); 263 let a = Group::<Circuit>::new(Mode::Constant, first); 264 let b = Group::<Circuit>::new(Mode::Public, second); 265 check_ternary("false ? Constant : Public", expected, condition, a, b); 266 267 // false ? Public : Constant 268 let expected = second; 269 let condition = Boolean::<Circuit>::new(Mode::Private, false); 270 let a = Group::<Circuit>::new(Mode::Public, first); 271 let b = Group::<Circuit>::new(Mode::Constant, second); 272 check_ternary("false ? Public : Constant", expected, condition, a, b); 273 274 // true ? Constant : Public 275 let expected = first; 276 let condition = Boolean::<Circuit>::new(Mode::Private, true); 277 let a = Group::<Circuit>::new(Mode::Constant, first); 278 let b = Group::<Circuit>::new(Mode::Public, second); 279 check_ternary("true ? Constant : Public", expected, condition, a, b); 280 281 // true ? Public : Constant 282 let expected = first; 283 let condition = Boolean::<Circuit>::new(Mode::Private, true); 284 let a = Group::<Circuit>::new(Mode::Public, first); 285 let b = Group::<Circuit>::new(Mode::Constant, second); 286 check_ternary("true ? Public : Constant", expected, condition, a, b); 287 } 288 289 #[test] 290 fn test_public_condition_and_variable_inputs() { 291 let mut rng = TestRng::default(); 292 293 let first = Uniform::rand(&mut rng); 294 let second = Uniform::rand(&mut rng); 295 296 // false ? Public : Public 297 let expected = second; 298 let condition = Boolean::<Circuit>::new(Mode::Public, false); 299 let a = Group::<Circuit>::new(Mode::Public, first); 300 let b = Group::<Circuit>::new(Mode::Public, second); 301 check_ternary("false ? Public : Public", expected, condition, a, b); 302 303 // false ? Public : Private 304 let expected = second; 305 let condition = Boolean::<Circuit>::new(Mode::Public, false); 306 let a = Group::<Circuit>::new(Mode::Public, first); 307 let b = Group::<Circuit>::new(Mode::Private, second); 308 check_ternary("false ? Public : Private", expected, condition, a, b); 309 310 // false ? Private : Public 311 let expected = second; 312 let condition = Boolean::<Circuit>::new(Mode::Public, false); 313 let a = Group::<Circuit>::new(Mode::Private, first); 314 let b = Group::<Circuit>::new(Mode::Public, second); 315 check_ternary("false ? Private : Public", expected, condition, a, b); 316 317 // false ? Private : Private 318 let expected = second; 319 let condition = Boolean::<Circuit>::new(Mode::Public, false); 320 let a = Group::<Circuit>::new(Mode::Private, first); 321 let b = Group::<Circuit>::new(Mode::Private, second); 322 check_ternary("false ? Private : Private", expected, condition, a, b); 323 324 // true ? Public : Public 325 let expected = first; 326 let condition = Boolean::<Circuit>::new(Mode::Public, true); 327 let a = Group::<Circuit>::new(Mode::Public, first); 328 let b = Group::<Circuit>::new(Mode::Public, second); 329 check_ternary("true ? Public : Public", expected, condition, a, b); 330 331 // true ? Public : Private 332 let expected = first; 333 let condition = Boolean::<Circuit>::new(Mode::Public, true); 334 let a = Group::<Circuit>::new(Mode::Public, first); 335 let b = Group::<Circuit>::new(Mode::Private, second); 336 check_ternary("true ? Public : Private", expected, condition, a, b); 337 338 // true ? Private : Public 339 let expected = first; 340 let condition = Boolean::<Circuit>::new(Mode::Public, true); 341 let a = Group::<Circuit>::new(Mode::Private, first); 342 let b = Group::<Circuit>::new(Mode::Public, second); 343 check_ternary("true ? Private : Public", expected, condition, a, b); 344 345 // true ? Private : Private 346 let expected = first; 347 let condition = Boolean::<Circuit>::new(Mode::Public, true); 348 let a = Group::<Circuit>::new(Mode::Private, first); 349 let b = Group::<Circuit>::new(Mode::Private, second); 350 check_ternary("true ? Private : Private", expected, condition, a, b); 351 } 352 353 #[test] 354 fn test_private_condition_and_variable_inputs() { 355 let mut rng = TestRng::default(); 356 357 let first = Uniform::rand(&mut rng); 358 let second = Uniform::rand(&mut rng); 359 360 // false ? Public : Public 361 let expected = second; 362 let condition = Boolean::<Circuit>::new(Mode::Private, false); 363 let a = Group::<Circuit>::new(Mode::Public, first); 364 let b = Group::<Circuit>::new(Mode::Public, second); 365 check_ternary("false ? Public : Public", expected, condition, a, b); 366 367 // false ? Public : Private 368 let expected = second; 369 let condition = Boolean::<Circuit>::new(Mode::Private, false); 370 let a = Group::<Circuit>::new(Mode::Public, first); 371 let b = Group::<Circuit>::new(Mode::Private, second); 372 check_ternary("false ? Public : Private", expected, condition, a, b); 373 374 // false ? Private : Public 375 let expected = second; 376 let condition = Boolean::<Circuit>::new(Mode::Private, false); 377 let a = Group::<Circuit>::new(Mode::Private, first); 378 let b = Group::<Circuit>::new(Mode::Public, second); 379 check_ternary("false ? Private : Public", expected, condition, a, b); 380 381 // false ? Private : Private 382 let expected = second; 383 let condition = Boolean::<Circuit>::new(Mode::Private, false); 384 let a = Group::<Circuit>::new(Mode::Private, first); 385 let b = Group::<Circuit>::new(Mode::Private, second); 386 check_ternary("false ? Private : Private", expected, condition, a, b); 387 388 // true ? Public : Public 389 let expected = first; 390 let condition = Boolean::<Circuit>::new(Mode::Private, true); 391 let a = Group::<Circuit>::new(Mode::Public, first); 392 let b = Group::<Circuit>::new(Mode::Public, second); 393 check_ternary("true ? Public : Public", expected, condition, a, b); 394 395 // true ? Public : Private 396 let expected = first; 397 let condition = Boolean::<Circuit>::new(Mode::Private, true); 398 let a = Group::<Circuit>::new(Mode::Public, first); 399 let b = Group::<Circuit>::new(Mode::Private, second); 400 check_ternary("true ? Public : Private", expected, condition, a, b); 401 402 // true ? Private : Public 403 let expected = first; 404 let condition = Boolean::<Circuit>::new(Mode::Private, true); 405 let a = Group::<Circuit>::new(Mode::Private, first); 406 let b = Group::<Circuit>::new(Mode::Public, second); 407 check_ternary("true ? Private : Public", expected, condition, a, b); 408 409 // true ? Private : Private 410 let expected = first; 411 let condition = Boolean::<Circuit>::new(Mode::Private, true); 412 let a = Group::<Circuit>::new(Mode::Private, first); 413 let b = Group::<Circuit>::new(Mode::Private, second); 414 check_ternary("true ? Private : Private", expected, condition, a, b); 415 } 416 }