From 820fced615459bc05eebe8f8a03059a89728526d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bossuat Date: Fri, 15 Sep 2023 17:49:19 +0200 Subject: [PATCH] [circuits/float]: improved bootstrapper API --- circuits/float/bootstrapper/bootstrapper.go | 36 +++++++++---------- .../float/bootstrapper/bootstrapping_test.go | 8 ++--- circuits/float/bootstrapper/utils.go | 22 ++++++------ examples/ckks/bootstrapping/basic/main.go | 2 +- 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/circuits/float/bootstrapper/bootstrapper.go b/circuits/float/bootstrapper/bootstrapper.go index cad8a401..945bb4b4 100644 --- a/circuits/float/bootstrapper/bootstrapper.go +++ b/circuits/float/bootstrapper/bootstrapper.go @@ -15,13 +15,10 @@ import ( ) type Bootstrapper struct { + Parameters bridge ckks.DomainSwitcher bootstrapper *bootstrapping.Bootstrapper - paramsN1 ckks.Parameters - paramsN2 ckks.Parameters - btpParamsN2 bootstrapping.Parameters - xPow2N1 []ring.Poly xPow2InvN1 []ring.Poly xPow2N2 []ring.Poly @@ -30,11 +27,12 @@ type Bootstrapper struct { evk *BootstrappingKeys } -func NewBootstrapper(paramsN1 ckks.Parameters, btpParamsN2 Parameters, evk *BootstrappingKeys) (*Bootstrapper, error) { +func NewBootstrapper(btpParams Parameters, evk *BootstrappingKeys) (*Bootstrapper, error) { b := &Bootstrapper{} - paramsN2 := btpParamsN2.Parameters.Parameters + paramsN1 := btpParams.ResidualParameters + paramsN2 := btpParams.Parameters.Parameters switch paramsN1.RingType() { case ring.Standard: @@ -52,27 +50,25 @@ func NewBootstrapper(paramsN1 ckks.Parameters, btpParamsN2 Parameters, evk *Boot } // The switch to standard to conjugate invariant multiplies the scale by 2 - btpParamsN2.SlotsToCoeffsParameters.Scaling = new(big.Float).SetFloat64(0.5) + btpParams.SlotsToCoeffsParameters.Scaling = new(big.Float).SetFloat64(0.5) } - b.paramsN1 = paramsN1 - b.paramsN2 = paramsN2 - b.btpParamsN2 = btpParamsN2.Parameters + b.Parameters = btpParams b.evk = evk - b.xPow2N2 = rlwe.GenXPow2(b.paramsN2.RingQ().AtLevel(0), b.paramsN2.LogN(), false) - b.xPow2InvN2 = rlwe.GenXPow2(b.paramsN2.RingQ(), b.paramsN2.LogN(), true) + b.xPow2N2 = rlwe.GenXPow2(paramsN2.RingQ().AtLevel(0), paramsN2.LogN(), false) + b.xPow2InvN2 = rlwe.GenXPow2(paramsN2.RingQ(), paramsN2.LogN(), true) - if paramsN1.N() != b.paramsN2.N() { + if paramsN1.N() != paramsN2.N() { b.xPow2N1 = b.xPow2N2 b.xPow2InvN1 = b.xPow2InvN2 } else { - b.xPow2N1 = rlwe.GenXPow2(b.paramsN1.RingQ().AtLevel(0), b.paramsN2.LogN(), false) - b.xPow2InvN1 = rlwe.GenXPow2(b.paramsN1.RingQ(), b.paramsN2.LogN(), true) + b.xPow2N1 = rlwe.GenXPow2(paramsN1.RingQ().AtLevel(0), paramsN2.LogN(), false) + b.xPow2InvN1 = rlwe.GenXPow2(paramsN1.RingQ(), paramsN2.LogN(), true) } var err error - if b.bootstrapper, err = bootstrapping.NewBootstrapper(btpParamsN2.Parameters, evk.EvkBootstrapping); err != nil { + if b.bootstrapper, err = bootstrapping.NewBootstrapper(btpParams.Parameters, evk.EvkBootstrapping); err != nil { return nil, err } @@ -80,11 +76,11 @@ func NewBootstrapper(paramsN1 ckks.Parameters, btpParamsN2 Parameters, evk *Boot } func (b Bootstrapper) Depth() int { - return b.btpParamsN2.SlotsToCoeffsParameters.Depth(true) + b.btpParamsN2.Mod1ParametersLiteral.Depth() + b.btpParamsN2.CoeffsToSlotsParameters.Depth(true) + return b.Parameters.Parameters.MaxLevel() - b.ResidualParameters.MaxLevel() } func (b Bootstrapper) OutputLevel() int { - return b.paramsN2.MaxLevel() - b.Depth() + return b.ResidualParameters.MaxLevel() } func (b Bootstrapper) MinimumInputLevel() int { @@ -104,7 +100,7 @@ func (b Bootstrapper) BootstrapMany(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphertext, var err error - switch b.paramsN1.RingType() { + switch b.ResidualParameters.RingType() { case ring.ConjugateInvariant: for i := 0; i < len(cts); i = i + 2 { @@ -154,7 +150,7 @@ func (b Bootstrapper) BootstrapMany(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphertext, runtime.GC() for i := range cts { - cts[i].Scale = b.paramsN1.DefaultScale() + cts[i].Scale = b.ResidualParameters.DefaultScale() } return cts, err diff --git a/circuits/float/bootstrapper/bootstrapping_test.go b/circuits/float/bootstrapper/bootstrapping_test.go index ff489a6e..4f008370 100644 --- a/circuits/float/bootstrapper/bootstrapping_test.go +++ b/circuits/float/bootstrapper/bootstrapping_test.go @@ -62,7 +62,7 @@ func TestBootstrapping(t *testing.T) { btpKeys, err := btpParams.GenBootstrappingKeys(sk) require.NoError(t, err) - bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys) + bootstrapper, err := NewBootstrapper(btpParams, btpKeys) require.NoError(t, err) ecd := ckks.NewEncoder(params) @@ -142,7 +142,7 @@ func TestBootstrapping(t *testing.T) { btpKeys, err := btpParams.GenBootstrappingKeys(sk) require.Nil(t, err) - bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys) + bootstrapper, err := NewBootstrapper(btpParams, btpKeys) require.Nil(t, err) ecd := ckks.NewEncoder(params) @@ -225,7 +225,7 @@ func TestBootstrapping(t *testing.T) { btpKeys, err := btpParams.GenBootstrappingKeys(sk) require.Nil(t, err) - bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys) + bootstrapper, err := NewBootstrapper(btpParams, btpKeys) require.Nil(t, err) ecd := ckks.NewEncoder(params) @@ -305,7 +305,7 @@ func TestBootstrapping(t *testing.T) { btpKeys, err := btpParams.GenBootstrappingKeys(sk) require.Nil(t, err) - bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys) + bootstrapper, err := NewBootstrapper(btpParams, btpKeys) require.Nil(t, err) ecd := ckks.NewEncoder(params) diff --git a/circuits/float/bootstrapper/utils.go b/circuits/float/bootstrapper/utils.go index cba7ebff..9d63d378 100644 --- a/circuits/float/bootstrapper/utils.go +++ b/circuits/float/bootstrapper/utils.go @@ -12,8 +12,8 @@ import ( func (b Bootstrapper) SwitchRingDegreeN1ToN2New(ctN1 *rlwe.Ciphertext) (ctN2 *rlwe.Ciphertext) { - if ctN1.Value[0].N() < b.paramsN2.N() { - ctN2 = ckks.NewCiphertext(b.paramsN2, 1, ctN1.Level()) + if ctN1.Value[0].N() < b.Parameters.Parameters.Parameters.N() { + ctN2 = ckks.NewCiphertext(b.Parameters.Parameters.Parameters, 1, ctN1.Level()) if err := b.bootstrapper.ApplyEvaluationKey(ctN1, b.evk.EvkN1ToN2, ctN2); err != nil { panic(err) } @@ -26,8 +26,8 @@ func (b Bootstrapper) SwitchRingDegreeN1ToN2New(ctN1 *rlwe.Ciphertext) (ctN2 *rl func (b Bootstrapper) SwitchRingDegreeN2ToN1New(ctN2 *rlwe.Ciphertext) (ctN1 *rlwe.Ciphertext) { - if ctN2.Value[0].N() > b.paramsN1.N() { - ctN1 = ckks.NewCiphertext(b.paramsN1, 1, ctN2.Level()) + if ctN2.Value[0].N() > b.ResidualParameters.N() { + ctN1 = ckks.NewCiphertext(b.ResidualParameters, 1, ctN2.Level()) if err := b.bootstrapper.ApplyEvaluationKey(ctN2, b.evk.EvkN2ToN1, ctN1); err != nil { panic(err) } @@ -39,7 +39,7 @@ func (b Bootstrapper) SwitchRingDegreeN2ToN1New(ctN2 *rlwe.Ciphertext) (ctN1 *rl } func (b Bootstrapper) ComplexToRealNew(ctCmplx *rlwe.Ciphertext) (ctReal *rlwe.Ciphertext) { - ctReal = ckks.NewCiphertext(b.paramsN1, 1, ctCmplx.Level()) + ctReal = ckks.NewCiphertext(b.ResidualParameters, 1, ctCmplx.Level()) if err := b.bridge.ComplexToReal(b.bootstrapper.Evaluator, ctCmplx, ctReal); err != nil { panic(err) } @@ -47,7 +47,7 @@ func (b Bootstrapper) ComplexToRealNew(ctCmplx *rlwe.Ciphertext) (ctReal *rlwe.C } func (b Bootstrapper) RealToComplexNew(ctReal *rlwe.Ciphertext) (ctCmplx *rlwe.Ciphertext) { - ctCmplx = ckks.NewCiphertext(b.paramsN2, 1, ctReal.Level()) + ctCmplx = ckks.NewCiphertext(b.Parameters.Parameters.Parameters, 1, ctReal.Level()) if err := b.bridge.RealToComplex(b.bootstrapper.Evaluator, ctReal, ctCmplx); err != nil { panic(err) } @@ -58,8 +58,8 @@ func (b Bootstrapper) PackAndSwitchN1ToN2(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphe var err error - if b.paramsN1.N() != b.paramsN2.N() { - if cts, err = b.Pack(cts, b.paramsN1, b.xPow2N1); err != nil { + if b.ResidualParameters.N() != b.Parameters.Parameters.Parameters.N() { + if cts, err = b.Pack(cts, b.ResidualParameters, b.xPow2N1); err != nil { return nil, fmt.Errorf("cannot PackAndSwitchN1ToN2: PackN1: %w", err) } @@ -68,7 +68,7 @@ func (b Bootstrapper) PackAndSwitchN1ToN2(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphe } } - if cts, err = b.Pack(cts, b.paramsN2, b.xPow2N2); err != nil { + if cts, err = b.Pack(cts, b.Parameters.Parameters.Parameters, b.xPow2N2); err != nil { return nil, fmt.Errorf("cannot PackAndSwitchN1ToN2: PackN2: %w", err) } @@ -79,11 +79,11 @@ func (b Bootstrapper) UnpackAndSwitchN2Tn1(cts []*rlwe.Ciphertext, LogSlots, Nb var err error - if cts, err = b.UnPack(cts, b.paramsN2, LogSlots, Nb, b.xPow2InvN2); err != nil { + if cts, err = b.UnPack(cts, b.Parameters.Parameters.Parameters, LogSlots, Nb, b.xPow2InvN2); err != nil { return nil, fmt.Errorf("cannot UnpackAndSwitchN2Tn1: UnpackN2: %w", err) } - if b.paramsN1.N() != b.paramsN2.N() { + if b.ResidualParameters.N() != b.Parameters.Parameters.Parameters.N() { for i := range cts { cts[i] = b.SwitchRingDegreeN2ToN1New(cts[i]) } diff --git a/examples/ckks/bootstrapping/basic/main.go b/examples/ckks/bootstrapping/basic/main.go index de8064a5..8cbe1c41 100644 --- a/examples/ckks/bootstrapping/basic/main.go +++ b/examples/ckks/bootstrapping/basic/main.go @@ -152,7 +152,7 @@ func main() { // Instantiates the bootstrapper var btp *bootstrapper.Bootstrapper - if btp, err = bootstrapper.NewBootstrapper(params, btpParams, evk); err != nil { + if btp, err = bootstrapper.NewBootstrapper(btpParams, evk); err != nil { panic(err) }