diff --git a/ipa-core/src/ff/boolean_array.rs b/ipa-core/src/ff/boolean_array.rs index 8b421098b..1408660e4 100644 --- a/ipa-core/src/ff/boolean_array.rs +++ b/ipa-core/src/ff/boolean_array.rs @@ -215,8 +215,9 @@ macro_rules! impl_serializable_trait { }; ($name: ident, $bits: tt, $store: ty, infallible) => { - const _SAFEGUARD: () = assert!( - $bits % 8 == 0, + $crate::const_assert_eq!( + $bits % 8, + 0, "Infallible deserialization is defined for lengths that are multiples of 8 only" ); diff --git a/ipa-core/src/ff/curve_points.rs b/ipa-core/src/ff/curve_points.rs index c5789e420..597673c97 100644 --- a/ipa-core/src/ff/curve_points.rs +++ b/ipa-core/src/ff/curve_points.rs @@ -8,6 +8,7 @@ use typenum::U32; use crate::{ ff::{ec_prime_field::Fp25519, Serializable}, impl_shared_value_common, + protocol::ipa_prf::PRF_CHUNK, secret_sharing::{Block, SharedValue, StdArray, Vectorizable}, }; @@ -42,6 +43,10 @@ impl Vectorizable<1> for RP25519 { type Array = StdArray; } +impl Vectorizable for RP25519 { + type Array = StdArray; +} + #[derive(thiserror::Error, Debug)] #[error("{0:?} is not the canonical encoding of a Ristretto point.")] pub struct NonCanonicalEncoding(CompressedRistretto); diff --git a/ipa-core/src/ff/ec_prime_field.rs b/ipa-core/src/ff/ec_prime_field.rs index dad5ca0f4..29d7964e0 100644 --- a/ipa-core/src/ff/ec_prime_field.rs +++ b/ipa-core/src/ff/ec_prime_field.rs @@ -5,10 +5,16 @@ use generic_array::GenericArray; use typenum::{U2, U32}; use crate::{ - ff::{boolean_array::BA256, Field, Serializable}, + ff::{boolean_array::BA256, Expand, Field, Serializable}, impl_shared_value_common, - protocol::prss::FromRandom, - secret_sharing::{Block, FieldVectorizable, SharedValue, StdArray, Vectorizable}, + protocol::{ + ipa_prf::PRF_CHUNK, + prss::{FromPrss, FromRandom, PrssIndex, SharedRandomness}, + }, + secret_sharing::{ + replicated::{semi_honest::AdditiveShare, ReplicatedSecretSharing}, + Block, FieldVectorizable, SharedValue, StdArray, Vectorizable, + }, }; impl Block for Scalar { @@ -125,6 +131,20 @@ impl std::ops::MulAssign for Fp25519 { } } +impl Expand for AdditiveShare +where + Fp25519: Vectorizable, +{ + type Input = AdditiveShare; + + fn expand(v: &Self::Input) -> Self { + AdditiveShare::new_arr( + >::Array::expand(&v.left()), + >::Array::expand(&v.right()), + ) + } +} + impl From for Fp25519 { fn from(s: Scalar) -> Self { Fp25519(s) @@ -185,6 +205,14 @@ impl FieldVectorizable<1> for Fp25519 { type ArrayAlias = StdArray; } +impl Vectorizable for Fp25519 { + type Array = StdArray; +} + +impl FieldVectorizable for Fp25519 { + type ArrayAlias = StdArray; +} + impl Field for Fp25519 { const NAME: &'static str = "Fp25519"; @@ -203,6 +231,29 @@ impl FromRandom for Fp25519 { } } +macro_rules! impl_share_from_random { + ($width:expr) => { + impl FromPrss for AdditiveShare { + fn from_prss_with>( + prss: &P, + index: I, + _params: (), + ) -> AdditiveShare { + let (l_arr, r_arr) = StdArray::from_tuple_iter( + prss.generate_chunks_iter::<_, U2>(index) + .map(|(l_rand, r_rand)| { + (Fp25519::from_random(l_rand), Fp25519::from_random(r_rand)) + }) + .take($width), + ); + AdditiveShare::new_arr(l_arr, r_arr) + } + } + }; +} + +impl_share_from_random!(PRF_CHUNK); + #[cfg(all(test, unit_test))] mod test { use curve25519_dalek::scalar::Scalar; diff --git a/ipa-core/src/lib.rs b/ipa-core/src/lib.rs index 784313c85..984ba0f12 100644 --- a/ipa-core/src/lib.rs +++ b/ipa-core/src/lib.rs @@ -145,6 +145,26 @@ pub(crate) mod test_executor { } } +#[macro_export] +macro_rules! const_assert { + ($x:expr $(,)?) => { + const _: () = assert!($x, stringify!($x)); + }; + ($x:expr, $msg:expr $(,)?) => { + const _: () = assert!($x, $msg); + }; +} + +#[macro_export] +macro_rules! const_assert_eq { + ($x:expr, $y:expr $(,)?) => { + $crate::const_assert!($x == $y); + }; + ($x:expr, $y:expr, $msg:expr $(,)?) => { + $crate::const_assert!($x == $y, $msg); + }; +} + macro_rules! mutually_incompatible { ($feature1:literal,$feature2:literal) => { #[cfg(all(feature = $feature1, feature = $feature2))] diff --git a/ipa-core/src/protocol/basics/mod.rs b/ipa-core/src/protocol/basics/mod.rs index 7314af874..f7536d606 100644 --- a/ipa-core/src/protocol/basics/mod.rs +++ b/ipa-core/src/protocol/basics/mod.rs @@ -13,7 +13,7 @@ pub use check_zero::check_zero; pub use if_else::{if_else, select}; pub use mul::{BooleanArrayMul, MultiplyZeroPositions, SecureMul, ZeroPositions}; pub use reshare::Reshare; -pub use reveal::{reveal, Reveal}; +pub use reveal::{partial_reveal, reveal, Reveal}; pub use share_known_value::ShareKnownValue; pub use sum_of_product::SumOfProducts; diff --git a/ipa-core/src/protocol/basics/reveal.rs b/ipa-core/src/protocol/basics/reveal.rs index 4b9c21da5..42849ff6a 100644 --- a/ipa-core/src/protocol/basics/reveal.rs +++ b/ipa-core/src/protocol/basics/reveal.rs @@ -176,8 +176,9 @@ impl<'a, F: ExtendableField> Reveal, 1> for Mali } } -// Workaround for https://github.com/rust-lang/rust/issues/100013. Calling this wrapper function -// instead of `Reveal::reveal` seems to hide the `impl Future` GAT. +// Workaround for https://github.com/rust-lang/rust/issues/100013. Calling these wrapper functions +// instead of the trait methods seems to hide the `impl Future` GAT. + pub fn reveal<'fut, C, S>( ctx: C, record_id: RecordId, @@ -190,6 +191,19 @@ where S::reveal(v, ctx, record_id) } +pub fn partial_reveal<'fut, C, S, const N: usize>( + ctx: C, + record_id: RecordId, + excluded: Role, + v: &'fut S, +) -> impl Future, Error>> + Send + 'fut +where + C: Context + 'fut, + S: Reveal, +{ + S::partial_reveal(v, ctx, record_id, excluded) +} + #[cfg(all(test, unit_test))] mod tests { use std::iter::zip; diff --git a/ipa-core/src/protocol/context/prss.rs b/ipa-core/src/protocol/context/prss.rs index 5ff5d3cd2..cc1f7756c 100644 --- a/ipa-core/src/protocol/context/prss.rs +++ b/ipa-core/src/protocol/context/prss.rs @@ -1,6 +1,6 @@ //! Metric-aware PRSS decorators -use generic_array::{ArrayLength, GenericArray}; +use generic_array::ArrayLength; use rand_core::{Error, RngCore}; use crate::{ @@ -35,16 +35,38 @@ impl<'a> InstrumentedIndexedSharedRandomness<'a> { } impl SharedRandomness for InstrumentedIndexedSharedRandomness<'_> { - fn generate_arrays, N: ArrayLength>( + type ChunksIter<'a, Z: ArrayLength> = InstrumentedChunksIter< + 'a, + ::ChunksIter<'a, Z>, + > + where Self: 'a; + + fn generate_chunks_iter, Z: ArrayLength>( &self, index: I, - ) -> (GenericArray, GenericArray) { - let step = self.step.as_ref().to_string(); + ) -> Self::ChunksIter<'_, Z> { + InstrumentedChunksIter { + instrumented: self, + inner: self.inner.generate_chunks_iter(index), + } + } +} + +pub struct InstrumentedChunksIter<'a, I: Iterator> { + instrumented: &'a InstrumentedIndexedSharedRandomness<'a>, + inner: I, +} + +impl<'a, I: Iterator> Iterator for InstrumentedChunksIter<'a, I> { + type Item = ::Item; + + fn next(&mut self) -> Option { + let step = self.instrumented.step.as_ref().to_string(); // TODO: what we really want here is a gauge indicating the maximum index used to generate // PRSS. Gauge infrastructure is not supported yet, `Metrics` struct needs to be able to // handle gauges - metrics::increment_counter!(INDEXED_PRSS_GENERATED, STEP => step, ROLE => self.role.as_static_str()); - self.inner.generate_arrays(index) + metrics::increment_counter!(INDEXED_PRSS_GENERATED, STEP => step, ROLE => self.instrumented.role.as_static_str()); + self.inner.next() } } diff --git a/ipa-core/src/protocol/ipa_prf/boolean_ops/addition_sequential.rs b/ipa-core/src/protocol/ipa_prf/boolean_ops/addition_sequential.rs index dc27e6ef7..b4dc09bce 100644 --- a/ipa-core/src/protocol/ipa_prf/boolean_ops/addition_sequential.rs +++ b/ipa-core/src/protocol/ipa_prf/boolean_ops/addition_sequential.rs @@ -1,13 +1,18 @@ +use std::{borrow::Borrow, iter::repeat, ops::Not}; + #[cfg(all(test, unit_test))] use ipa_macros::Step; -#[cfg(all(test, unit_test))] -use crate::secret_sharing::{FieldSimd, FieldVectorizable}; use crate::{ error::Error, - ff::{ArrayAccess, CustomArray, Field}, + ff::{ArrayAccessRef, ArrayBuild, ArrayBuilder, Field}, protocol::{basics::SecureMul, context::Context, step::BitOpStep, RecordId}, - secret_sharing::{replicated::semi_honest::AdditiveShare, SharedValue}, + secret_sharing::{replicated::semi_honest::AdditiveShare, FieldSimd}, +}; +#[cfg(all(test, unit_test))] +use crate::{ + ff::CustomArray, + secret_sharing::{FieldVectorizable, SharedValue}, }; #[cfg(all(test, unit_test))] @@ -25,19 +30,20 @@ pub(crate) enum Step { /// /// # Errors /// propagates errors from multiply -pub async fn integer_add( +pub async fn integer_add( ctx: C, record_id: RecordId, - x: &AdditiveShare, - y: &AdditiveShare, -) -> Result<(AdditiveShare, AdditiveShare), Error> + x: &XS, + y: &YS, +) -> Result<(XS, AdditiveShare), Error> where C: Context, - YS: SharedValue + CustomArray, - XS: SharedValue + CustomArray, - XS::Element: Field, + F: Field + FieldSimd, + XS: ArrayAccessRef> + ArrayBuild>, + YS: ArrayAccessRef>, + AdditiveShare: SecureMul + Not>, { - let mut carry = AdditiveShare::::ZERO; + let mut carry = AdditiveShare::::ZERO; let sum = addition_circuit(ctx, record_id, x, y, &mut carry).await?; Ok((sum, carry)) } @@ -59,6 +65,7 @@ where C: Context, S: SharedValue + CustomArray, AdditiveShare: From> + Into>, + AdditiveShare: Not>, { use crate::{ff::Expand, protocol::basics::if_else}; let mut carry = AdditiveShare::::ZERO; @@ -95,35 +102,41 @@ where /// propagates errors from multiply /// /// -async fn addition_circuit( +async fn addition_circuit( ctx: C, record_id: RecordId, - x: &AdditiveShare, - y: &AdditiveShare, - carry: &mut AdditiveShare, -) -> Result, Error> + x: &XS, + y: &YS, + carry: &mut AdditiveShare, +) -> Result where C: Context, - XS: SharedValue + CustomArray, - YS: SharedValue + CustomArray, - XS::Element: Field, + F: Field + FieldSimd, + XS: ArrayAccessRef> + ArrayBuild>, + YS: ArrayAccessRef>, + AdditiveShare: SecureMul + Not>, { - let mut result = AdditiveShare::::ZERO; - for (i, v) in x.iter().enumerate() { - result.set( - i, + let x = x.iter(); + let y = y.iter(); + + let mut result = XS::builder().with_capacity(x.len()); + for (i, (xb, yb)) in x + .zip(y.chain(repeat(YS::make_ref(&AdditiveShare::::ZERO)))) + .enumerate() + { + result.push( bit_adder( ctx.narrow(&BitOpStep::from(i)), record_id, - &v, - y.get(i).as_ref(), + xb.borrow(), + yb.borrow(), carry, ) .await?, ); } - Ok(result) + Ok(result.build()) } /// @@ -145,26 +158,23 @@ where /// /// # Errors /// propagates errors from multiply -async fn bit_adder( +async fn bit_adder( ctx: C, record_id: RecordId, - x: &AdditiveShare, - y: Option<&AdditiveShare>, - carry: &mut AdditiveShare, -) -> Result, Error> + x: &AdditiveShare, + y: &AdditiveShare, + carry: &mut AdditiveShare, +) -> Result, Error> where C: Context, - S: Field, + F: Field + FieldSimd, + AdditiveShare: SecureMul + Not>, { - let output = x + y.unwrap_or(&AdditiveShare::::ZERO) + &*carry; + let output = x + y + &*carry; *carry = &*carry + (x + &*carry) - .multiply( - &(y.unwrap_or(&AdditiveShare::::ZERO) + &*carry), - ctx, - record_id, - ) + .multiply(&(y + &*carry), ctx, record_id) .await?; Ok(output) @@ -185,6 +195,7 @@ mod test { ipa_prf::boolean_ops::addition_sequential::{integer_add, integer_sat_add}, }, rand::thread_rng, + secret_sharing::replicated::semi_honest::AdditiveShare, test_executor::run, test_fixture::{Reconstruct, Runner, TestWorld}, }; @@ -207,7 +218,7 @@ mod test { let (result, carry) = world .semi_honest((x_ba64, y_ba64), |ctx, x_y| async move { - integer_add::<_, BA64, BA64>( + integer_add::<_, _, AdditiveShare, AdditiveShare, 1>( ctx.set_total_records(1), protocol::RecordId(0), &x_y.0, @@ -275,7 +286,7 @@ mod test { let (result, carry) = world .semi_honest((x_ba64, y_ba32), |ctx, x_y| async move { - integer_add::<_, BA64, BA32>( + integer_add::<_, _, AdditiveShare, AdditiveShare, 1>( ctx.set_total_records(1), protocol::RecordId(0), &x_y.0, @@ -296,7 +307,7 @@ mod test { let expected_carry = (x + y) >> 32 & 1; let (result, carry) = world .semi_honest((y_ba32, x_ba64), |ctx, x_y| async move { - integer_add::<_, BA32, BA64>( + integer_add::<_, _, AdditiveShare, AdditiveShare, 1>( ctx.set_total_records(1), protocol::RecordId(0), &x_y.0, diff --git a/ipa-core/src/protocol/ipa_prf/boolean_ops/comparison_and_subtraction_sequential.rs b/ipa-core/src/protocol/ipa_prf/boolean_ops/comparison_and_subtraction_sequential.rs index 21b86aed5..cee540964 100644 --- a/ipa-core/src/protocol/ipa_prf/boolean_ops/comparison_and_subtraction_sequential.rs +++ b/ipa-core/src/protocol/ipa_prf/boolean_ops/comparison_and_subtraction_sequential.rs @@ -238,7 +238,6 @@ mod test { use std::{ array, iter::{repeat, repeat_with, zip}, - time::Instant, }; use futures::stream::iter as stream_iter; @@ -419,9 +418,10 @@ mod test { let result = world .semi_honest((x.clone().into_iter(), y), |ctx, (x, y)| async move { - let begin = Instant::now(); + #[cfg(not(debug_assertions))] + let begin = std::time::Instant::now(); let ctx = ctx.set_total_records(x.len()); - let res = seq_join( + let res: Vec> = seq_join( ctx.active_work(), stream_iter(x.into_iter().zip(repeat((ctx, y))).enumerate().map( |(i, (x, (ctx, y)))| async move { @@ -429,9 +429,10 @@ mod test { }, )), ) - .try_collect::>>() + .try_collect() .await .unwrap(); + #[cfg(not(debug_assertions))] tracing::info!("Execution time: {:?}", begin.elapsed()); res }) @@ -494,10 +495,10 @@ mod test { let xa_iter = xa.clone().into_iter(); let result = world .semi_honest((xa_iter, ya.clone()), |ctx, (x, y)| async move { - println!("Processing {} records", x.len()); - let begin = Instant::now(); + #[cfg(not(debug_assertions))] + let begin = std::time::Instant::now(); let ctx = ctx.set_total_records(x.len()); - let res = seq_join( + let res: Vec> = seq_join( ctx.active_work(), stream_iter(x.into_iter().zip(repeat((ctx, y))).enumerate().map( |(i, (x, (ctx, y)))| async move { @@ -505,9 +506,10 @@ mod test { }, )), ) - .try_collect::>>() + .try_collect() .await .unwrap(); + #[cfg(not(debug_assertions))] tracing::info!("Execution time: {:?}", begin.elapsed()); res }) diff --git a/ipa-core/src/protocol/ipa_prf/boolean_ops/share_conversion_aby.rs b/ipa-core/src/protocol/ipa_prf/boolean_ops/share_conversion_aby.rs index 8f8ae7ee2..b75660d4d 100644 --- a/ipa-core/src/protocol/ipa_prf/boolean_ops/share_conversion_aby.rs +++ b/ipa-core/src/protocol/ipa_prf/boolean_ops/share_conversion_aby.rs @@ -1,21 +1,28 @@ -use std::ops::Neg; +use std::{ + borrow::Borrow, + convert::Infallible, + ops::{Neg, Not}, +}; use ipa_macros::Step; use crate::{ - error::Error, + error::{Error, UnwrapInfallible}, ff::{ - boolean::Boolean, boolean_array::BA256, ec_prime_field::Fp25519, ArrayAccess, CustomArray, - Expand, + boolean::Boolean, boolean_array::BA256, ec_prime_field::Fp25519, ArrayAccess, + ArrayAccessRef, ArrayBuild, ArrayBuilder, CustomArray, Expand, }, helpers::Role, protocol::{ - basics::Reveal, context::Context, ipa_prf::boolean_ops::addition_sequential::integer_add, - prss::SharedRandomness, RecordId, + basics::{partial_reveal, Reveal, SecureMul}, + context::Context, + ipa_prf::boolean_ops::addition_sequential::integer_add, + prss::{FromPrss, SharedRandomness}, + RecordId, }, secret_sharing::{ replicated::{semi_honest::AdditiveShare, ReplicatedSecretSharing}, - SharedValue, + FieldSimd, FieldVectorizable, SharedValue, SharedValueArray, TransposeFrom, Vectorizable, }, }; @@ -24,7 +31,8 @@ pub(crate) enum Step { GenerateSecretSharing, IntegerAddBetweenMasks, IntegerAddMaskToX, - RevealY, + #[dynamic(256)] + RevealY(usize), } /// share conversion @@ -90,56 +98,53 @@ pub(crate) enum Step { /// However, these terms are only non-zero when all `rs_{k}` terms are non-zero /// this happens with probability `1/(2^(256-m))` which is negligible for a sufficiently small `m` /// +/// The implementation uses two type parameters to support vectorization. The type `XS` holds match +/// keys. In the unvectorized case, `XS` is `AdditiveShare`. In the vectorized case, `XS` is +/// `BitDecomposed>`. The type `YS` holds bitwise Fp25519 intermediates. In the +/// unvectorized case, `YS` is `AdditiveShare`. In the vectorized case, `YS` is +/// `BitDecomposed>`. +/// /// # Errors /// Propagates Errors from Integer Subtraction and Partial Reveal -pub async fn convert_to_fp25519( +pub async fn convert_to_fp25519( ctx: C, record_id: RecordId, - x: &AdditiveShare, -) -> Result, Error> + x: XS, +) -> Result, Error> where C: Context, - B: SharedValue + CustomArray, + Fp25519: Vectorizable, + Boolean: FieldSimd, + XS: ArrayAccessRef>, + YS: ArrayAccessRef> + + ArrayBuild> + + FromPrss, + AdditiveShare: SecureMul + + Reveal>::ArrayAlias> + + Not>, + Vec>: for<'a> TransposeFrom<&'a YS>, + Vec: + for<'a> TransposeFrom<&'a [>::Array; 256], Error = Infallible>, { + // `BITS` is the number of bits in the memory representation of Fp25519 field elements. It does + // not vary with vectorization. Where the type `BA256` appears literally in the source of this + // function, it is referring to this constant. (It is also possible for `BA256` to be used to + // hold width-256 vectorizations, but when it serves that purpose, it does not appear literally + // in the source of this function -- it is behind the XS and YS parameters.) + const BITS: usize = 256; + + // Ensure that the probability of leaking information is less than 1/(2^128). + debug_assert!(x.iter().count() < (BITS - 128)); + // generate sh_r = (0, 0, sh_r) and sh_s = (sh_s, 0, 0) // the two highest bits are set to 0 to allow carries for two additions - let (sh_r, sh_s) = { - // this closure generates sh_r, sh_r from PRSS randomness r - - // we generate random values r = (r1,r2,r3) using PRSS - // r: H1: (r1,r2), H2: (r2,r3), H3: (r3, r1) - let mut r: AdditiveShare = ctx - .narrow(&Step::GenerateSecretSharing) - .prss() - .generate(record_id); - - // set 2 highest order bits of r1, r2, r3 to 0 - r.set(255, AdditiveShare::::ZERO); - r.set(254, AdditiveShare::::ZERO); - - // generate sh_r, sh_s - // sh_r: H1: (0,0), H2: (0,r3), H3: (r3, 0) - // sh_s: H1: (r1,0), H2: (0,0), H3: (0, r1) - match ctx.role() { - Role::H1 => ( - AdditiveShare::new(::ZERO, ::ZERO), - AdditiveShare::new(r.left(), ::ZERO), - ), - Role::H2 => ( - AdditiveShare::new(::ZERO, r.right()), - AdditiveShare::new(::ZERO, ::ZERO), - ), - Role::H3 => ( - AdditiveShare::new(r.left(), ::ZERO), - AdditiveShare::new(::ZERO, r.right()), - ), - } - }; + let (sh_r, sh_s) = + gen_sh_r_and_sh_s::<_, _, BITS, N>(&ctx.narrow(&Step::GenerateSecretSharing), record_id); // addition r+s might cause carry, // this is no problem since we have set bit 254 of sh_r and sh_s to 0 let sh_rs = { - let (mut rs_with_higherorderbits, _) = integer_add::<_, BA256, BA256>( + let (mut rs_with_higherorderbits, _) = integer_add::<_, _, YS, YS, N>( ctx.narrow(&Step::IntegerAddBetweenMasks), record_id, &sh_r, @@ -149,7 +154,7 @@ where // PRSS/Multiply masks added random highest order bit, // remove them to not cause overflow in second addition (which is mod 256): - rs_with_higherorderbits.set(255, AdditiveShare::::ZERO); + rs_with_higherorderbits.set(BITS - 1, YS::make_ref(&AdditiveShare::::ZERO)); // return rs rs_with_higherorderbits @@ -158,30 +163,127 @@ where // addition x+rs, where rs=r+s might cause carry // this is not a problem since bit 255 of rs is set to 0 let (sh_y, _) = - integer_add::<_, BA256, B>(ctx.narrow(&Step::IntegerAddMaskToX), record_id, &sh_rs, x) + integer_add::<_, _, YS, XS, N>(ctx.narrow(&Step::IntegerAddMaskToX), record_id, &sh_rs, &x) .await?; // this leaks information, but with negligible probability - let y = AdditiveShare::::new(sh_y.left(), sh_y.right()) - .partial_reveal(ctx.narrow(&Step::RevealY), record_id, Role::H3) + let mut y = (ctx.role() != Role::H3).then(|| Vec::with_capacity(N)); + for i in 0..BITS { + let y_bit = partial_reveal( + ctx.narrow(&Step::RevealY(i)), + record_id, + Role::H3, + sh_y.get(i).unwrap().borrow(), + ) .await?; + match (&mut y, y_bit) { + (Some(y), Some(y_bit)) => y.push(y_bit), + (None, None) => (), + _ => unreachable!("inconsistent partial_reveal behavior"), + } + } + + let y = y.map(|y| { + Vec::::transposed_from(y.as_slice().try_into().unwrap()).unwrap_infallible() + }); + + let sh_r = Vec::>::transposed_from(&sh_r) + .ok() + .expect("sh_r was constructed with the correct number of bits"); + let sh_s = Vec::>::transposed_from(&sh_s) + .ok() + .expect("sh_s was constructed with the correct number of bits"); match ctx.role() { - Role::H1 => Ok(AdditiveShare::::new( - Fp25519::from(sh_s.left()).neg(), - Fp25519::from(BA256::from_array(&y.unwrap())), + Role::H1 => Ok(AdditiveShare::::new_arr( + >::Array::from_fn(|i| { + Fp25519::from(sh_s.get(i).unwrap().left()).neg() + }), + y.unwrap().into_iter().map(Fp25519::from).collect(), )), - Role::H2 => Ok(AdditiveShare::::new( - Fp25519::from(BA256::from_array(&y.unwrap())), - Fp25519::from(sh_r.right()).neg(), + Role::H2 => Ok(AdditiveShare::::new_arr( + y.unwrap().into_iter().map(Fp25519::from).collect(), + >::Array::from_fn(|i| { + Fp25519::from(sh_r.get(i).unwrap().right()).neg() + }), )), - Role::H3 => Ok(AdditiveShare::::new( - Fp25519::from(sh_r.left()).neg(), - Fp25519::from(sh_s.right()).neg(), + Role::H3 => Ok(AdditiveShare::::new_arr( + >::Array::from_fn(|i| { + Fp25519::from(sh_r.get(i).unwrap().left()).neg() + }), + >::Array::from_fn(|i| { + Fp25519::from(sh_s.get(i).unwrap().right()).neg() + }), )), } } +/// Generates `sh_r` and `sh_s` from PRSS randomness (`r`). +fn gen_sh_r_and_sh_s( + ctx: &C, + record_id: RecordId, +) -> (YS, YS) +where + C: Context, + Boolean: FieldSimd, + YS: ArrayAccessRef> + + ArrayBuild> + + FromPrss, +{ + // we generate random values r = (r1,r2,r3) using PRSS + // r: H1: (r1,r2), H2: (r2,r3), H3: (r3, r1) + let mut r: YS = ctx.prss().generate_with(record_id, BITS); + + // set 2 highest order bits of r1, r2, r3 to 0 + r.set(BITS - 1, YS::make_ref(&AdditiveShare::::ZERO)); + r.set(BITS - 2, YS::make_ref(&AdditiveShare::::ZERO)); + + let mut sh_r_builder = YS::builder().with_capacity(BITS); + let mut sh_s_builder = YS::builder().with_capacity(BITS); + // generate sh_r, sh_s + // sh_r: H1: (0,0), H2: (0,r3), H3: (r3, 0) + // sh_s: H1: (r1,0), H2: (0,0), H3: (0, r1) + match ctx.role() { + Role::H1 => { + for i in 0..BITS { + sh_r_builder.push(AdditiveShare::new_arr( + >::Array::ZERO_ARRAY, + >::Array::ZERO_ARRAY, + )); + sh_s_builder.push(AdditiveShare::new_arr( + r.get(i).unwrap().borrow().left_arr().clone(), + >::Array::ZERO_ARRAY, + )); + } + } + Role::H2 => { + for i in 0..BITS { + sh_r_builder.push(AdditiveShare::new_arr( + >::Array::ZERO_ARRAY, + r.get(i).unwrap().borrow().right_arr().clone(), + )); + sh_s_builder.push(AdditiveShare::new_arr( + >::Array::ZERO_ARRAY, + >::Array::ZERO_ARRAY, + )); + } + } + Role::H3 => { + for i in 0..BITS { + sh_r_builder.push(AdditiveShare::new_arr( + r.get(i).unwrap().borrow().left_arr().clone(), + >::Array::ZERO_ARRAY, + )); + sh_s_builder.push(AdditiveShare::new_arr( + >::Array::ZERO_ARRAY, + r.get(i).unwrap().borrow().right_arr().clone(), + )); + } + } + } + (sh_r_builder.build(), sh_s_builder.build()) +} + /// inserts smaller array in the larger array starting from location offset pub fn expand_shared_array_in_place( y: &mut AdditiveShare, @@ -192,9 +294,10 @@ pub fn expand_shared_array_in_place( XS: SharedValue + ArrayAccess + Expand, { for i in 0..XS::BITS as usize { - y.set( + ArrayAccess::set( + y, i + offset, - x.get(i).unwrap_or(AdditiveShare::::ZERO), + ArrayAccess::get(x, i).unwrap_or(AdditiveShare::::ZERO), ); } } @@ -207,9 +310,10 @@ where { let mut x = AdditiveShare::::ZERO; for i in 0..XS::BITS as usize { - x.set( + ArrayAccess::set( + &mut x, i, - y.get(i + offset).unwrap_or(AdditiveShare::::ZERO), + ArrayAccess::get(y, i + offset).unwrap_or(AdditiveShare::::ZERO), ); } x @@ -238,60 +342,137 @@ where #[cfg(all(test, unit_test))] mod tests { + use std::iter::repeat_with; + use curve25519_dalek::Scalar; + use futures::stream::TryStreamExt; use generic_array::GenericArray; use rand::Rng; use typenum::U32; + use super::*; use crate::{ - ff::{ - boolean::Boolean, - boolean_array::{BA256, BA64}, - ec_prime_field::Fp25519, - ArrayAccess, Serializable, - }, - protocol, - protocol::{ - context::Context, - ipa_prf::boolean_ops::share_conversion_aby::{convert_to_fp25519, expand_array}, - }, + ff::{boolean_array::BA64, Serializable}, + helpers::stream::{ProcessChunks, TryFlattenItersExt}, rand::thread_rng, - secret_sharing::SharedValue, + seq_join::{seq_join, SeqJoin}, test_executor::run, - test_fixture::{Reconstruct, Runner, TestWorld}, + test_fixture::{ReconstructArr, Runner, TestWorld}, + BoolVector, }; - #[test] - fn semi_honest_convert_into_fp25519() { + fn test_semi_honest_convert_into_fp25519() + where + Fp25519: Vectorizable, + Boolean: FieldSimd, + XS: ArrayAccessRef> + + ArrayBuild> + + for<'a> TransposeFrom<&'a [AdditiveShare; CHUNK], Error = Infallible> + + Send + + Sync + + 'static, + YS: ArrayAccessRef> + + ArrayBuild> + + FromPrss + + Send + + Sync + + 'static, + for<'a> ::Ref<'a>: Send, + for<'a> ::Ref<'a>: Send, + AdditiveShare: Not>, + Vec>: for<'a> TransposeFrom<&'a YS>, + Vec: for<'a> TransposeFrom< + &'a [>::Array; 256], + Error = Infallible, + >, + [AdditiveShare; 3]: ReconstructArr<>::Array>, + { run(|| async move { let world = TestWorld::default(); let mut rng = thread_rng(); - let records = rng.gen::(); - - let mut buf: GenericArray = [0u8; 32].into(); - - expand_array::(&records, None).serialize(&mut buf); + let records = repeat_with(|| rng.gen::()) + .take(COUNT) + .collect::>(); - let expected = Fp25519::from(::from_bytes_mod_order(<[u8; 32]>::from(buf))); + let expected = records + .iter() + .map(|record| { + let mut buf: GenericArray = [0u8; 32].into(); + expand_array::(record, None).serialize(&mut buf); + Fp25519::from(::from_bytes_mod_order(<[u8; 32]>::from(buf))) + }) + .collect::>(); - let result = world - .semi_honest(records, |ctx, x| async move { - convert_to_fp25519::<_, BA64>( - ctx.set_total_records(1), - protocol::RecordId(0), - &x, + let [res0, res1, res2] = world + .semi_honest(records.into_iter(), |ctx, records| async move { + #[cfg(not(debug_assertions))] + let begin = std::time::Instant::now(); + let res: Result>, Error> = seq_join( + ctx.active_work(), + records.process_chunks( + |idx, chunk| { + let ctx = ctx.clone(); + async move { + let mut match_keys_builder = XS::builder(); + for _ in 0..CHUNK { + match_keys_builder + .push(AdditiveShare::::ZERO); + } + let mut match_keys = match_keys_builder.build(); + match_keys.transpose_from(&chunk).unwrap_infallible(); + convert_to_fp25519::<_, XS, YS, CHUNK>( + ctx.set_total_records((COUNT + CHUNK - 1) / CHUNK), + RecordId::from(idx), + match_keys, + ) + .await + .map(|shares| { + shares + .into_unpacking_iter() + .collect::>() + .try_into() + .unwrap() + }) + } + }, + || AdditiveShare::::ZERO, + ), ) - .await - .unwrap() + .try_flatten_iters() + .try_collect() + .await; + #[cfg(not(debug_assertions))] + tracing::info!("Execution time: {:?}", begin.elapsed()); + res }) .await - .reconstruct(); + .map(Result::unwrap); + let mut result = Vec::with_capacity(COUNT); + for line in res0.into_iter().zip(res1).zip(res2) { + let ((s0, s1), s2) = line; + result.extend([s0, s1, s2].reconstruct_arr().into_iter()); + } assert_eq!(result, expected); }); } + // The third generic parameter in these calls is the number of conversions. It is set to give + // reasonable runtime for debug builds. These can also be used for benchmarking, in which case + // a size of 4096 is reasonable. + + #[test] + fn semi_honest_convert_into_fp25519_novec() { + test_semi_honest_convert_into_fp25519::(); + } + + #[test] + fn semi_honest_convert_into_fp25519_vec64() { + test_semi_honest_convert_into_fp25519::( + ); + } + #[test] fn test_expand() { let mut rng = thread_rng(); diff --git a/ipa-core/src/protocol/ipa_prf/mod.rs b/ipa-core/src/protocol/ipa_prf/mod.rs index aab014b52..aa5628c70 100644 --- a/ipa-core/src/protocol/ipa_prf/mod.rs +++ b/ipa-core/src/protocol/ipa_prf/mod.rs @@ -1,5 +1,6 @@ -use std::{num::NonZeroU32, ops::Add}; +use std::{array, iter, num::NonZeroU32, ops::Add}; +use futures_util::TryStreamExt; use generic_array::{ArrayLength, GenericArray}; use ipa_macros::Step; use typenum::{Unsigned, U18}; @@ -11,6 +12,7 @@ use crate::{ boolean::Boolean, boolean_array::BA64, CustomArray, PrimeField, Serializable, U128Conversions, }, + helpers::stream::{ChunkData, ProcessChunks, TryFlattenItersExt}, protocol::{ basics::BooleanArrayMul, context::{UpgradableContext, UpgradedContext}, @@ -25,8 +27,10 @@ use crate::{ }, secret_sharing::{ replicated::{malicious::ExtendableField, semi_honest::AdditiveShare as Replicated}, - SharedValue, + SharedValue, TransposeFrom, }, + seq_join::seq_join, + BoolVector, }; mod boolean_ops; @@ -38,6 +42,12 @@ mod malicious_security; mod quicksort; mod shuffle; +/// Match key size +pub const MK_BITS: usize = 64; + +/// Vectorization dimension for PRF +pub const PRF_CHUNK: usize = 64; + #[derive(Step)] pub(crate) enum Step { ConvertFp25519, @@ -47,8 +57,8 @@ pub(crate) enum Step { SortByTimestamp, } -#[derive(Debug)] -#[cfg_attr(test, derive(Clone, PartialEq, Eq))] +#[derive(Clone, Debug)] +#[cfg_attr(test, derive(PartialEq, Eq))] pub struct OPRFIPAInputRow { pub match_key: Replicated, pub is_trigger: Replicated, @@ -186,7 +196,7 @@ where { let shuffled = shuffle_inputs(ctx.narrow(&Step::Shuffle), input_rows).await?; let mut prfd_inputs = - compute_prf_for_inputs(ctx.narrow(&Step::ConvertInputRowsToPrf), shuffled).await?; + compute_prf_for_inputs(ctx.narrow(&Step::ConvertInputRowsToPrf), &shuffled).await?; prfd_inputs.sort_by(|a, b| a.prf_of_match_key.cmp(&b.prf_of_match_key)); @@ -212,7 +222,7 @@ where #[tracing::instrument(name = "compute_prf_for_inputs", skip_all)] async fn compute_prf_for_inputs( ctx: C, - input_rows: Vec>, + input_rows: &[OPRFIPAInputRow], ) -> Result>, Error> where C: UpgradableContext, @@ -224,35 +234,74 @@ where F: PrimeField + ExtendableField, Replicated: Serializable, { - let ctx = ctx.set_total_records(input_rows.len()); + let ctx = ctx.set_total_records((input_rows.len() + PRF_CHUNK - 1) / PRF_CHUNK); let convert_ctx = ctx.narrow(&Step::ConvertFp25519); let eval_ctx = ctx.narrow(&Step::EvalPrf); let prf_key = gen_prf_key(&convert_ctx); - ctx.try_join(input_rows.into_iter().enumerate().map(|(idx, record)| { - let convert_ctx = convert_ctx.clone(); - let eval_ctx = eval_ctx.clone(); - let prf_key = &prf_key; - async move { - let record_id = RecordId::from(idx); - let elliptic_curve_pt = - convert_to_fp25519::<_, BA64>(convert_ctx, record_id, &record.match_key).await?; - let elliptic_curve_pt = - eval_dy_prf(eval_ctx, record_id, prf_key, &elliptic_curve_pt).await?; - - Ok::<_, Error>(PrfShardedIpaInputRow { - prf_of_match_key: elliptic_curve_pt, - is_trigger_bit: record.is_trigger, - breakdown_key: record.breakdown_key, - trigger_value: record.trigger_value, - timestamp: record.timestamp, - sort_key: Replicated::ZERO, - }) - } - })) + seq_join( + ctx.active_work(), + input_rows.process_chunks( + move |idx, records: ChunkData<_, PRF_CHUNK>| { + let convert_ctx = convert_ctx.clone(); + let eval_ctx = eval_ctx.clone(); + let prf_key = prf_key.clone(); + + async move { + let record_id = RecordId::from(idx); + let input_match_keys: &dyn Fn(usize) -> Replicated = + &|i| records[i].match_key.clone(); + let mut match_keys = iter::empty().collect::(); + match_keys + .transpose_from(input_match_keys) + .unwrap_infallible(); + let curve_pts = convert_to_fp25519::< + _, + BoolVector!(64, PRF_CHUNK), + BoolVector!(256, PRF_CHUNK), + PRF_CHUNK, + >(convert_ctx, record_id, match_keys) + .await?; + + let prf_of_match_keys = + eval_dy_prf::<_, PRF_CHUNK>(eval_ctx, record_id, &prf_key, curve_pts) + .await?; + + Ok(array::from_fn(|i| { + let OPRFIPAInputRow { + match_key: _, + is_trigger, + breakdown_key, + trigger_value, + timestamp, + } = &records[i]; + + PrfShardedIpaInputRow { + prf_of_match_key: prf_of_match_keys[i], + is_trigger_bit: is_trigger.clone(), + breakdown_key: breakdown_key.clone(), + trigger_value: trigger_value.clone(), + timestamp: timestamp.clone(), + sort_key: Replicated::ZERO, + } + })) + } + }, + || OPRFIPAInputRow { + match_key: Replicated::::ZERO, + is_trigger: Replicated::::ZERO, + breakdown_key: Replicated::::ZERO, + trigger_value: Replicated::::ZERO, + timestamp: Replicated::::ZERO, + }, + ), + ) + .try_flatten_iters() + .try_collect() .await } + #[cfg(all(test, any(unit_test, feature = "shuttle")))] pub mod tests { use crate::{ diff --git a/ipa-core/src/protocol/ipa_prf/prf_eval.rs b/ipa-core/src/protocol/ipa_prf/prf_eval.rs index 10bbad630..a10a9a0e2 100644 --- a/ipa-core/src/protocol/ipa_prf/prf_eval.rs +++ b/ipa-core/src/protocol/ipa_prf/prf_eval.rs @@ -1,17 +1,19 @@ +use std::iter::zip; + use ipa_macros::Step; use crate::{ error::Error, - ff::{curve_points::RP25519, ec_prime_field::Fp25519}, + ff::{boolean::Boolean, curve_points::RP25519, ec_prime_field::Fp25519, Expand}, protocol::{ basics::{Reveal, SecureMul}, context::Context, - prss::SharedRandomness, + prss::{FromPrss, SharedRandomness}, RecordId, }, secret_sharing::{ - replicated::{semi_honest::AdditiveShare, ReplicatedSecretSharing}, - SharedValue, + replicated::semi_honest::AdditiveShare, FieldSimd, FieldVectorizable, Sendable, StdArray, + Vectorizable, }, }; @@ -40,15 +42,25 @@ where { let ctx = sh_ctx.set_total_records(input_match_keys.len()); let futures = input_match_keys - .iter() + .into_iter() .enumerate() .map(|(i, x)| eval_dy_prf(ctx.clone(), i.into(), &prf_key, x)); - ctx.try_join(futures).await + Ok(ctx.try_join(futures).await?.into_iter().flatten().collect()) } -impl From> for AdditiveShare { - fn from(s: AdditiveShare) -> Self { - AdditiveShare::new(RP25519::from(s.left()), RP25519::from(s.right())) +impl From> for AdditiveShare +where + Fp25519: Vectorizable, + RP25519: Vectorizable>, + StdArray: Sendable, +{ + fn from(value: AdditiveShare) -> Self { + let (left_arr, right_arr) = + StdArray::::from_tuple_iter(value.into_unpacking_iter().map(|sh| { + let (l, r) = sh.as_tuple(); + (RP25519::from(l), RP25519::from(r)) + })); + Self::new_arr(left_arr, right_arr) } } @@ -67,35 +79,47 @@ where /// outputs a u64 as specified in `protocol/prf_sharding/mod.rs`, all parties learn the output /// # Errors /// Propagates errors from multiplications, reveal and scalar multiplication - -pub async fn eval_dy_prf( +/// # Panics +/// Never as of when this comment was written, but the compiler didn't know that. +pub async fn eval_dy_prf( ctx: C, record_id: RecordId, k: &AdditiveShare, - x: &AdditiveShare, -) -> Result + x: AdditiveShare, +) -> Result<[u64; N], Error> where C: Context, + Fp25519: Vectorizable, + RP25519: Vectorizable>, + Boolean: FieldSimd, + AdditiveShare: Reveal>::ArrayAlias>, + AdditiveShare: SecureMul + FromPrss, + StdArray: Sendable, { - let sh_r: AdditiveShare = ctx.narrow(&Step::GenRandomMask).prss().generate(record_id); - - //compute (g^left, g^right) - let sh_gr = AdditiveShare::::from(sh_r.clone()); + let sh_r: AdditiveShare = + ctx.narrow(&Step::GenRandomMask).prss().generate(record_id); //compute x+k - let mut y = x + k; + let mut y = x + AdditiveShare::::expand(k); //compute y <- r*y y = y .multiply(&sh_r, ctx.narrow(&Step::MultMaskWithPRFInput), record_id) .await?; + //compute (g^left, g^right) + let sh_gr = AdditiveShare::::from(sh_r); + //reconstruct (z,R) - let gr = RP25519::from_array(&sh_gr.reveal(ctx.narrow(&Step::RevealR), record_id).await?); - let z = Fp25519::from_array(&y.reveal(ctx.narrow(&Step::Revealz), record_id).await?); + let gr = sh_gr.reveal(ctx.narrow(&Step::RevealR), record_id).await?; + let z = y.reveal(ctx.narrow(&Step::Revealz), record_id).await?; //compute R^(1/z) to u64 - Ok(u64::from(gr * (z.invert()))) + Ok(zip(gr, z) + .map(|(gr, z)| u64::from(gr * z.invert())) + .collect::>() + .try_into() + .expect("iteration over arrays")) } #[cfg(all(test, unit_test))] diff --git a/ipa-core/src/protocol/prss/crypto.rs b/ipa-core/src/protocol/prss/crypto.rs index a332b9bea..0fa8c9209 100644 --- a/ipa-core/src/protocol/prss/crypto.rs +++ b/ipa-core/src/protocol/prss/crypto.rs @@ -13,7 +13,7 @@ use crate::{ ff::Field, protocol::prss::PrssIndex, secret_sharing::{ - replicated::{semi_honest::AdditiveShare as Replicated, ReplicatedSecretSharing}, + replicated::{semi_honest::AdditiveShare, ReplicatedSecretSharing}, SharedValue, }, }; @@ -69,14 +69,30 @@ impl FromRandom for T { /// /// In the first case, `FromPrss` is implemented for a tuple type, while in the second case, /// `FromPrss` is implemented for a secret-shared type. -pub trait FromPrss: Sized { - fn from_prss>(prss: &P, index: I) -> Self; +pub trait FromPrss +where + Self: Sized, + Params: Default, +{ + fn from_prss_with>( + prss: &P, + index: I, + params: Params, + ) -> Self; + + fn from_prss>(prss: &P, index: I) -> Self { + Self::from_prss_with(prss, index, Default::default()) + } } /// Generate two random values, one that is known to the left helper /// and one that is known to the right helper. impl FromPrss for (T, T) { - fn from_prss>(prss: &P, index: I) -> (T, T) { + fn from_prss_with>( + prss: &P, + index: I, + _params: (), + ) -> (T, T) { let (l, r) = prss.generate_arrays(index); (T::from_random(l), T::from_random(r)) } @@ -88,24 +104,68 @@ impl FromPrss for (T, T) { /// "Efficient Bit-Decomposition and Modulus Conversion Protocols with an Honest Majority" /// by Ryo Kikuchi, Dai Ikarashi, Takahiro Matsuda, Koki Hamada, and Koji Chida /// -impl FromPrss for Replicated { - fn from_prss>( +impl FromPrss for AdditiveShare { + fn from_prss_with>( prss: &P, index: I, - ) -> Replicated { + _params: (), + ) -> AdditiveShare { let (l, r) = <(T, T) as FromPrss>::from_prss(prss, index); - Replicated::new(l, r) + AdditiveShare::new(l, r) + } +} + +/// Generate a replicated secret sharing of a random value, which none +/// of the helpers knows. This is an implementation of the functionality 2.1 `F_rand` +/// described on page 5 of the paper: +/// "Efficient Bit-Decomposition and Modulus Conversion Protocols with an Honest Majority" +/// by Ryo Kikuchi, Dai Ikarashi, Takahiro Matsuda, Koki Hamada, and Koji Chida +/// +impl FromPrss for AdditiveShare { + fn from_prss_with>( + prss: &P, + index: I, + len: usize, + ) -> AdditiveShare { + assert_eq!( + u32::try_from(len).unwrap(), + ::BITS, + "incorrect length {len} for AdditiveShare::FromPrss, expected {}", + ::BITS, + ); + let (l, r) = <(T, T) as FromPrss>::from_prss(prss, index); + AdditiveShare::new(l, r) } } pub trait SharedRandomness { + type ChunksIter<'a, Z: ArrayLength>: Iterator< + Item = (GenericArray, GenericArray), + > + where + Self: 'a; + + /// Return an iterator over chunks of generated randomness. + /// + /// The iterator returns 2-tuples of `GenericArray` chunks, one that is known to the + /// left helper and one that is known to the right helper. + /// + /// This functionality is intended for use generating large vectorized values. + #[must_use] + fn generate_chunks_iter, Z: ArrayLength>( + &self, + index: I, + ) -> Self::ChunksIter<'_, Z>; + /// Generate two random values, one that is known to the left helper /// and one that is known to the right helper. #[must_use] fn generate_arrays, N: ArrayLength>( &self, index: I, - ) -> (GenericArray, GenericArray); + ) -> (GenericArray, GenericArray) { + Self::generate_chunks_iter(self, index).next().unwrap() + } /// Generate two random values, one that is known to the left helper /// and one that is known to the right helper. @@ -133,6 +193,18 @@ pub trait SharedRandomness { T::from_prss(self, index) } + /// Generate something that implements the `FromPrss` trait, passing parameters. + /// + /// Generation by `FromPrss` is described in more detail in the `FromPrss` documentation. + #[must_use] + fn generate_with, I: Into, P: Default>( + &self, + index: I, + params: P, + ) -> T { + T::from_prss_with(self, index, params) + } + /// Generate a non-replicated additive secret sharing of zero. /// /// This is used for the MAC accumulators for malicious security. diff --git a/ipa-core/src/protocol/prss/mod.rs b/ipa-core/src/protocol/prss/mod.rs index 15690fd7e..41db1e7d3 100644 --- a/ipa-core/src/protocol/prss/mod.rs +++ b/ipa-core/src/protocol/prss/mod.rs @@ -4,6 +4,7 @@ use std::collections::HashSet; use std::{ collections::HashMap, fmt::{Debug, Display, Formatter}, + marker::PhantomData, }; pub use crypto::{ @@ -157,20 +158,50 @@ pub struct IndexedSharedRandomness { } impl SharedRandomness for IndexedSharedRandomness { - fn generate_arrays, N: ArrayLength>( + type ChunksIter<'a, Z: ArrayLength> = ChunksIter<'a, Z>; + + fn generate_chunks_iter, Z: ArrayLength>( &self, index: I, - ) -> (GenericArray, GenericArray) { - let index = index.into(); + ) -> Self::ChunksIter<'_, Z> { + ChunksIter { + inner: self, + index: index.into(), + offset: 0, + phantom_data: PhantomData, + } + } +} + +pub struct ChunksIter<'a, Z: ArrayLength> { + inner: &'a IndexedSharedRandomness, + index: PrssIndex, + offset: usize, + phantom_data: PhantomData, +} + +impl<'a, Z: ArrayLength> Iterator for ChunksIter<'a, Z> { + type Item = (GenericArray, GenericArray); + + fn next(&mut self) -> Option { #[cfg(debug_assertions)] { - for i in 0..N::USIZE { - self.used.insert(index.offset(i)); + for i in self.offset..self.offset + Z::USIZE { + self.inner.used.insert(self.index.offset(i)); } } - let l = GenericArray::generate(|i| self.left.generate(index.offset(i).into())); - let r = GenericArray::generate(|i| self.right.generate(index.offset(i).into())); - (l, r) + let l = GenericArray::generate(|i| { + self.inner + .left + .generate(self.index.offset(self.offset + i).into()) + }); + let r = GenericArray::generate(|i| { + self.inner + .right + .generate(self.index.offset(self.offset + i).into()) + }); + self.offset += Z::USIZE; + Some((l, r)) } } diff --git a/ipa-core/src/protocol/step/steps.txt b/ipa-core/src/protocol/step/steps.txt index 8bffb0fb6..5d233d7ef 100644 --- a/ipa-core/src/protocol/step/steps.txt +++ b/ipa-core/src/protocol/step/steps.txt @@ -515,7 +515,262 @@ ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol: ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::integer_add_mask_to_x/ipa_core::protocol::step::BitOpStep::bit97 ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::integer_add_mask_to_x/ipa_core::protocol::step::BitOpStep::bit98 ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::integer_add_mask_to_x/ipa_core::protocol::step::BitOpStep::bit99 -ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y0 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y1 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y10 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y100 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y101 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y102 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y103 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y104 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y105 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y106 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y107 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y108 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y109 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y11 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y110 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y111 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y112 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y113 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y114 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y115 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y116 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y117 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y118 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y119 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y12 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y120 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y121 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y122 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y123 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y124 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y125 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y126 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y127 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y128 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y129 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y13 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y130 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y131 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y132 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y133 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y134 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y135 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y136 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y137 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y138 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y139 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y14 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y140 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y141 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y142 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y143 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y144 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y145 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y146 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y147 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y148 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y149 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y15 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y150 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y151 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y152 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y153 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y154 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y155 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y156 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y157 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y158 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y159 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y16 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y160 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y161 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y162 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y163 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y164 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y165 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y166 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y167 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y168 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y169 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y17 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y170 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y171 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y172 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y173 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y174 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y175 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y176 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y177 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y178 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y179 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y18 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y180 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y181 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y182 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y183 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y184 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y185 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y186 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y187 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y188 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y189 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y19 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y190 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y191 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y192 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y193 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y194 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y195 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y196 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y197 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y198 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y199 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y2 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y20 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y200 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y201 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y202 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y203 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y204 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y205 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y206 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y207 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y208 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y209 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y21 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y210 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y211 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y212 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y213 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y214 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y215 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y216 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y217 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y218 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y219 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y22 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y220 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y221 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y222 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y223 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y224 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y225 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y226 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y227 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y228 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y229 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y23 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y230 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y231 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y232 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y233 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y234 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y235 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y236 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y237 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y238 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y239 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y24 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y240 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y241 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y242 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y243 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y244 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y245 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y246 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y247 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y248 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y249 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y25 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y250 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y251 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y252 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y253 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y254 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y255 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y26 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y27 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y28 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y29 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y3 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y30 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y31 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y32 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y33 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y34 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y35 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y36 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y37 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y38 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y39 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y4 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y40 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y41 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y42 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y43 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y44 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y45 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y46 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y47 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y48 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y49 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y5 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y50 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y51 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y52 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y53 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y54 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y55 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y56 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y57 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y58 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y59 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y6 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y60 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y61 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y62 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y63 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y64 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y65 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y66 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y67 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y68 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y69 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y7 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y70 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y71 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y72 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y73 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y74 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y75 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y76 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y77 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y78 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y79 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y8 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y80 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y81 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y82 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y83 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y84 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y85 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y86 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y87 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y88 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y89 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y9 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y90 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y91 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y92 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y93 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y94 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y95 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y96 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y97 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y98 +ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::boolean_ops::share_conversion_aby::Step::reveal_y99 ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::convert_fp25519/ipa_core::protocol::ipa_prf::prf_eval::Step::p_r_f_key_gen ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::eval_prf ipa_core::protocol::ipa_prf::Step::convert_input_rows_to_prf/ipa_core::protocol::ipa_prf::Step::eval_prf/ipa_core::protocol::ipa_prf::prf_eval::Step::gen_random_mask @@ -708,7 +963,42 @@ ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass13/ipa_core::protocol::ipa_prf::quicksort::Step::reveal ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14 ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit0 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit1 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit10 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit11 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit12 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit13 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit14 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit15 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit16 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit17 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit18 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit19 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit2 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit20 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit21 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit22 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit23 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit24 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit25 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit26 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit27 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit28 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit29 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit3 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit30 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit31 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit4 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit5 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit6 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit7 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit8 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit9 ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass14/ipa_core::protocol::ipa_prf::quicksort::Step::reveal +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass15 +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass15/ipa_core::protocol::ipa_prf::quicksort::Step::compare +ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass15/ipa_core::protocol::ipa_prf::quicksort::Step::reveal ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass2 ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass2/ipa_core::protocol::ipa_prf::quicksort::Step::compare ipa_core::protocol::ipa_prf::Step::sort_by_timestamp/ipa_core::protocol::ipa_prf::quicksort::Step::quicksort_pass2/ipa_core::protocol::ipa_prf::quicksort::Step::compare/ipa_core::protocol::step::BitOpStep::bit0 diff --git a/ipa-core/src/secret_sharing/decomposed.rs b/ipa-core/src/secret_sharing/decomposed.rs index f15455a87..e96d8e322 100644 --- a/ipa-core/src/secret_sharing/decomposed.rs +++ b/ipa-core/src/secret_sharing/decomposed.rs @@ -6,8 +6,12 @@ use std::{ use crate::{ error::Error, - ff::{ArrayAccessRef, ArrayBuild, ArrayBuilder, PrimeField}, - secret_sharing::{Linear as LinearSecretSharing, LinearRefOps}, + ff::{boolean::Boolean, ArrayAccessRef, ArrayBuild, ArrayBuilder, PrimeField}, + protocol::prss::{FromPrss, FromRandom, PrssIndex, SharedRandomness}, + secret_sharing::{ + replicated::semi_honest::AdditiveShare, Linear as LinearSecretSharing, LinearRefOps, + SharedValue, Vectorizable, + }, }; #[derive(Clone, Debug, PartialEq)] @@ -103,12 +107,42 @@ impl BitDecomposed { } } +// Provides BitDecomposed <-> BooleanArray interoperability. Otherwise just use `new`. +impl FromIterator for BitDecomposed { + fn from_iter>(iter: I) -> Self { + Self::new(iter) + } +} + impl BitDecomposed { pub fn resize(&mut self, new_len: usize, value: S) { self.bits.resize(new_len, value); } } +impl FromPrss for BitDecomposed> +where + A: SharedValue + FromRandom, + Boolean: Vectorizable, +{ + fn from_prss_with>( + prss: &P, + index: I, + len: usize, + ) -> Self { + let bits = prss + .generate_chunks_iter::<_, ::SourceLength>(index) + .map(|(l_rand, r_rand)| { + let l_val = A::from_random(l_rand); + let r_val = A::from_random(r_rand); + AdditiveShare::new_arr(l_val, r_val) + }) + .take(len) + .collect(); + Self { bits } + } +} + impl TryFrom> for BitDecomposed { type Error = Error; fn try_from(bits: Vec) -> Result { diff --git a/ipa-core/src/secret_sharing/mod.rs b/ipa-core/src/secret_sharing/mod.rs index eb1838f0e..9e5e2453f 100644 --- a/ipa-core/src/secret_sharing/mod.rs +++ b/ipa-core/src/secret_sharing/mod.rs @@ -23,8 +23,8 @@ use rand::{ }; pub use scheme::{Bitwise, Linear, LinearRefOps, SecretSharing}; pub use vector::{ - FieldArray, FieldSimd, FieldVectorizable, SharedValueArray, StdArray, TransposeFrom, - Vectorizable, + BoolVectorLookup, BoolVectorTrait, FieldArray, FieldSimd, FieldVectorizable, SharedValueArray, + StdArray, TransposeFrom, Vectorizable, }; #[cfg(any(test, feature = "test-fixture", feature = "cli"))] diff --git a/ipa-core/src/secret_sharing/replicated/semi_honest/additive_share.rs b/ipa-core/src/secret_sharing/replicated/semi_honest/additive_share.rs index c37bee4b1..55c5fbe2f 100644 --- a/ipa-core/src/secret_sharing/replicated/semi_honest/additive_share.rs +++ b/ipa-core/src/secret_sharing/replicated/semi_honest/additive_share.rs @@ -113,17 +113,20 @@ impl, const N: usize> AdditiveShare { &mut self.1 } - pub fn into_arr_tuple(self) -> (>::Array, >::Array) { - let Self(left, right) = self; - (left, right) - } - pub fn from_fns V, RF: FnMut(usize) -> V>(lf: LF, rf: RF) -> Self { Self( >::Array::from_fn(lf), >::Array::from_fn(rf), ) } + + // Providing this as IntoIterator results in conflicting malicious upgrade implementations for + // AdditiveShare. It's not clear that the unpacking iterator is a universally appropriate thing + // to return from IntoIterator anyways. + pub fn into_unpacking_iter(self) -> UnpackIter { + let Self(left, right) = self; + UnpackIter(left.into_iter(), right.into_iter()) + } } impl AdditiveShare @@ -476,6 +479,23 @@ where } } +pub struct UnpackIter, const N: usize>( + <>::Array as IntoIterator>::IntoIter, + <>::Array as IntoIterator>::IntoIter, +); + +impl, const N: usize> Iterator for UnpackIter { + type Item = AdditiveShare; + + fn next(&mut self) -> Option { + match (self.0.next(), self.1.next()) { + (None, None) => None, + (Some(left), Some(right)) => Some(AdditiveShare::new(left, right)), + _ => unreachable!("unequal left/right length in vectorized AdditiveShare"), + } + } +} + pub struct AdditiveShareArrayBuilder where B: ArrayBuilder, diff --git a/ipa-core/src/secret_sharing/vector/array.rs b/ipa-core/src/secret_sharing/vector/array.rs index ce3c22f14..a5ad37119 100644 --- a/ipa-core/src/secret_sharing/vector/array.rs +++ b/ipa-core/src/secret_sharing/vector/array.rs @@ -6,12 +6,13 @@ use std::{ }; use generic_array::{ArrayLength, GenericArray}; -use typenum::{U16, U256, U32, U64}; +use typenum::{U128, U16, U256, U32, U64}; use crate::{ + const_assert_eq, error::LengthError, - ff::{Field, Fp32BitPrime, Serializable}, - protocol::prss::FromRandom, + ff::{ec_prime_field::Fp25519, Expand, Field, Fp32BitPrime, Serializable}, + protocol::{ipa_prf::PRF_CHUNK, prss::FromRandom}, secret_sharing::{FieldArray, Sendable, SharedValue, SharedValueArray}, }; @@ -104,6 +105,31 @@ where } } +impl StdArray +where + Self: Sendable, // required for `::ZERO` +{ + /// Build a pair of `StdArray`s from an iterator over tuples. + /// + /// # Panics + /// If the iterator terminates before producing N items. + pub fn from_tuple_iter>(iter: T) -> (Self, Self) { + let mut l_res = Self::ZERO_ARRAY; + let mut r_res = Self::ZERO_ARRAY; + let mut iter = iter.into_iter(); + + for i in 0..N { + let (l, r) = iter + .next() + .unwrap_or_else(|| panic!("Expected iterator to produce {N} items, got only {i}")); + l_res.0[i] = l; + r_res.0[i] = r; + } + + (l_res, r_res) + } +} + impl IntoIterator for StdArray { type Item = V; type IntoIter = std::array::IntoIter; @@ -113,6 +139,14 @@ impl IntoIterator for StdArray { } } +impl Expand for StdArray { + type Input = V; + + fn expand(v: &Self::Input) -> Self { + Self(array::from_fn(|_| *v)) + } +} + impl<'a, 'b, V: SharedValue, const N: usize> Add<&'b StdArray> for &'a StdArray { type Output = StdArray; @@ -293,6 +327,13 @@ macro_rules! impl_from_random { }; } +const_assert_eq!( + PRF_CHUNK, + 64, + "Appropriate FromRandom implementation required" +); +impl_from_random!(Fp25519, 64, U128, 2); + impl_from_random!(Fp32BitPrime, 32, U32, 1); impl Serializable for StdArray { diff --git a/ipa-core/src/secret_sharing/vector/impls.rs b/ipa-core/src/secret_sharing/vector/impls.rs index 2ada6571c..9fffbc0c3 100644 --- a/ipa-core/src/secret_sharing/vector/impls.rs +++ b/ipa-core/src/secret_sharing/vector/impls.rs @@ -1,19 +1,24 @@ //! Supported vectorizations use crate::{ + const_assert_eq, ff::{ boolean::Boolean, boolean_array::{BA16, BA20, BA256, BA3, BA32, BA5, BA64, BA8}, + ec_prime_field::Fp25519, Fp32BitPrime, }, + protocol::ipa_prf::{MK_BITS, PRF_CHUNK}, secret_sharing::{ - replicated::semi_honest::AdditiveShare, FieldSimd, FieldVectorizable, - ReplicatedSecretSharing, Vectorizable, + replicated::semi_honest::AdditiveShare, BitDecomposed, FieldSimd, FieldVectorizable, + ReplicatedSecretSharing, SharedValue, Vectorizable, }, }; impl FieldSimd<32> for Fp32BitPrime {} +impl FieldSimd for Fp25519 {} + macro_rules! boolean_vector { ($dim:expr, $vec:ty) => { impl Vectorizable<$dim> for Boolean { @@ -65,6 +70,38 @@ boolean_vector!(256, BA256); /// `BitDecomposed>`. #[macro_export] macro_rules! BoolVector { - (16, 1) => { $crate::secret_sharing::replicated::semi_honest::AdditiveShare<$crate::ff::BA16> }; - ($width:expr, $dim:expr) => { BitDecomposed<$crate::secret_sharing::replicated::semi_honest::AdditiveShare<$crate::ff::boolean::Boolean, $dim>> }; + ($width:expr, $dim:expr) => { + <$crate::secret_sharing::BoolVectorLookup as $crate::secret_sharing::BoolVectorTrait< + $width, + $dim, + >>::Share + }; +} + +pub trait BoolVectorTrait { + type Share; +} + +pub struct BoolVectorLookup; + +const_assert_eq!( + MK_BITS, + 64, + "Appropriate BoolVectorTrait implementation required" +); +impl BoolVectorTrait<64, 1> for BoolVectorLookup { + type Share = AdditiveShare; +} + +const_assert_eq!( + Fp25519::BITS, + 256, + "Appropriate BoolVectorTrait implementation required" +); +impl BoolVectorTrait<256, 1> for BoolVectorLookup { + type Share = AdditiveShare; +} + +impl BoolVectorTrait for BoolVectorLookup { + type Share = BitDecomposed>; } diff --git a/ipa-core/src/secret_sharing/vector/mod.rs b/ipa-core/src/secret_sharing/vector/mod.rs index 4e4575af3..e4bb70c6e 100644 --- a/ipa-core/src/secret_sharing/vector/mod.rs +++ b/ipa-core/src/secret_sharing/vector/mod.rs @@ -54,6 +54,7 @@ mod traits; mod transpose; pub use array::StdArray; +pub use impls::{BoolVectorLookup, BoolVectorTrait}; pub use traits::{FieldArray, FieldSimd, FieldVectorizable, SharedValueArray, Vectorizable}; pub use transpose::TransposeFrom; #[cfg(feature = "enable-benches")] diff --git a/ipa-core/src/secret_sharing/vector/traits.rs b/ipa-core/src/secret_sharing/vector/traits.rs index b44316b70..91da2f2e1 100644 --- a/ipa-core/src/secret_sharing/vector/traits.rs +++ b/ipa-core/src/secret_sharing/vector/traits.rs @@ -5,7 +5,7 @@ use std::{ use crate::{ error::LengthError, - ff::Field, + ff::{Expand, Field}, protocol::prss::FromRandom, secret_sharing::{Sendable, SharedValue}, }; @@ -96,6 +96,7 @@ pub trait SharedValueArray: + for<'a> Sub<&'a Self, Output = Self> + SubAssign + for<'a> SubAssign<&'a Self> + + Expand { const ZERO_ARRAY: Self; diff --git a/ipa-core/src/secret_sharing/vector/transpose.rs b/ipa-core/src/secret_sharing/vector/transpose.rs index 020cdb9a6..d17a21b69 100644 --- a/ipa-core/src/secret_sharing/vector/transpose.rs +++ b/ipa-core/src/secret_sharing/vector/transpose.rs @@ -41,17 +41,40 @@ use std::borrow::Borrow; use std::{array, convert::Infallible}; use crate::{ + const_assert_eq, error::{LengthError, UnwrapInfallible}, ff::{ boolean::Boolean, - boolean_array::{BA16, BA256, BA64}, + boolean_array::{BA256, BA64}, + ec_prime_field::Fp25519, }, + protocol::ipa_prf::{MK_BITS, PRF_CHUNK}, secret_sharing::{ replicated::{semi_honest::AdditiveShare, ReplicatedSecretSharing}, BitDecomposed, SharedValue, StdArray, }, }; +// The following constants are hardcoded in various places throughout this file (including in type +// names like `BA256` where they cannot be substituted directly). +// +// The symbolic names are referenced in a comment adjacent to each use. +const_assert_eq!( + Fp25519::BITS, + 256, + "Appropriate transpose implementations required" +); +const_assert_eq!( + MK_BITS, + 64, + "Appropriate transpose implementations required" +); +const_assert_eq!( + PRF_CHUNK, + 64, + "Appropriate transpose implementations required" +); + /// Trait for overwriting a value with the transpose of a source value. pub trait TransposeFrom { type Error; @@ -152,26 +175,40 @@ pub fn transpose_16x16(src: &[u8; 32]) -> [u8; 32] { dst } -// Degenerate transposes. +// Degenerate transposes +// +// These can be particularly confusing, because an Mx1 matrix may be stored as a `BA{M}` rather +// than a `[Boolean; M]`. -impl TransposeFrom> for Vec> { +// Usage: Share conversion input (convert_to_fp25519 test). M = PRF_CHUNK, N = MK_BITS. +impl<'a> TransposeFrom<&'a [AdditiveShare; 1]> for AdditiveShare { type Error = Infallible; - - fn transpose_from(&mut self, src: AdditiveShare) -> Result<(), Infallible> { - *self = vec![src]; + fn transpose_from(&mut self, src: &'a [AdditiveShare; 1]) -> Result<(), Infallible> { + *self = src[0].clone(); Ok(()) } } -impl TransposeFrom>> for Vec { +// Usage: Share conversion output (r/s). M = Fp25519::BITS, N = PRF_CHUNK. +impl<'a> TransposeFrom<&'a AdditiveShare> for Vec> { type Error = Infallible; + fn transpose_from(&mut self, src: &'a AdditiveShare) -> Result<(), Infallible> { + *self = vec![src.clone()]; + Ok(()) + } +} - fn transpose_from(&mut self, src: Vec>) -> Result<(), Infallible> { +// Usage: Share conversion output (y). M = Fp25519::BITS, N = PRF_CHUNK. +impl<'a> TransposeFrom<&'a [StdArray; 256]> for Vec { + type Error = Infallible; + fn transpose_from(&mut self, src: &'a [StdArray; 256]) -> Result<(), Infallible> { *self = vec![src.iter().map(Boolean::from_array).collect::()]; Ok(()) } } +// Matrix transpose helpers + /// Perform a larger transpose using an 16x16 kernel. /// /// Matrix height and width must be multiples of 16. @@ -259,15 +296,16 @@ macro_rules! impl_transpose_ba_to_ba { }; } -impl_transpose_ba_to_ba!(BA16, BA64, 16, 64, test_transpose_ba_16x64); +// Usage: Transpose benchmark. impl_transpose_ba_to_ba!(BA64, BA64, 64, 64, test_transpose_ba_64x64); + +// Usage: Share conversion output (y). M = Fp25519::BITS, N = PRF_CHUNK. impl_transpose_ba_to_ba!(BA256, BA64, 256, 64, test_transpose_ba_256x64); -impl_transpose_ba_to_ba!(BA256, BA256, 256, 256, test_transpose_ba_256x256); /// Implement a transpose of a MxN matrix of secret-shared bits represented as /// `[AdditiveShare; ]` into a NxM bit matrix represented as `[AdditiveShare>; N]`. /// -/// For MxN = 256x64, the invocation looks like `impl_transpose_bool_to_ba!(BA256, 256, 64)`. +/// For MxN = 256x64, the invocation looks like `impl_transpose_shares_bool_to_ba!(BA256, 256, 64)`. macro_rules! impl_transpose_shares_bool_to_ba { ($dst_row:ty, $src_rows:expr, $src_cols:expr, $test_fn:ident) => { impl TransposeFrom<&[AdditiveShare; $src_rows]> @@ -355,27 +393,22 @@ macro_rules! impl_transpose_shares_bool_to_ba { }; } -impl_transpose_shares_bool_to_ba!(BA256, 256, 16, test_transpose_shares_bool_to_ba_256x16); +// Usage: Share conversion output (r/s). M = Fp25519::BITS, N = PRF_CHUNK. impl_transpose_shares_bool_to_ba!(BA256, 256, 64, test_transpose_shares_bool_to_ba_256x64); -impl_transpose_shares_bool_to_ba!(BA256, 256, 256, test_transpose_shares_bool_to_ba_256x256); -/// Implement a transpose of a MxN matrix of secret-shared bits accessed via -/// `Fn(usize) -> AdditiveShare` into a NxM bit matrix represented as `[AdditiveShare; N]`. +/// Implement a transpose of a MxN matrix of secret-shared bits represented as +/// `[AdditiveShare>; M]` into a NxM bit matrix represented as `[AdditiveShare; N]`. /// -/// For MxN = 256x64, the invocation looks like `impl_transpose_shares_ba_fn_to_bool!(BA64, 256, 64)`. -macro_rules! impl_transpose_shares_ba_fn_to_bool { +/// For MxN = 16x64, the invocation looks like `impl_transpose_shares_ba_to_bool!(BA64, 16, 64)`. +macro_rules! impl_transpose_shares_ba_to_bool { ($src_row:ty, $src_rows:expr, $src_cols:expr, $test_fn:ident) => { - // This function-based access to the source is useful when the source is not contiguous in - // memory (i.e. accessing the match key for each input record). However, it does not - // optimize as well as the other implementations (even without the dynamic dispatch). - impl TransposeFrom<&dyn Fn(usize) -> AdditiveShare<$src_row>> + impl TransposeFrom<&[AdditiveShare<$src_row>; $src_rows]> for [AdditiveShare; $src_cols] { type Error = Infallible; - fn transpose_from( &mut self, - src: &dyn Fn(usize) -> AdditiveShare<$src_row>, + src: &[AdditiveShare<$src_row>; $src_rows], ) -> Result<(), Infallible> { // Transpose left share do_transpose_16( @@ -385,7 +418,7 @@ macro_rules! impl_transpose_shares_ba_fn_to_bool { let mut d = [0u8; 32]; for k in 0..16 { d[2 * k..2 * (k + 1)].copy_from_slice( - &src(16 * i + k).left().as_raw_slice()[2 * j..2 * (j + 1)], + &src[16 * i + k].left().as_raw_slice()[2 * j..2 * (j + 1)], ); } d @@ -405,7 +438,7 @@ macro_rules! impl_transpose_shares_ba_fn_to_bool { let mut d = [0u8; 32]; for k in 0..16 { d[2 * k..2 * (k + 1)].copy_from_slice( - &src(16 * i + k).right().as_raw_slice()[2 * j..2 * (j + 1)], + &src[16 * i + k].right().as_raw_slice()[2 * j..2 * (j + 1)], ); } d @@ -421,14 +454,19 @@ macro_rules! impl_transpose_shares_ba_fn_to_bool { } } - impl TransposeFrom<&dyn Fn(usize) -> AdditiveShare<$src_row>> + #[cfg(all(test, unit_test))] + #[test] + fn $test_fn() { + tests::test_transpose_shares_ba_to_bool::<$src_row, $src_rows, $src_cols>(); + } + + impl TransposeFrom<&[AdditiveShare<$src_row>; $src_rows]> for BitDecomposed> { type Error = Infallible; - fn transpose_from( &mut self, - src: &dyn Fn(usize) -> AdditiveShare<$src_row>, + src: &[AdditiveShare<$src_row>; $src_rows], ) -> Result<(), Infallible> { self.resize($src_cols, AdditiveShare::::ZERO); let dst = @@ -440,23 +478,27 @@ macro_rules! impl_transpose_shares_ba_fn_to_bool { }; } -impl_transpose_shares_ba_fn_to_bool!(BA64, 16, 64, test_transpose_shares_ba_fn_to_bool_16x64); -impl_transpose_shares_ba_fn_to_bool!(BA64, 256, 64, test_transpose_shares_ba_fn_to_bool_256x64); +// Usage: Share conversion input (convert_to_fp25519 test). M = PRF_CHUNK, N = MK_BITS. +// Note first macro argument is `BA{N}`, not `BA{M}`. +impl_transpose_shares_ba_to_bool!(BA64, 64, 64, test_transpose_shares_ba_to_bool_64x64); -/// Implement a transpose of a MxN matrix of secret-shared bits represented as -/// `[AdditiveShare; ]` into a NxM bit matrix represented as `[AdditiveShare>; N]`. +/// Implement a transpose of a MxN matrix of secret-shared bits accessed via +/// `Fn(usize) -> AdditiveShare` into a NxM bit matrix represented as `[AdditiveShare; N]`. /// -/// For MxN = 256x64, the invocation looks like `impl_transpose_bool_to_bool!(BA64, 256, 64)`. -macro_rules! impl_transpose_shares_bool_to_bool { +/// For MxN = 256x64, the invocation looks like `impl_transpose_shares_ba_fn_to_bool!(BA64, 256, 64)`. +macro_rules! impl_transpose_shares_ba_fn_to_bool { ($src_row:ty, $src_rows:expr, $src_cols:expr, $test_fn:ident) => { - impl TransposeFrom<&[AdditiveShare; $src_rows]> + // This function-based access to the source is useful when the source is not contiguous in + // memory (i.e. accessing the match key for each input record). However, it does not + // optimize as well as the other implementations (even without the dynamic dispatch). + impl TransposeFrom<&dyn Fn(usize) -> AdditiveShare<$src_row>> for [AdditiveShare; $src_cols] { type Error = Infallible; fn transpose_from( &mut self, - src: &[AdditiveShare; $src_rows], + src: &dyn Fn(usize) -> AdditiveShare<$src_row>, ) -> Result<(), Infallible> { // Transpose left share do_transpose_16( @@ -466,7 +508,7 @@ macro_rules! impl_transpose_shares_bool_to_bool { let mut d = [0u8; 32]; for k in 0..16 { d[2 * k..2 * (k + 1)].copy_from_slice( - &src[16 * i + k].left_arr().as_raw_slice()[2 * j..2 * (j + 1)], + &src(16 * i + k).left().as_raw_slice()[2 * j..2 * (j + 1)], ); } d @@ -486,7 +528,7 @@ macro_rules! impl_transpose_shares_bool_to_bool { let mut d = [0u8; 32]; for k in 0..16 { d[2 * k..2 * (k + 1)].copy_from_slice( - &src[16 * i + k].right_arr().as_raw_slice()[2 * j..2 * (j + 1)], + &src(16 * i + k).right().as_raw_slice()[2 * j..2 * (j + 1)], ); } d @@ -505,34 +547,17 @@ macro_rules! impl_transpose_shares_bool_to_bool { #[cfg(all(test, unit_test))] #[test] fn $test_fn() { - tests::test_transpose_shares_bool_to_bool::<$src_rows, $src_cols>(); + tests::test_transpose_shares_ba_fn_to_bool::<$src_row, $src_rows, $src_cols>(); } - impl TransposeFrom<&[AdditiveShare]> - for BitDecomposed> - { - type Error = LengthError; - fn transpose_from( - &mut self, - src: &[AdditiveShare], - ) -> Result<(), LengthError> { - let src = <&[AdditiveShare; $src_rows]>::try_from(src) - .map_err(|_| LengthError { - expected: $src_rows, - actual: src.len(), - })?; - self.transpose_from(src).unwrap_infallible(); - Ok(()) - } - } - - impl TransposeFrom<&[AdditiveShare; $src_rows]> + impl TransposeFrom<&dyn Fn(usize) -> AdditiveShare<$src_row>> for BitDecomposed> { type Error = Infallible; + fn transpose_from( &mut self, - src: &[AdditiveShare; $src_rows], + src: &dyn Fn(usize) -> AdditiveShare<$src_row>, ) -> Result<(), Infallible> { self.resize($src_cols, AdditiveShare::::ZERO); let dst = @@ -544,15 +569,12 @@ macro_rules! impl_transpose_shares_bool_to_bool { }; } -impl_transpose_shares_bool_to_bool!(BA64, 16, 64, test_transpose_shares_bool_to_bool_16x64); -impl_transpose_shares_bool_to_bool!(BA64, 64, 64, test_transpose_shares_bool_to_bool_64x64); -impl_transpose_shares_bool_to_bool!(BA64, 256, 64, test_transpose_shares_bool_to_bool_256x64); +// Usage: Share conversion input (compute_prf_for_inputs). M = PRF_CHUNK, N = MK_BITS. +// Note first macro argument is `BA{N}`, not `BA{M}`. +impl_transpose_shares_ba_fn_to_bool!(BA64, 64, 64, test_transpose_shares_ba_fn_to_bool_64x64); #[cfg(all(test, unit_test))] mod tests { - // Using `.enumerate()` would just obfuscate the nested for loops verifying transposes. - #![allow(clippy::needless_range_loop)] - use std::{ cmp::min, fmt::Debug, @@ -626,6 +648,19 @@ mod tests { impl_byte_conversion!([u32; 32], [u8; 128]); impl_byte_conversion!([u64; 64], [u8; 512]); + fn verify_transpose(src_rows: usize, src_cols: usize, transposed: F1, original: F2) + where + T: PartialEq + Debug, + F1: Fn(usize, usize) -> T, + F2: Fn(usize, usize) -> T, + { + for i in 0..src_cols { + for j in 0..src_rows { + assert_eq!(transposed(i, j), original(j, i)); + } + } + } + fn test_transpose_array< T, // Matrix integer type (e.g. u16 for 16x16) const N: usize, // Matrix dimension @@ -667,11 +702,7 @@ mod tests { let m = <[T; N]>::from_bytes(m); let m_t = <[T; N]>::from_bytes(m_t); - for i in 0..N { - for j in 0..N { - assert_eq!((m_t[i] >> j) & one, (m[j] >> i) & one); - } - } + verify_transpose(N, N, |i, j| (m_t[i] >> j) & one, |i, j| (m[i] >> j) & one); } #[test] @@ -684,6 +715,48 @@ mod tests { test_transpose_array::(super::transpose_16x16); } + fn ba_shares_test_matrix( + step: usize, + ) -> [AdditiveShare; M] + where + BA: SharedValue + FromIterator + Vectorizable<1, Array = StdArray>, + { + array::from_fn(|i| { + let mut left = vec![Boolean::FALSE; N]; + let mut right = vec![Boolean::FALSE; N]; + for j in ((i % N)..N).step_by(step) { + let b = Boolean::from(j % 2 != 0); + left[j] = b; + right[j] = !b; + } + AdditiveShare::new_arr( + BA::from_iter(left).into_array(), + BA::from_iter(right).into_array(), + ) + }) + } + + fn bool_shares_test_matrix( + step: usize, + ) -> [AdditiveShare; M] + where + Boolean: Vectorizable, + { + array::from_fn(|i| { + let mut left = vec![Boolean::FALSE; N]; + let mut right = vec![Boolean::FALSE; N]; + for j in ((i % N)..N).step_by(step) { + let b = Boolean::from(j % 2 != 0); + left[j] = b; + right[j] = !b; + } + AdditiveShare::new_arr( + >::Array::from_iter(left), + >::Array::from_iter(right), + ) + }) + } + // The order of type parameters matches the implementation macro: BA, BA, , pub(super) fn test_transpose_ba_to_ba< DR, // Destination row type @@ -727,91 +800,67 @@ mod tests { let m = repeat_with(|| rng.gen()).take(SM).collect::>(); let m_t = t_impl(<&[SR; SM]>::try_from(m.as_slice()).unwrap()); - for i in 0..DM { - for j in 0..SM { - assert_eq!(m_t[i].get(j), m[j].get(i)); - } - } + verify_transpose(SM, DM, |i, j| m_t[i].get(j), |i, j| m[i].get(j)); } - // The order of type parameters matches the implementation macro: BA, , - pub(super) fn test_transpose_shares_bool_to_ba< - DR, // Destination row type + // The order of type parameters matches the implementation macro: BA, , + pub(super) fn test_transpose_shares_ba_to_bool< + SR, // Source row type const SM: usize, // Source rows (== dest cols) const DM: usize, // Destination rows (== source cols) >() where - Boolean: Vectorizable, - >::Array: ArrayAccess, - DR: SharedValue + ArrayAccess, - [AdditiveShare; DM]: - for<'a> TransposeFrom<&'a [AdditiveShare; SM], Error = Infallible>, + Boolean: Vectorizable, + >::Array: ArrayAccess, + SR: SharedValue + + ArrayAccess + + FromIterator + + Vectorizable<1, Array = StdArray>, + [AdditiveShare; DM]: + for<'a> TransposeFrom<&'a [AdditiveShare; SM], Error = Infallible>, + Standard: Distribution, { let t_impl = |src| { - let mut dst = [AdditiveShare::::ZERO; DM]; + let mut dst = [AdditiveShare::::ZERO; DM]; dst.transpose_from(src).unwrap_infallible(); dst }; let step = min(SM, DM); - let m = array::from_fn(|i| { - let mut left = vec![Boolean::FALSE; DM]; - let mut right = vec![Boolean::FALSE; DM]; - for j in ((i % DM)..DM).step_by(step) { - let b = Boolean::from(j % 2 != 0); - left[j] = b; - right[j] = !b; - } - AdditiveShare::new_arr( - >::Array::from_iter(left), - >::Array::from_iter(right), - ) - }); + let m = ba_shares_test_matrix::(step); let m_t = t_impl(&m); - assert_eq!( - m_t, - array::from_fn(|i| { - let mut v = AdditiveShare::::ZERO; - for j in ((i % SM)..SM).step_by(step) { - let b = Boolean::from(j % 2 != 0); - v.set(j, AdditiveShare::new(b, !b)); - } - v - }) - ); + assert_eq!(m_t, bool_shares_test_matrix::(step)); let mut left_rng = thread_rng(); let mut right_rng = thread_rng(); let m = repeat_with(|| AdditiveShare::from_fns(|_| left_rng.gen(), |_| right_rng.gen())) .take(SM) .collect::>(); - let m_t = t_impl(<&[AdditiveShare; SM]>::try_from(m.as_slice()).unwrap()); + let m_t = t_impl(<&[AdditiveShare; SM]>::try_from(m.as_slice()).unwrap()); - for i in 0..DM { - for j in 0..SM { - assert_eq!( - m_t[i].get(j).unwrap().left(), - m[j].left_arr().get(i).unwrap() - ); - assert_eq!( - m_t[i].get(j).unwrap().right(), - m[j].right_arr().get(i).unwrap() - ); - } - } + #[rustfmt::skip] + verify_transpose(SM, DM, + |i, j| (m_t[i].left_arr().get(j).unwrap(), m_t[i].right_arr().get(j).unwrap()), + |i, j| (m[i].get(j).unwrap().left(), m[i].get(j).unwrap().right()), + ); } - pub(super) fn test_transpose_shares_bool_to_bool< + // The order of type parameters matches the implementation macro: BA, , + pub(super) fn test_transpose_shares_ba_fn_to_bool< + SR, // Source row type const SM: usize, // Source rows (== dest cols) const DM: usize, // Destination rows (== source cols) >() where - Boolean: Vectorizable, - >::Array: ArrayAccess, Boolean: Vectorizable, >::Array: ArrayAccess, + SR: SharedValue + + ArrayAccess + + FromIterator + + Vectorizable<1, Array = StdArray>, [AdditiveShare; DM]: - for<'a> TransposeFrom<&'a [AdditiveShare; SM], Error = Infallible>, + for<'a> TransposeFrom<&'a dyn Fn(usize) -> AdditiveShare, Error = Infallible>, + Standard: Distribution, { let t_impl = |src| { let mut dst = [AdditiveShare::::ZERO; DM]; @@ -820,36 +869,52 @@ mod tests { }; let step = min(SM, DM); - let m = array::from_fn(|i| { - let mut left = vec![Boolean::FALSE; DM]; - let mut right = vec![Boolean::FALSE; DM]; - for j in ((i % DM)..DM).step_by(step) { - let b = Boolean::from(j % 2 != 0); - left[j] = b; - right[j] = !b; - } - AdditiveShare::new_arr( - >::Array::from_iter(left), - >::Array::from_iter(right), - ) - }); - let m_t = t_impl(&m); - assert_eq!( - m_t, - array::from_fn(|i| { - let mut left = vec![Boolean::FALSE; SM]; - let mut right = vec![Boolean::FALSE; SM]; - for j in ((i % SM)..SM).step_by(step) { - let b = Boolean::from(j % 2 != 0); - left[j] = b; - right[j] = !b; - } - AdditiveShare::new_arr( - >::Array::from_iter(left), - >::Array::from_iter(right), - ) - }) + let m = ba_shares_test_matrix::(step); + let m_func = |i| AdditiveShare::::clone(&m[i]); + let m_t = t_impl(&m_func); + assert_eq!(m_t, bool_shares_test_matrix::(step)); + + let mut left_rng = thread_rng(); + let mut right_rng = thread_rng(); + let m = repeat_with(|| AdditiveShare::from_fns(|_| left_rng.gen(), |_| right_rng.gen())) + .take(SM) + .collect::>(); + let m_func = |i| AdditiveShare::::clone(&m[i]); + let m_t = t_impl(&m_func); + + #[rustfmt::skip] + verify_transpose(SM, DM, + |i, j| (m_t[i].left_arr().get(j).unwrap(), m_t[i].right_arr().get(j).unwrap()), + |i, j| (m[i].get(j).unwrap().left(), m[i].get(j).unwrap().right()), ); + } + + // The order of type parameters matches the implementation macro: BA, , + pub(super) fn test_transpose_shares_bool_to_ba< + DR, // Destination row type + const SM: usize, // Source rows (== dest cols) + const DM: usize, // Destination rows (== source cols) + >() + where + Boolean: Vectorizable, + >::Array: ArrayAccess, + DR: SharedValue + + ArrayAccess + + FromIterator + + Vectorizable<1, Array = StdArray>, + [AdditiveShare; DM]: + for<'a> TransposeFrom<&'a [AdditiveShare; SM], Error = Infallible>, + { + let t_impl = |src| { + let mut dst = [AdditiveShare::::ZERO; DM]; + dst.transpose_from(src).unwrap_infallible(); + dst + }; + + let step = min(SM, DM); + let m = bool_shares_test_matrix::(step); + let m_t = t_impl(&m); + assert_eq!(m_t, ba_shares_test_matrix::(step)); let mut left_rng = thread_rng(); let mut right_rng = thread_rng(); @@ -858,17 +923,10 @@ mod tests { .collect::>(); let m_t = t_impl(<&[AdditiveShare; SM]>::try_from(m.as_slice()).unwrap()); - for i in 0..DM { - for j in 0..SM { - assert_eq!( - m_t[i].left_arr().get(j).unwrap(), - m[j].left_arr().get(i).unwrap() - ); - assert_eq!( - m_t[i].right_arr().get(j).unwrap(), - m[j].right_arr().get(i).unwrap() - ); - } - } + #[rustfmt::skip] + verify_transpose(SM, DM, + |i, j| (m_t[i].get(j).unwrap().left(), m_t[i].get(j).unwrap().right()), + |i, j| (m[i].left_arr().get(j).unwrap(), m[i].right_arr().get(j).unwrap()), + ); } }