| 406 | } |
| 407 | |
| 408 | fn evaluate( |
| 409 | mpc_graph: Graph, |
| 410 | input_status: Vec<IOStatus>, |
| 411 | input: TypedValue, |
| 412 | permutation: PermutationType, |
| 413 | output_parties: Vec<IOStatus>, |
| 414 | inverse_permutation: bool, |
| 415 | ) -> Result<()> { |
| 416 | let permutations = prepare_permutation(permutation, input_status[1].clone())?; |
| 417 | let output = random_evaluate( |
| 418 | mpc_graph.clone(), |
| 419 | vec![ |
| 420 | prepare_input(input.clone(), input_status[0].clone())?, |
| 421 | convert_to_value(permutations.clone())?, |
| 422 | ], |
| 423 | )?; |
| 424 | let t = input.t.clone(); |
| 425 | |
| 426 | let output = if !output_parties.is_empty() { |
| 427 | output.to_flattened_array_u128(t.clone()) |
| 428 | } else { |
| 429 | // check that mpc_output is a sharing of plain_output |
| 430 | assert!(output.check_type(tuple_type(vec![t.clone(); PARTIES]))?); |
| 431 | // check that output is a sharing of expected |
| 432 | output.access_vector(|v| match t.clone() { |
| 433 | Type::Array(_, _) => { |
| 434 | let mut res = vec![0; t.get_dimensions().into_iter().product::<u64>() as usize]; |
| 435 | for val in v { |
| 436 | let arr = val.to_flattened_array_u128(t.clone())?; |
| 437 | for i in 0..arr.len() { |
| 438 | res[i as usize] = u128::wrapping_add(res[i as usize], arr[i as usize]); |
| 439 | } |
| 440 | } |
| 441 | Ok(res) |
| 442 | } |
| 443 | _ => unreachable!(), |
| 444 | }) |
| 445 | }?; |
| 446 | let input = input.value.to_flattened_array_u128(t.clone())?; |
| 447 | let m = match t.get_scalar_type().get_modulus() { |
| 448 | Some(m) => m, |
| 449 | None => 2u128.pow(64), |
| 450 | }; |
| 451 | let (input, output) = ( |
| 452 | input.iter().map(|x| (x % m)).collect::<Vec<_>>(), |
| 453 | output.iter().map(|x| (x % m)).collect::<Vec<_>>(), |
| 454 | ); |
| 455 | assert_eq!(input.len(), output.len()); |
| 456 | let n = permutations[0].len(); |
| 457 | let perm = if permutations.len() == 1 { |
| 458 | permutations[0].clone() |
| 459 | } else { |
| 460 | let mut res: Vec<u64> = (0..n).map(|i| i as u64).collect(); |
| 461 | // p = p2(p1(p0)), but to compose we actually need to traverse backwards. |
| 462 | for p in permutations.iter().rev() { |
| 463 | for i in 0..n { |
| 464 | res[i] = p[res[i] as usize]; |
| 465 | } |