|
1 | 1 | use crate::{ |
2 | 2 | algebra::structure_traits::{ErrorCorrect, Ring}, |
3 | | - error::error_handler::{anyhow_error_and_log, log_error_wrapper}, |
| 3 | + error::error_handler::anyhow_error_and_log, |
4 | 4 | execution::{ |
5 | 5 | runtime::session::BaseSessionHandles, |
6 | 6 | sharing::{ |
7 | 7 | open::{RobustOpen, SecureRobustOpen}, |
8 | 8 | share::Share, |
9 | 9 | }, |
10 | 10 | }, |
| 11 | + thread_handles::spawn_compute_bound, |
11 | 12 | }; |
12 | | -use anyhow::Context; |
13 | 13 | use itertools::Itertools; |
14 | 14 | use serde::{Deserialize, Serialize}; |
15 | 15 | use tracing::instrument; |
@@ -74,57 +74,61 @@ pub async fn mult_list<Z: Ring + ErrorCorrect, Ses: BaseSessionHandles>( |
74 | 74 | triples.len() |
75 | 75 | ))); |
76 | 76 | } |
77 | | - let mut to_open = Vec::with_capacity(2 * amount); |
78 | | - // Compute the shares of epsilon and rho and merge them together into a single list |
79 | | - for ((cur_x, cur_y), cur_trip) in x_vec.iter().zip_eq(y_vec).zip_eq(&triples) { |
80 | | - if cur_x.owner() != cur_y.owner() |
81 | | - || cur_trip.a.owner() != cur_x.owner() |
82 | | - || cur_trip.b.owner() != cur_x.owner() |
83 | | - || cur_trip.c.owner() != cur_x.owner() |
84 | | - { |
85 | | - tracing::warn!("Trying to multiply with shares of different owners. This will always result in an incorrect share"); |
86 | | - } |
87 | | - let share_epsilon = cur_trip.a + *cur_x; |
88 | | - let share_rho = cur_trip.b + *cur_y; |
89 | | - to_open.push(share_epsilon); |
90 | | - to_open.push(share_rho); |
91 | | - } |
| 77 | + let x_vec_cloned = x_vec.to_owned(); |
| 78 | + let y_vec_cloned = y_vec.to_owned(); |
| 79 | + let (triples_a, (triples_b, triples_c)): (Vec<_>, (Vec<_>, Vec<_>)) = triples |
| 80 | + .into_iter() |
| 81 | + .map(|triple| (triple.a, (triple.b, triple.c))) |
| 82 | + .unzip(); |
| 83 | + |
| 84 | + let triples_a_cloned = triples_a.clone(); |
| 85 | + let to_open: Vec<Share<Z>> = spawn_compute_bound(move || { |
| 86 | + x_vec_cloned.into_iter().zip_eq( |
| 87 | + y_vec_cloned |
| 88 | + .into_iter() |
| 89 | + .zip(triples_a_cloned.into_iter().zip_eq(triples_b.into_iter())), |
| 90 | + ).fold(Vec::with_capacity(2*amount), |mut acc, (cur_x, (cur_y, (cur_a, cur_b)))| { |
| 91 | + if cur_x.owner() != cur_y.owner() |
| 92 | + || cur_a.owner() != cur_x.owner() |
| 93 | + || cur_b.owner() != cur_x.owner() |
| 94 | + { |
| 95 | + tracing::warn!("Trying to multiply with shares of different owners. This will always result in an incorrect share"); |
| 96 | + } |
| 97 | + let share_epsilon = cur_a + cur_x; |
| 98 | + let share_rho = cur_b + cur_y; |
| 99 | + acc.push(share_epsilon); |
| 100 | + acc.push(share_rho); |
| 101 | + acc |
| 102 | + }) |
| 103 | + }).await?; |
| 104 | + |
92 | 105 | //NOTE: That's a lot of memory manipulation, could execute the "linear equation loop" with epsilonrho directly |
93 | 106 | // Open and seperate the list of both epsilon and rho values into two lists of values |
94 | | - let mut epsilonrho = open_list(&to_open, session).await?; |
95 | | - let mut epsilon_vec = Vec::with_capacity(amount); |
96 | | - let mut rho_vec = Vec::with_capacity(amount); |
97 | | - // Indicator variable if the current element is an epsilson value (or rho value) |
98 | | - let mut epsilon_val = false; |
99 | | - // Go through the list from the back |
100 | | - while let Some(cur_val) = epsilonrho.pop() { |
101 | | - match epsilon_val { |
102 | | - true => epsilon_vec.push(cur_val), |
103 | | - false => rho_vec.push(cur_val), |
104 | | - } |
105 | | - // Flip the indicator |
106 | | - epsilon_val = !epsilon_val; |
| 107 | + let epsilonrho = open_list(&to_open, session).await?; |
| 108 | + |
| 109 | + if 2 * amount != epsilonrho.len() { |
| 110 | + return Err(anyhow_error_and_log(format!( |
| 111 | + "Inconsistent share lengths: epsilonrho_vec: {:?}. Expected {:?}", |
| 112 | + epsilonrho.len(), |
| 113 | + 2 * amount |
| 114 | + ))); |
107 | 115 | } |
108 | 116 | // Compute the linear equation of shares to get the result |
109 | | - let mut res = Vec::with_capacity(amount); |
110 | | - for i in 0..amount { |
111 | | - let y = *y_vec |
112 | | - .get(i) |
113 | | - .with_context(|| log_error_wrapper("Missing y value"))?; |
114 | | - // Observe that the list of epsilons and rhos have already been reversed above, because of the use of pop, |
115 | | - // so we get the elements in the original order by popping again here |
116 | | - let epsilon = epsilon_vec |
117 | | - .pop() |
118 | | - .with_context(|| log_error_wrapper("Missing epsilon value"))?; |
119 | | - let rho = rho_vec |
120 | | - .pop() |
121 | | - .with_context(|| log_error_wrapper("Missing rho value"))?; |
122 | | - let trip = triples |
123 | | - .get(i) |
124 | | - .with_context(|| log_error_wrapper("Missing triple"))?; |
125 | | - res.push(y * epsilon - trip.a * rho + trip.c); |
126 | | - } |
127 | | - Ok(res) |
| 117 | + let y_vec_cloned = y_vec.to_owned(); |
| 118 | + |
| 119 | + spawn_compute_bound(move || { |
| 120 | + let epsilon_rho_vec = epsilonrho.chunks(2); |
| 121 | + y_vec_cloned |
| 122 | + .into_iter() |
| 123 | + .zip_eq(epsilon_rho_vec.zip_eq(triples_a.into_iter().zip_eq(triples_c.into_iter()))) |
| 124 | + .map(|(curr_y, (curr_epsilonrho, (curr_a, curr_c)))| { |
| 125 | + //curr_epsilonrho is a pair of shares, so we need to extract them |
| 126 | + //first is epsilon then rho |
| 127 | + curr_y * curr_epsilonrho[0] - curr_a * curr_epsilonrho[1] + curr_c |
| 128 | + }) |
| 129 | + .collect() |
| 130 | + }) |
| 131 | + .await |
128 | 132 | } |
129 | 133 |
|
130 | 134 | /// Opens a single secret |
|
0 commit comments