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