arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
add more comments in traits inside rgdw/runtime
Janmajaya Mall janmajayamall@protonmail.com
Sat, 29 Jun 2024 20:11:49 +0530
commit

f5f3700ea425effd07574db77c172034313814be

parent

bc02262f9d9ec022cf9b37e41a2e3493f46c54ba

2 files changed, 98 insertions(+), 68 deletions(-)

jump to
M src/bool/parameters.rs → src/bool/parameters.rs

@@ -69,19 +69,6 @@ self.1

} } -// impl DecomposerParams for (DecompostionLogBase, (DecompositionCount)) { -// type Base = DecompostionLogBase; -// type Count = DecompositionCount; - -// fn decomposition_base(&self) -> Self::Base { -// self.0 -// } - -// fn decomposition_count(&self) -> Self::Count { -// self.1 -// } -// } - #[derive(Clone, PartialEq, Debug)] pub(crate) enum ParameterVariant { SingleParty,
M src/rgsw/runtime.rs → src/rgsw/runtime.rs

@@ -30,15 +30,22 @@ ///

/// RGSW is a collection of RLWE' ciphertext which are collection degree 1 of /// RLWE ciphertexts /// -/// Let -/// RGSW = [RLWE'(-sm) || RLW'(m)] = [RW] +/// RGSW = [RLWE'(-sm) || RLWE'(m)] +/// +/// As usual we refer to decomposition count for RLWE_A in RLWE x RGSW +/// multiplicaiton as `d_a` and decomposition count for RLWE_B in RLWE x RGDW +/// multiplication as `d_b`. pub(crate) trait RgswCiphertext { type R: Row; + /// Splits RGSW ciphertext and returns references: + /// (RLWE'_A(-sm), RLWE'_B(-sm)), (RLWE'_A(m), RLWE'_B(m)) fn split(&self) -> ((&[Self::R], &[Self::R]), (&[Self::R], &[Self::R])); } pub(crate) trait RgswCiphertextMut: RgswCiphertext { + /// Splits RGSW ciphertext and returns mutable references: + /// (RLWE'_A(-sm), RLWE'_B(-sm)), (RLWE'_A(m), RLWE'_B(m)) fn split_mut( &mut self, ) -> (

@@ -47,6 +54,75 @@ (&mut [Self::R], &mut [Self::R]),

); } +/// RLWE Key switching Key +/// +/// Key switching key from s' -> s consists of multiple RLWE cipheretxts. +/// For gadget vector: [1, beta, ..., beta^{d-1}] +/// RLWE'_{s}(-s'm) = [RWLE_{s}(-s'm), ..., RLWE_{s}(beta^{d-1} -s'm)] +pub(crate) trait RlweKsk { + type R: Row; + /// Returns reference to RLWE'_A(-s'm) polynomials + fn ksk_part_a(&self) -> &[Self::R]; + /// Returns reference to RLWE'_B(-s'm) polynomials + fn ksk_part_b(&self) -> &[Self::R]; +} + +/// Scratch matrix used in several rlwe/rgsw runtime operations +pub(crate) trait RuntimeScratchMatrix { + type R: RowMut; + type Rgsw: RgswCiphertext; + + /// Returns scratch matrix for RLWE automorphism (not trivial case) + /// + /// RLWE auto requires scratch matric to store decomposed polynomials + 1 + /// rlwe ciphertext temporarily. + /// + /// For example, if Auto decomposer has decompostion count `d` then the + /// scratch matrix must have dimension (d + 2, N) where N is the ring size. + fn scratch_for_rlwe_auto_and_zero_rlwe_space( + &mut self, + decompostion_count: usize, + ) -> (&mut [Self::R], &mut [Self::R]); + + /// Returns scratch matrix for RLWE automorphism (trivial case) + /// + /// We refer to cases where RLWE(m) = [0, b] s.t. m = b as trivial cases. In + /// such a case a single row of length N, N being the ring dimension, is + /// required as scratch buffer to store automorphism of polynomial `b` + /// temporarily. + fn scratch_for_rlwe_auto_trivial_case(&mut self) -> &mut Self::R; + + /// Returns scratch matrix + zeroed RLWE ciphertext space for + /// RLWE x RGSW + /// + /// RLWE x RGSW product requires scratch space to store decomposed + /// polynomials for both cases: (1) SignedDecompose(RLWE_A) x RLWE'(-sm) and + /// (2) SignedDecompose(RLWE_B) x RLWE'(m). Hence, scratch space returned to + /// store decomposed polynomials must have MAX(d_a, d_b) rows. + /// + /// Additional scratch space is required to store 1 RLWE ciphertext + /// temporarily. The space must be zeroed. + fn scratch_for_rlwe_x_rgsw_and_zero_rlwe_space<D: RlweDecomposer>( + &mut self, + decomposer: &D, + ) -> (&mut [Self::R], &mut [Self::R]); + + /// Returns scracth matrix + zeroed RGSW ciphertext space for RGSW0 x RGSW1 + /// + /// RGSW0 x RGSW1 requires `d_{0,a} + d_{0,b}` RLWE x RGSW1 products where + /// d_{0, a/b} are decomposition counts corresponding to decmposer used for + /// RGSW0. Hence, scratch space required to store decomposed polynomial for + /// RLWE x RGSW1 product should have MAX(d_{1, a}, d_{1, b}) rows. + /// + /// Additional scravth space is required to store RGSW0 ciphertext + /// temporarily. The space must be zeroed. + fn scratch_for_rgsw_x_rgsw_and_zero_rgsw0_space<D: RlweDecomposer>( + &mut self, + d0: &D, + d1: &D, + ) -> (&mut [Self::R], &mut [Self::R]); +} + pub(crate) struct RlweCiphertextMutRef<'a, R> { data: &'a mut [R], }

@@ -154,12 +230,6 @@ )

} } -pub(crate) trait RlweKsk { - type R: Row; - fn ksk_part_a(&self) -> &[Self::R]; - fn ksk_part_b(&self) -> &[Self::R]; -} - pub(crate) struct RlweKskRef<'a, R> { data: &'a [R], decomposition_count: usize,

@@ -185,29 +255,6 @@ &self.data[self.decomposition_count..]

} } -pub(crate) trait RlweAutoScratch { - type R: RowMut; - type Rgsw: RgswCiphertext; - - fn split_for_rlwe_auto_and_zero_rlwe_space( - &mut self, - decompostion_count: usize, - ) -> (&mut [Self::R], &mut [Self::R]); - - fn split_for_rlwe_auto_trivial_case(&mut self) -> &mut Self::R; - - fn split_for_rlwe_x_rgsw_and_zero_rlwe_space<D: RlweDecomposer>( - &mut self, - decomposer: &D, - ) -> (&mut [Self::R], &mut [Self::R]); - - fn split_for_rgsw_x_rgsw_and_zero_rgsw0_space<D: RlweDecomposer>( - &mut self, - d0: &D, - d1: &D, - ) -> (&mut [Self::R], &mut [Self::R]); -} - pub(crate) struct RuntimeScratchMutRef<'a, R> { data: &'a mut [R], }

@@ -218,14 +265,14 @@ Self { data }

} } -impl<'a, R: RowMut> RlweAutoScratch for RuntimeScratchMutRef<'a, R> +impl<'a, R: RowMut> RuntimeScratchMatrix for RuntimeScratchMutRef<'a, R> where R::Element: Zero + Clone, { type R = R; type Rgsw = RgswCiphertextRef<'a, R>; - fn split_for_rlwe_auto_and_zero_rlwe_space( + fn scratch_for_rlwe_auto_and_zero_rlwe_space( &mut self, decompostion_count: usize, ) -> (&mut [Self::R], &mut [Self::R]) {

@@ -239,11 +286,11 @@

(decomp_poly, rlwe) } - fn split_for_rlwe_auto_trivial_case(&mut self) -> &mut Self::R { + fn scratch_for_rlwe_auto_trivial_case(&mut self) -> &mut Self::R { &mut self.data[0] } - fn split_for_rgsw_x_rgsw_and_zero_rgsw0_space<D: RlweDecomposer>( + fn scratch_for_rgsw_x_rgsw_and_zero_rgsw0_space<D: RlweDecomposer>( &mut self, rgsw0_decoposer: &D, rgsw1_decoposer: &D,

@@ -264,7 +311,7 @@

(decomp_poly, rgsw) } - fn split_for_rlwe_x_rgsw_and_zero_rlwe_space<D: RlweDecomposer>( + fn scratch_for_rlwe_x_rgsw_and_zero_rlwe_space<D: RlweDecomposer>( &mut self, decomposer: &D, ) -> (&mut [Self::R], &mut [Self::R]) {

@@ -283,6 +330,7 @@ (decomp_poly, rlwe)

} } +/// Returns no. of rows in scratch space for RGSW0 x RGSW1 product pub(crate) fn rgsw_x_rgsw_scratch_rows<D: RlweDecomposer>( rgsw0_decomposer: &D, rgsw1_decomposer: &D,

@@ -294,13 +342,14 @@ ) + rgsw0_decomposer.a().decomposition_count() * 2

+ rgsw0_decomposer.b().decomposition_count() * 2 } +/// Returns no. of rows in scratch space for RLWE x RGSW product pub(crate) fn rlwe_x_rgsw_scratch_rows<D: RlweDecomposer>(rgsw_decomposer: &D) -> usize { std::cmp::max( rgsw_decomposer.a().decomposition_count(), rgsw_decomposer.b().decomposition_count(), ) + 2 } - +/// Returns no. of rows in scratch space for RLWE auto pub(crate) fn rlwe_auto_scratch_rows<D: Decomposer>(decomposer: &D) -> usize { decomposer.decomposition_count() + 2 }

@@ -357,7 +406,7 @@ /// store decomposed polynomials nad 2 rows to store out RLWE temporarily.

pub(crate) fn rlwe_auto< Rlwe: RlweCiphertext, Ksk: RlweKsk<R = Rlwe::R>, - Sc: RlweAutoScratch<R = Rlwe::R>, + Sc: RuntimeScratchMatrix<R = Rlwe::R>, ModOp: ArithmeticOps<Element = <Rlwe::R as Row>::Element> + VectorOps<Element = <Rlwe::R as Row>::Element>, NttOp: Ntt<Element = <Rlwe::R as Row>::Element>,

@@ -381,7 +430,7 @@ // assert!(scratch_matrix.fits(d + 2, ring_size));

if !is_trivial { let (decomp_poly_scratch, tmp_rlwe) = scratch_matrix - .split_for_rlwe_auto_and_zero_rlwe_space(decomposer.decomposition_count()); + .scratch_for_rlwe_auto_and_zero_rlwe_space(decomposer.decomposition_count()); let mut tmp_rlwe = RlweCiphertextMutRef::new(tmp_rlwe); // send a(X) -> a(X^k) and decompose a(X^k)

@@ -449,7 +498,7 @@ rlwe_in.part_b_mut().copy_from_slice(tmp_rlwe.part_b());

} else { // RLWE is trivial, a(X) is 0. // send b(X) -> b(X^k) - let tmp_row = scratch_matrix.split_for_rlwe_auto_trivial_case(); + let tmp_row = scratch_matrix.scratch_for_rlwe_auto_trivial_case(); izip!( rlwe_in.part_b(), auto_map_index.iter(),

@@ -475,7 +524,7 @@ /// `ksk_shoup`, of the polynomials in evaluation domain is also supplied.

pub(crate) fn rlwe_auto_shoup< Rlwe: RlweCiphertext, Ksk: RlweKsk<R = Rlwe::R>, - Sc: RlweAutoScratch<R = Rlwe::R>, + Sc: RuntimeScratchMatrix<R = Rlwe::R>, ModOp: ArithmeticOps<Element = <Rlwe::R as Row>::Element> // + VectorOps<Element = MT::MatElement> + ShoupMatrixFMA<Rlwe::R>,

@@ -502,7 +551,7 @@ // assert!(scratch_matrix.fits(d + 2, ring_size));

if !is_trivial { let (decomp_poly_scratch, tmp_rlwe) = scratch_matrix - .split_for_rlwe_auto_and_zero_rlwe_space(decomposer.decomposition_count()); + .scratch_for_rlwe_auto_and_zero_rlwe_space(decomposer.decomposition_count()); let mut tmp_rlwe = RlweCiphertextMutRef::new(tmp_rlwe); // send a(X) -> a(X^k) and decompose a(X^k)

@@ -570,7 +619,7 @@ rlwe_in.part_b_mut().copy_from_slice(tmp_rlwe.part_b());

} else { // RLWE is trivial, a(X) is 0. // send b(X) -> b(X^k) - let row = scratch_matrix.split_for_rlwe_auto_trivial_case(); + let row = scratch_matrix.scratch_for_rlwe_auto_trivial_case(); izip!( rlwe_in.part_b(), auto_map_index.iter(),

@@ -596,7 +645,7 @@ /// It's used to store decomposed polynomials and out RLWE temporarily

pub(crate) fn rlwe_by_rgsw< Rlwe: RlweCiphertext, Rgsw: RgswCiphertext<R = Rlwe::R>, - Sc: RlweAutoScratch<R = Rlwe::R>, + Sc: RuntimeScratchMatrix<R = Rlwe::R>, D: RlweDecomposer<Element = <Rlwe::R as Row>::Element>, ModOp: VectorOps<Element = <Rlwe::R as Row>::Element>, NttOp: Ntt<Element = <Rlwe::R as Row>::Element>,

@@ -620,7 +669,7 @@ let ((rlwe_dash_nsm_parta, rlwe_dash_nsm_partb), (rlwe_dash_m_parta, rlwe_dash_m_partb)) =

rgsw_in.split(); let (decomposed_poly_scratch, tmp_rlwe) = - scratch_matrix.split_for_rlwe_x_rgsw_and_zero_rlwe_space(decomposer); + scratch_matrix.scratch_for_rlwe_x_rgsw_and_zero_rlwe_space(decomposer); // RLWE_in = a_in, b_in; RLWE_out = a_out, b_out if !is_trivial {

@@ -699,7 +748,7 @@ /// evaluation domain, `rgsw_in_shoup`, is also supplied.

pub(crate) fn rlwe_by_rgsw_shoup< Rlwe: RlweCiphertext, Rgsw: RgswCiphertext<R = Rlwe::R>, - Sc: RlweAutoScratch<R = Rlwe::R>, + Sc: RuntimeScratchMatrix<R = Rlwe::R>, D: RlweDecomposer<Element = <Rlwe::R as Row>::Element>, ModOp: ShoupMatrixFMA<Rlwe::R>, NttOp: Ntt<Element = <Rlwe::R as Row>::Element>,

@@ -729,7 +778,7 @@ (rlwe_dash_m_parta_shoup, rlwe_dash_m_partb_shoup),

) = rgsw_in_shoup.split(); let (decomposed_poly_scratch, tmp_rlwe) = - scratch_matrix.split_for_rlwe_x_rgsw_and_zero_rlwe_space(decomposer); + scratch_matrix.scratch_for_rlwe_x_rgsw_and_zero_rlwe_space(decomposer); // RLWE_in = a_in, b_in; RLWE_out = a_out, b_out if !is_trivial {

@@ -828,7 +877,7 @@ /// - rgsw_1_eval: RGSW(m1) in evaluation domain

pub(crate) fn rgsw_by_rgsw_inplace< Rgsw: RgswCiphertext, RgswMut: RgswCiphertextMut<R = Rgsw::R>, - Sc: RlweAutoScratch<R = Rgsw::R, Rgsw = Rgsw>, + Sc: RuntimeScratchMatrix<R = Rgsw::R, Rgsw = Rgsw>, D: RlweDecomposer<Element = <Rgsw::R as Row>::Element>, ModOp: VectorOps<Element = <Rgsw::R as Row>::Element>, NttOp: Ntt<Element = <Rgsw::R as Row>::Element>,

@@ -846,14 +895,8 @@ RgswMut: AsMut<[Rgsw::R]>,

RgswMut::R: RowMut, // Rgsw: AsRef<[Rgsw::R]>, { - // let rgsw0_rows = rgsw0_da * 2 + rgsw0_db * 2; - // let ring_size = rgsw0.dimension().1; - // assert!(rgsw0.dimension().0 == rgsw0_rows); - // assert!(rgsw1_eval.dimension() == (rgsw1_rows, ring_size)); - // assert!(scratch_matrix.fits(max_d + rgsw0_rows, ring_size)); - let (decomp_r_space, rgsw_space) = scratch_matrix - .split_for_rgsw_x_rgsw_and_zero_rgsw0_space(rgsw0_decomposer, rgsw1_decomposer); + .scratch_for_rgsw_x_rgsw_and_zero_rgsw0_space(rgsw0_decomposer, rgsw1_decomposer); let mut rgsw_space = RgswCiphertextMutRef::new( rgsw_space,