mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
Added evaluator and encryptor contexts for ckks
This commit is contained in:
@@ -3,8 +3,6 @@ package bfv
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ldsec/lattigo/ring"
|
||||
)
|
||||
|
||||
func Benchmark_BFV(b *testing.B) {
|
||||
@@ -40,12 +38,7 @@ func Benchmark_BFV(b *testing.B) {
|
||||
pt := bfvContext.NewPlaintext()
|
||||
pt.setCoefficientsUint64(bfvContext, ptcoeffs)
|
||||
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(params.N, params.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := NewCiphertextRingContext(¶ms)
|
||||
|
||||
ctd1 := NewCiphertext(1, ringCtx)
|
||||
b.Run(testString("EncryptFromPk", ¶ms), func(b *testing.B) {
|
||||
|
||||
@@ -426,12 +426,7 @@ func testEvaluatorSub(t *testing.T) {
|
||||
func testEvaluatorMul(t *testing.T) {
|
||||
|
||||
for _, parameters := range testParams.bfvParameters {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := NewCiphertextRingContext(parameters)
|
||||
|
||||
params := genBfvParams(parameters)
|
||||
|
||||
@@ -543,12 +538,7 @@ func testRotateRows(t *testing.T) {
|
||||
func testRotateCols(t *testing.T) {
|
||||
|
||||
for _, parameters := range testParams.bfvParameters {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := NewCiphertextRingContext(parameters)
|
||||
|
||||
params := genBfvParams(parameters)
|
||||
|
||||
|
||||
@@ -14,6 +14,18 @@ func NewCiphertextStruct() (ciphertext *Ciphertext) {
|
||||
return &Ciphertext{&bfvElement{}}
|
||||
}
|
||||
|
||||
func NewCiphertextRingContext(params *Parameters) *ring.Context {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(params.N, params.Qi)
|
||||
|
||||
err := ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ringCtx
|
||||
}
|
||||
|
||||
// NewCiphertext creates a new empty ciphertext of degree degree.
|
||||
func NewCiphertext(degree uint64, ringCtx *ring.Context) *Ciphertext {
|
||||
ciphertext := &Ciphertext{&bfvElement{}}
|
||||
|
||||
@@ -19,13 +19,13 @@ func (evaluator *Evaluator) PowerOf2(el0 *Ciphertext, logPow2 uint64, evakey *Ev
|
||||
|
||||
evaluator.MulRelin(el0.Element(), el0.Element(), evakey, elOut)
|
||||
|
||||
evaluator.Rescale(elOut, evaluator.ckkscontext.scale, elOut)
|
||||
evaluator.Rescale(elOut, evaluator.context.scale, elOut)
|
||||
|
||||
for i := uint64(1); i < logPow2; i++ {
|
||||
|
||||
evaluator.MulRelin(elOut.Element(), elOut.Element(), evakey, elOut)
|
||||
|
||||
evaluator.Rescale(elOut, evaluator.ckkscontext.scale, elOut)
|
||||
evaluator.Rescale(elOut, evaluator.context.scale, elOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func (evaluator *Evaluator) PowerOf2(el0 *Ciphertext, logPow2 uint64, evakey *Ev
|
||||
// PowerNew compute ct0^degree, consuming log(degree) levels, and returns the result on a new element. Providing an evaluation
|
||||
// key is necessary when degree > 2.
|
||||
func (evaluator *Evaluator) PowerNew(op *Ciphertext, degree uint64, evakey *EvaluationKey) (opOut *Ciphertext) {
|
||||
opOut = evaluator.ckkscontext.NewCiphertext(1, op.Level(), op.Scale())
|
||||
opOut = NewCiphertext(1, op.Level(), op.Scale(), evaluator.context.contextQ)
|
||||
evaluator.Power(op, degree, evakey, opOut)
|
||||
return
|
||||
}
|
||||
@@ -58,13 +58,13 @@ func (evaluator *Evaluator) Power(ct0 *Ciphertext, degree uint64, evakey *Evalua
|
||||
logDegree = uint64(bits.Len64(degree)) - 1
|
||||
po2Degree = 1 << logDegree
|
||||
|
||||
tmp := evaluator.ckkscontext.NewCiphertext(1, tmpct0.Level(), tmpct0.Scale())
|
||||
tmp := NewCiphertext(1, tmpct0.Level(), tmpct0.Scale(), evaluator.context.contextQ)
|
||||
|
||||
evaluator.PowerOf2(tmpct0.Ciphertext(), logDegree, evakey, tmp)
|
||||
|
||||
evaluator.MulRelin(res.Element(), tmp.Element(), evakey, res)
|
||||
|
||||
evaluator.Rescale(res, evaluator.ckkscontext.scale, res)
|
||||
evaluator.Rescale(res, evaluator.context.scale, res)
|
||||
|
||||
degree -= po2Degree
|
||||
}
|
||||
@@ -85,13 +85,13 @@ func (evaluator *Evaluator) InverseNew(ct0 *Ciphertext, steps uint64, evakey *Ev
|
||||
|
||||
evaluator.MulRelin(cbar.Element(), cbar.Element(), evakey, cbar.Ciphertext())
|
||||
|
||||
evaluator.Rescale(cbar, evaluator.ckkscontext.scale, cbar)
|
||||
evaluator.Rescale(cbar, evaluator.context.scale, cbar)
|
||||
|
||||
tmp = evaluator.AddConstNew(cbar, 1)
|
||||
|
||||
evaluator.MulRelin(tmp.Element(), res.Element(), evakey, tmp.Ciphertext())
|
||||
|
||||
evaluator.Rescale(tmp, evaluator.ckkscontext.scale, tmp)
|
||||
evaluator.Rescale(tmp, evaluator.context.scale, tmp)
|
||||
|
||||
res = tmp.CopyNew().Ciphertext()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func (evaluator *Evaluator) EvaluateChebyFast(ct *Ciphertext, cheby *ChebyshevIn
|
||||
|
||||
evaluator.MultByConst(C[1], 2/(cheby.b-cheby.a), C[1])
|
||||
evaluator.AddConst(C[1], (-cheby.a-cheby.b)/(cheby.b-cheby.a), C[1])
|
||||
evaluator.Rescale(C[1], evaluator.ckkscontext.scale, C[1])
|
||||
evaluator.Rescale(C[1], evaluator.context.scale, C[1])
|
||||
|
||||
M := uint64(bits.Len64(cheby.degree - 1))
|
||||
L := uint64(M >> 1)
|
||||
@@ -86,7 +86,7 @@ func computePowerBasisCheby(n uint64, C map[uint64]*Ciphertext, evaluator *Evalu
|
||||
// Computes C[n] = C[a]*C[b]
|
||||
C[n] = evaluator.MulRelinNew(C[a], C[b], evakey)
|
||||
|
||||
evaluator.Rescale(C[n], evaluator.ckkscontext.scale, C[n])
|
||||
evaluator.Rescale(C[n], evaluator.context.scale, C[n])
|
||||
|
||||
// Computes C[n] = 2*C[a]*C[b]
|
||||
evaluator.Add(C[n], C[n], C[n])
|
||||
@@ -123,7 +123,7 @@ func recurseCheby(maxDegree, L, M uint64, coeffs map[uint64]complex128, C map[ui
|
||||
|
||||
evaluator.Add(res, tmp, res)
|
||||
|
||||
evaluator.Rescale(res, evaluator.ckkscontext.scale, res)
|
||||
evaluator.Rescale(res, evaluator.context.scale, res)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
@@ -9,18 +9,66 @@ type Ciphertext struct {
|
||||
*ckksElement
|
||||
}
|
||||
|
||||
// NewCiphertext returns a new Ciphertext element.
|
||||
func NewCiphertext() (ciphertext *Ciphertext) {
|
||||
// NewCiphertextStruct returns a new Ciphertext element.
|
||||
func NewCiphertextStruct() (ciphertext *Ciphertext) {
|
||||
return &Ciphertext{&ckksElement{}}
|
||||
}
|
||||
|
||||
func NewCiphertextRingContext(params *Parameters) *ring.Context {
|
||||
scalechain := make([]float64, len(params.Modulichain))
|
||||
|
||||
// Extracts all the different primes bit size and maps their number
|
||||
primesbitlen := make(map[uint64]uint64)
|
||||
for i, qi := range params.Modulichain {
|
||||
|
||||
primesbitlen[uint64(qi)]++
|
||||
|
||||
if uint64(params.Modulichain[i]) > 60 {
|
||||
panic("provided moduli must be smaller than 61")
|
||||
}
|
||||
}
|
||||
|
||||
for _, pj := range params.P {
|
||||
primesbitlen[uint64(pj)]++
|
||||
|
||||
if uint64(pj) > 60 {
|
||||
panic("provided P must be smaller than 61")
|
||||
}
|
||||
}
|
||||
|
||||
// For each bitsize, finds that many primes
|
||||
primes := make(map[uint64][]uint64)
|
||||
for key, value := range primesbitlen {
|
||||
primes[key] = GenerateCKKSPrimes(key, uint64(params.LogN), value)
|
||||
}
|
||||
|
||||
// Assigns the primes to the ckks moduli chain
|
||||
moduli := make([]uint64, len(params.Modulichain))
|
||||
for i, qi := range params.Modulichain {
|
||||
moduli[i] = primes[uint64(params.Modulichain[i])][0]
|
||||
primes[uint64(qi)] = primes[uint64(qi)][1:]
|
||||
|
||||
scalechain[i] = float64(moduli[i])
|
||||
}
|
||||
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(1<<params.LogN, moduli)
|
||||
|
||||
err := ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ringCtx
|
||||
}
|
||||
|
||||
// NewCiphertext creates a new ciphertext parameterized by degree, level and scale.
|
||||
func (ckkscontext *Context) NewCiphertext(degree uint64, level uint64, scale float64) *Ciphertext {
|
||||
func NewCiphertext(degree uint64, level uint64, scale float64, ringCtx *ring.Context) *Ciphertext {
|
||||
ciphertext := &Ciphertext{&ckksElement{}}
|
||||
|
||||
ciphertext.value = make([]*ring.Poly, degree+1)
|
||||
for i := uint64(0); i < degree+1; i++ {
|
||||
ciphertext.value[i] = ckkscontext.contextQ.NewPolyLvl(level)
|
||||
ciphertext.value[i] = ringCtx.NewPolyLvl(level)
|
||||
}
|
||||
|
||||
ciphertext.scale = scale
|
||||
|
||||
@@ -97,11 +97,11 @@ func genCkksParams(contextParameters *Parameters) (params *ckksParams) {
|
||||
|
||||
params.encoder = NewEncoder(contextParameters)
|
||||
|
||||
params.encryptorPk = params.ckkscontext.NewEncryptorFromPk(params.pk)
|
||||
params.encryptorSk = params.ckkscontext.NewEncryptorFromSk(params.sk)
|
||||
params.encryptorPk = NewEncryptorFromPk(params.pk, contextParameters)
|
||||
params.encryptorSk = NewEncryptorFromSk(params.sk, contextParameters)
|
||||
params.decryptor = params.ckkscontext.NewDecryptor(params.sk)
|
||||
|
||||
params.evaluator = params.ckkscontext.NewEvaluator()
|
||||
params.evaluator = NewEvaluator(contextParameters)
|
||||
|
||||
return
|
||||
|
||||
@@ -871,12 +871,14 @@ func testRotateColumns(t *testing.T) {
|
||||
|
||||
rotKey := params.kgen.NewRotationKeysPow2(params.sk)
|
||||
|
||||
ringCtx := NewCiphertextRingContext(parameters)
|
||||
|
||||
t.Run(testString("InPlace/", params), func(t *testing.T) {
|
||||
|
||||
values1, _, ciphertext1 := newTestVectorsReals(params, params.encryptorSk, -1, 1, t)
|
||||
|
||||
values2 := make([]complex128, len(values1))
|
||||
ciphertext2 := params.ckkscontext.NewCiphertext(ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale())
|
||||
ciphertext2 := NewCiphertext(ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale(), ringCtx)
|
||||
|
||||
for n := 1; n < len(values1); n <<= 1 {
|
||||
|
||||
@@ -897,7 +899,7 @@ func testRotateColumns(t *testing.T) {
|
||||
values1, _, ciphertext1 := newTestVectorsReals(params, params.encryptorSk, -1, 1, t)
|
||||
|
||||
values2 := make([]complex128, len(values1))
|
||||
ciphertext2 := params.ckkscontext.NewCiphertext(ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale())
|
||||
ciphertext2 := NewCiphertext(ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale(), ringCtx)
|
||||
|
||||
for n := 1; n < len(values1); n <<= 1 {
|
||||
|
||||
@@ -918,7 +920,7 @@ func testRotateColumns(t *testing.T) {
|
||||
values1, _, ciphertext1 := newTestVectorsReals(params, params.encryptorSk, -1, 1, t)
|
||||
|
||||
values2 := make([]complex128, len(values1))
|
||||
ciphertext2 := params.ckkscontext.NewCiphertext(ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale())
|
||||
ciphertext2 := NewCiphertext(ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale(), ringCtx)
|
||||
|
||||
for n := 1; n < 4; n++ {
|
||||
|
||||
@@ -953,7 +955,7 @@ func testMarshaller(t *testing.T) {
|
||||
marshalledCiphertext, err := ciphertextWant.MarshalBinary()
|
||||
check(t, err)
|
||||
|
||||
ciphertextTest := NewCiphertext()
|
||||
ciphertextTest := NewCiphertextStruct()
|
||||
err = ciphertextTest.UnmarshalBinary(marshalledCiphertext)
|
||||
check(t, err)
|
||||
|
||||
|
||||
@@ -4,12 +4,140 @@ import (
|
||||
"github.com/ldsec/lattigo/ring"
|
||||
)
|
||||
|
||||
type encryptorContext struct {
|
||||
// Context parameters
|
||||
n uint64
|
||||
|
||||
// Number of available levels
|
||||
levels uint64
|
||||
|
||||
// Contexts
|
||||
specialPrimes []uint64
|
||||
contextQ *ring.Context
|
||||
contextP *ring.Context
|
||||
contextKeys *ring.Context
|
||||
|
||||
// Pre-computed values for the rescaling
|
||||
rescaleParamsKeys []uint64 // (P^-1) mod each qi
|
||||
|
||||
// Samplers
|
||||
gaussianSampler *ring.KYSampler
|
||||
}
|
||||
|
||||
func newEncryptorContext(params *Parameters) *encryptorContext {
|
||||
n := uint64(1 << uint64(params.LogN))
|
||||
levels := uint64(len(params.Modulichain))
|
||||
|
||||
scalechain := make([]float64, len(params.Modulichain))
|
||||
|
||||
// Extracts all the different primes bit size and maps their number
|
||||
primesbitlen := make(map[uint64]uint64)
|
||||
for i, qi := range params.Modulichain {
|
||||
|
||||
primesbitlen[uint64(qi)]++
|
||||
|
||||
if uint64(params.Modulichain[i]) > 60 {
|
||||
panic("provided moduli must be smaller than 61")
|
||||
}
|
||||
}
|
||||
|
||||
for _, pj := range params.P {
|
||||
primesbitlen[uint64(pj)]++
|
||||
|
||||
if uint64(pj) > 60 {
|
||||
panic("provided P must be smaller than 61")
|
||||
}
|
||||
}
|
||||
|
||||
// For each bitsize, finds that many primes
|
||||
primes := make(map[uint64][]uint64)
|
||||
for key, value := range primesbitlen {
|
||||
primes[key] = GenerateCKKSPrimes(key, uint64(params.LogN), value)
|
||||
}
|
||||
|
||||
// Assigns the primes to the ckks moduli chain
|
||||
moduli := make([]uint64, len(params.Modulichain))
|
||||
for i, qi := range params.Modulichain {
|
||||
moduli[i] = primes[uint64(params.Modulichain[i])][0]
|
||||
primes[uint64(qi)] = primes[uint64(qi)][1:]
|
||||
|
||||
scalechain[i] = float64(moduli[i])
|
||||
}
|
||||
|
||||
// Assigns the primes to the special primes list for the the keyscontext
|
||||
specialPrimes := make([]uint64, len(params.P))
|
||||
for i, pj := range params.P {
|
||||
specialPrimes[i] = primes[uint64(pj)][0]
|
||||
primes[uint64(pj)] = primes[uint64(pj)][1:]
|
||||
}
|
||||
|
||||
// Contexts
|
||||
contextQ := ring.NewContext()
|
||||
contextQ.SetParameters(1<<params.LogN, moduli)
|
||||
|
||||
err := contextQ.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
contextP := ring.NewContext()
|
||||
contextP.SetParameters(1<<params.LogN, specialPrimes)
|
||||
|
||||
err = contextP.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
contextKeys := ring.NewContext()
|
||||
contextKeys.SetParameters(1<<params.LogN, append(moduli, specialPrimes...))
|
||||
|
||||
err = contextKeys.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var Qi uint64
|
||||
|
||||
bredParams := contextQ.GetBredParams()
|
||||
|
||||
rescaleParamsKeys := make([]uint64, levels)
|
||||
|
||||
PBig := ring.NewUint(1)
|
||||
for _, pj := range specialPrimes {
|
||||
PBig.Mul(PBig, ring.NewUint(pj))
|
||||
}
|
||||
|
||||
tmp := ring.NewUint(0)
|
||||
|
||||
for i := uint64(0); i < levels; i++ {
|
||||
|
||||
Qi = moduli[i]
|
||||
|
||||
tmp.Mod(PBig, ring.NewUint(Qi))
|
||||
|
||||
rescaleParamsKeys[i] = ring.MForm(ring.ModExp(ring.BRedAdd(tmp.Uint64(), Qi, bredParams[i]), Qi-2, Qi), Qi, bredParams[i])
|
||||
}
|
||||
|
||||
gaussianSampler := contextKeys.NewKYSampler(params.Sigma, int(6*params.Sigma))
|
||||
|
||||
return &encryptorContext{
|
||||
n: n,
|
||||
levels: levels,
|
||||
specialPrimes: specialPrimes,
|
||||
contextQ: contextQ,
|
||||
contextP: contextP,
|
||||
contextKeys: contextKeys,
|
||||
rescaleParamsKeys: rescaleParamsKeys,
|
||||
gaussianSampler: gaussianSampler,
|
||||
}
|
||||
}
|
||||
|
||||
// Encryptor is a struct used to encrypt plaintext and storing the public-key and/or secret-key.
|
||||
type Encryptor struct {
|
||||
ckkscontext *Context
|
||||
pk *PublicKey
|
||||
sk *SecretKey
|
||||
polypool [3]*ring.Poly
|
||||
context *encryptorContext
|
||||
pk *PublicKey
|
||||
sk *SecretKey
|
||||
polypool [3]*ring.Poly
|
||||
|
||||
rescalepool []uint64
|
||||
|
||||
@@ -18,40 +146,41 @@ type Encryptor struct {
|
||||
|
||||
// NewEncryptorFromPk creates a new Encryptor with the provided public-key.
|
||||
// This encryptor can be used to encrypt plaintexts, using the stored key.
|
||||
func (ckkscontext *Context) NewEncryptorFromPk(pk *PublicKey) *Encryptor {
|
||||
return ckkscontext.newEncryptor(pk, nil)
|
||||
func NewEncryptorFromPk(pk *PublicKey, params *Parameters) *Encryptor {
|
||||
return newEncryptor(pk, nil, params)
|
||||
}
|
||||
|
||||
// NewEncryptorFromSk creates a new Encryptor with the provided secret-key.
|
||||
// This encryptor can be used to encrypt plaintexts, using the stored key.
|
||||
func (ckkscontext *Context) NewEncryptorFromSk(sk *SecretKey) *Encryptor {
|
||||
return ckkscontext.newEncryptor(nil, sk)
|
||||
func NewEncryptorFromSk(sk *SecretKey, params *Parameters) *Encryptor {
|
||||
return newEncryptor(nil, sk, params)
|
||||
}
|
||||
|
||||
// NewEncryptor creates a new Encryptor with the input public-key and/or secret-key.
|
||||
// This encryptor can be used to encrypt plaintexts, using the stored keys.
|
||||
func (ckkscontext *Context) newEncryptor(pk *PublicKey, sk *SecretKey) (encryptor *Encryptor) {
|
||||
func newEncryptor(pk *PublicKey, sk *SecretKey, params *Parameters) (encryptor *Encryptor) {
|
||||
context := newEncryptorContext(params)
|
||||
|
||||
if pk != nil && (uint64(pk.pk[0].GetDegree()) != ckkscontext.n || uint64(pk.pk[1].GetDegree()) != ckkscontext.n) {
|
||||
if pk != nil && (uint64(pk.pk[0].GetDegree()) != context.n || uint64(pk.pk[1].GetDegree()) != context.n) {
|
||||
panic("pk ring degree doesn't match ckkscontext ring degree")
|
||||
}
|
||||
|
||||
if sk != nil && uint64(sk.sk.GetDegree()) != ckkscontext.n {
|
||||
if sk != nil && uint64(sk.sk.GetDegree()) != context.n {
|
||||
panic("sk ring degree doesn't match ckkscontext ring degree")
|
||||
}
|
||||
|
||||
encryptor = new(Encryptor)
|
||||
encryptor.ckkscontext = ckkscontext
|
||||
encryptor.context = context
|
||||
encryptor.pk = pk
|
||||
encryptor.sk = sk
|
||||
|
||||
encryptor.polypool[0] = ckkscontext.contextKeys.NewPoly()
|
||||
encryptor.polypool[1] = ckkscontext.contextKeys.NewPoly()
|
||||
encryptor.polypool[2] = ckkscontext.contextKeys.NewPoly()
|
||||
encryptor.polypool[0] = context.contextKeys.NewPoly()
|
||||
encryptor.polypool[1] = context.contextKeys.NewPoly()
|
||||
encryptor.polypool[2] = context.contextKeys.NewPoly()
|
||||
|
||||
encryptor.rescalepool = make([]uint64, ckkscontext.n)
|
||||
encryptor.rescalepool = make([]uint64, context.n)
|
||||
|
||||
encryptor.baseconverter = ring.NewFastBasisExtender(ckkscontext.contextQ.Modulus, ckkscontext.specialprimes)
|
||||
encryptor.baseconverter = ring.NewFastBasisExtender(context.contextQ.Modulus, context.specialPrimes)
|
||||
|
||||
return encryptor
|
||||
}
|
||||
@@ -63,7 +192,7 @@ func (ckkscontext *Context) newEncryptor(pk *PublicKey, sk *SecretKey) (encrypto
|
||||
// encrypt with sk : ciphertext = [-a*sk + m + e, a]
|
||||
func (encryptor *Encryptor) EncryptNew(plaintext *Plaintext) (ciphertext *Ciphertext) {
|
||||
|
||||
ciphertext = encryptor.ckkscontext.NewCiphertext(1, plaintext.Level(), plaintext.Scale())
|
||||
ciphertext = NewCiphertext(1, plaintext.Level(), plaintext.Scale(), encryptor.context.contextQ)
|
||||
encryptor.Encrypt(plaintext, ciphertext)
|
||||
return
|
||||
}
|
||||
@@ -75,7 +204,7 @@ func (encryptor *Encryptor) EncryptNew(plaintext *Plaintext) (ciphertext *Cipher
|
||||
// encrypt with sk : ciphertext = [-a*sk + m + e, a]
|
||||
func (encryptor *Encryptor) Encrypt(plaintext *Plaintext, ciphertext *Ciphertext) {
|
||||
|
||||
if plaintext.Level() != encryptor.ckkscontext.levels-1 {
|
||||
if plaintext.Level() != encryptor.context.levels-1 {
|
||||
panic("cannot encrypt -> plaintext not at maximum level")
|
||||
}
|
||||
|
||||
@@ -97,10 +226,10 @@ func encryptfrompk(encryptor *Encryptor, plaintext *Plaintext, ciphertext *Ciphe
|
||||
|
||||
// We sample a R-WLE instance (encryption of zero) over the keys context (ciphertext context + special prime)
|
||||
|
||||
contextKeys := encryptor.ckkscontext.contextKeys
|
||||
contextQ := encryptor.ckkscontext.contextQ
|
||||
contextKeys := encryptor.context.contextKeys
|
||||
contextQ := encryptor.context.contextQ
|
||||
|
||||
encryptor.ckkscontext.contextKeys.SampleTernaryMontgomeryNTT(encryptor.polypool[2], 0.5)
|
||||
encryptor.context.contextKeys.SampleTernaryMontgomeryNTT(encryptor.polypool[2], 0.5)
|
||||
|
||||
// ct0 = u*pk0
|
||||
contextKeys.MulCoeffsMontgomery(encryptor.polypool[2], encryptor.pk.pk[0], encryptor.polypool[0])
|
||||
@@ -112,15 +241,15 @@ func encryptfrompk(encryptor *Encryptor, plaintext *Plaintext, ciphertext *Ciphe
|
||||
contextKeys.InvNTT(encryptor.polypool[1], encryptor.polypool[1])
|
||||
|
||||
// ct0 = u*pk0 + e0
|
||||
encryptor.ckkscontext.gaussianSampler.SampleAndAdd(encryptor.polypool[0])
|
||||
encryptor.context.gaussianSampler.SampleAndAdd(encryptor.polypool[0])
|
||||
// ct1 = u*pk1 + e1
|
||||
encryptor.ckkscontext.gaussianSampler.SampleAndAdd(encryptor.polypool[1])
|
||||
encryptor.context.gaussianSampler.SampleAndAdd(encryptor.polypool[1])
|
||||
|
||||
// ct0 = (u*pk0 + e0)/P
|
||||
encryptor.baseconverter.ModDown(contextKeys, encryptor.ckkscontext.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[0], ciphertext.value[0], encryptor.polypool[2])
|
||||
encryptor.baseconverter.ModDown(contextKeys, encryptor.context.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[0], ciphertext.value[0], encryptor.polypool[2])
|
||||
|
||||
// ct1 = (u*pk1 + e1)/P
|
||||
encryptor.baseconverter.ModDown(contextKeys, encryptor.ckkscontext.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[1], ciphertext.value[1], encryptor.polypool[2])
|
||||
encryptor.baseconverter.ModDown(contextKeys, encryptor.context.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[1], ciphertext.value[1], encryptor.polypool[2])
|
||||
|
||||
// 2*#Q NTT
|
||||
contextQ.NTT(ciphertext.value[0], ciphertext.value[0])
|
||||
@@ -133,9 +262,9 @@ func encryptfrompk(encryptor *Encryptor, plaintext *Plaintext, ciphertext *Ciphe
|
||||
}
|
||||
|
||||
func encryptfromsk(encryptor *Encryptor, plaintext *Plaintext, ciphertext *Ciphertext) {
|
||||
contextKeys := encryptor.ckkscontext.contextKeys
|
||||
contextP := encryptor.ckkscontext.contextP
|
||||
contextQ := encryptor.ckkscontext.contextQ
|
||||
contextKeys := encryptor.context.contextKeys
|
||||
contextP := encryptor.context.contextP
|
||||
contextQ := encryptor.context.contextQ
|
||||
|
||||
// ct1 = a
|
||||
contextKeys.UniformPoly(encryptor.polypool[1])
|
||||
@@ -148,15 +277,15 @@ func encryptfromsk(encryptor *Encryptor, plaintext *Plaintext, ciphertext *Ciphe
|
||||
contextKeys.InvNTT(encryptor.polypool[0], encryptor.polypool[0])
|
||||
|
||||
// ct0 = -s*a + e
|
||||
encryptor.ckkscontext.gaussianSampler.SampleAndAdd(encryptor.polypool[0])
|
||||
encryptor.context.gaussianSampler.SampleAndAdd(encryptor.polypool[0])
|
||||
|
||||
// We rescal by the special prime, dividing the error by this prime
|
||||
// ct0 = (-s*a + e)/P
|
||||
encryptor.baseconverter.ModDown(contextKeys, encryptor.ckkscontext.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[0], ciphertext.value[0], encryptor.polypool[2])
|
||||
encryptor.baseconverter.ModDown(contextKeys, encryptor.context.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[0], ciphertext.value[0], encryptor.polypool[2])
|
||||
|
||||
// #Q + #P NTT
|
||||
// ct1 = a/P
|
||||
encryptor.baseconverter.ModDownNTT(contextQ, contextP, encryptor.ckkscontext.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[1], ciphertext.value[1], encryptor.polypool[2])
|
||||
encryptor.baseconverter.ModDownNTT(contextQ, contextP, encryptor.context.rescaleParamsKeys, plaintext.Level(), encryptor.polypool[1], ciphertext.value[1], encryptor.polypool[2])
|
||||
|
||||
// #Q NTT
|
||||
contextQ.NTT(ciphertext.value[0], ciphertext.value[0])
|
||||
|
||||
@@ -7,10 +7,147 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
type evaluatorContext struct {
|
||||
// Context parameters
|
||||
n uint64
|
||||
scale float64
|
||||
|
||||
// Number of available levels
|
||||
levels uint64
|
||||
|
||||
// Moduli chain
|
||||
moduli []uint64
|
||||
scalechain []float64
|
||||
|
||||
// Contexts
|
||||
specialprimes []uint64
|
||||
alpha uint64
|
||||
beta uint64
|
||||
contextQ *ring.Context
|
||||
contextP *ring.Context
|
||||
contextKeys *ring.Context
|
||||
|
||||
// Pre-computed values for the rescaling
|
||||
rescaleParamsKeys []uint64 // (P^-1) mod each qi
|
||||
}
|
||||
|
||||
func newEvaluatorContext(params *Parameters) *evaluatorContext {
|
||||
n := uint64(1 << uint64(params.LogN))
|
||||
scale := params.Scale
|
||||
levels := uint64(len(params.Modulichain))
|
||||
|
||||
alpha := uint64(len(params.P))
|
||||
beta := uint64(math.Ceil(float64(levels) / float64(alpha)))
|
||||
|
||||
scalechain := make([]float64, len(params.Modulichain))
|
||||
|
||||
// Extracts all the different primes bit size and maps their number
|
||||
primesbitlen := make(map[uint64]uint64)
|
||||
for i, qi := range params.Modulichain {
|
||||
|
||||
primesbitlen[uint64(qi)]++
|
||||
|
||||
if uint64(params.Modulichain[i]) > 60 {
|
||||
panic("provided moduli must be smaller than 61")
|
||||
}
|
||||
}
|
||||
|
||||
for _, pj := range params.P {
|
||||
primesbitlen[uint64(pj)]++
|
||||
|
||||
if uint64(pj) > 60 {
|
||||
panic("provided P must be smaller than 61")
|
||||
}
|
||||
}
|
||||
// For each bitsize, finds that many primes
|
||||
primes := make(map[uint64][]uint64)
|
||||
for key, value := range primesbitlen {
|
||||
primes[key] = GenerateCKKSPrimes(key, uint64(params.LogN), value)
|
||||
}
|
||||
|
||||
// Assigns the primes to the ckks moduli chain
|
||||
moduli := make([]uint64, len(params.Modulichain))
|
||||
for i, qi := range params.Modulichain {
|
||||
moduli[i] = primes[uint64(params.Modulichain[i])][0]
|
||||
primes[uint64(qi)] = primes[uint64(qi)][1:]
|
||||
|
||||
scalechain[i] = float64(moduli[i])
|
||||
}
|
||||
|
||||
// Assigns the primes to the special primes list for the the keyscontext
|
||||
specialprimes := make([]uint64, len(params.P))
|
||||
for i, pj := range params.P {
|
||||
specialprimes[i] = primes[uint64(pj)][0]
|
||||
primes[uint64(pj)] = primes[uint64(pj)][1:]
|
||||
}
|
||||
|
||||
// Contexts
|
||||
contextQ := ring.NewContext()
|
||||
contextQ.SetParameters(1<<params.LogN, moduli)
|
||||
|
||||
err := contextQ.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
contextP := ring.NewContext()
|
||||
contextP.SetParameters(1<<params.LogN, specialprimes)
|
||||
|
||||
err = contextP.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
contextKeys := ring.NewContext()
|
||||
contextKeys.SetParameters(1<<params.LogN, append(moduli, specialprimes...))
|
||||
|
||||
err = contextKeys.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var Qi uint64
|
||||
|
||||
bredParams := contextQ.GetBredParams()
|
||||
|
||||
rescaleParamsKeys := make([]uint64, levels)
|
||||
|
||||
PBig := ring.NewUint(1)
|
||||
for _, pj := range specialprimes {
|
||||
PBig.Mul(PBig, ring.NewUint(pj))
|
||||
}
|
||||
|
||||
tmp := ring.NewUint(0)
|
||||
|
||||
for i := uint64(0); i < levels; i++ {
|
||||
|
||||
Qi = moduli[i]
|
||||
|
||||
tmp.Mod(PBig, ring.NewUint(Qi))
|
||||
|
||||
rescaleParamsKeys[i] = ring.MForm(ring.ModExp(ring.BRedAdd(tmp.Uint64(), Qi, bredParams[i]), Qi-2, Qi), Qi, bredParams[i])
|
||||
}
|
||||
|
||||
return &evaluatorContext{
|
||||
n: n,
|
||||
scale: scale,
|
||||
levels: levels,
|
||||
moduli: moduli,
|
||||
scalechain: scalechain,
|
||||
specialprimes: specialprimes,
|
||||
alpha: alpha,
|
||||
beta: beta,
|
||||
contextQ: contextQ,
|
||||
contextP: contextP,
|
||||
contextKeys: contextKeys,
|
||||
rescaleParamsKeys: rescaleParamsKeys,
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluator is a struct holding the necessary elements to operates the homomorphic operations between ciphertext and/or plaintexts.
|
||||
// It also holds a small memory pool used to store intermediate computations.
|
||||
type Evaluator struct {
|
||||
ckkscontext *Context
|
||||
context *evaluatorContext
|
||||
ringpool [6]*ring.Poly
|
||||
keyswitchpool [4]*ring.Poly
|
||||
|
||||
@@ -27,31 +164,32 @@ type Evaluator struct {
|
||||
// NewEvaluator creates a new Evaluator, that can be used to do homomorphic
|
||||
// operations on the ciphertexts and/or plaintexts. It stores a small pool of polynomials
|
||||
// and ciphertexts that will be used for intermediate values.
|
||||
func (ckkscontext *Context) NewEvaluator() (evaluator *Evaluator) {
|
||||
|
||||
func NewEvaluator(params *Parameters) (evaluator *Evaluator) {
|
||||
evaluator = new(Evaluator)
|
||||
evaluator.ckkscontext = ckkscontext
|
||||
|
||||
context := newEvaluatorContext(params)
|
||||
evaluator.context = context
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
evaluator.ringpool[i] = evaluator.ckkscontext.contextQ.NewPoly()
|
||||
evaluator.ringpool[i] = context.contextQ.NewPoly()
|
||||
}
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
evaluator.keyswitchpool[i] = evaluator.ckkscontext.contextKeys.NewPoly()
|
||||
evaluator.keyswitchpool[i] = context.contextKeys.NewPoly()
|
||||
}
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
evaluator.poolQ[i] = evaluator.ckkscontext.contextQ.NewPoly()
|
||||
evaluator.poolP[i] = evaluator.ckkscontext.contextP.NewPoly()
|
||||
evaluator.poolQ[i] = context.contextQ.NewPoly()
|
||||
evaluator.poolP[i] = context.contextP.NewPoly()
|
||||
}
|
||||
|
||||
evaluator.rescalepool = make([]uint64, ckkscontext.n)
|
||||
evaluator.rescalepool = make([]uint64, context.n)
|
||||
|
||||
evaluator.ctxpool = ckkscontext.NewCiphertext(1, ckkscontext.levels-1, ckkscontext.scale)
|
||||
evaluator.ctxpool = NewCiphertext(1, context.levels-1, context.scale, context.contextQ)
|
||||
|
||||
evaluator.baseconverter = ring.NewFastBasisExtender(evaluator.ckkscontext.contextQ.Modulus, evaluator.ckkscontext.specialprimes)
|
||||
evaluator.baseconverter = ring.NewFastBasisExtender(context.contextQ.Modulus, context.specialprimes)
|
||||
|
||||
evaluator.decomposer = ring.NewArbitraryDecomposer(ckkscontext.moduli, ckkscontext.specialprimes)
|
||||
evaluator.decomposer = ring.NewArbitraryDecomposer(context.moduli, context.specialprimes)
|
||||
|
||||
return evaluator
|
||||
}
|
||||
@@ -94,19 +232,19 @@ func (evaluator *Evaluator) newCiphertextBinary(op0, op1 Operand) (ctOut *Cipher
|
||||
maxScale := utils.MaxFloat64(op0.Scale(), op1.Scale())
|
||||
minLevel := utils.MinUint64(op0.Level(), op1.Level())
|
||||
|
||||
return evaluator.ckkscontext.NewCiphertext(maxDegree, minLevel, maxScale)
|
||||
return NewCiphertext(maxDegree, minLevel, maxScale, evaluator.context.contextQ)
|
||||
}
|
||||
|
||||
// Add adds op0 to op1 and returns the result on ctOut.
|
||||
func (evaluator *Evaluator) Add(op0, op1 Operand, ctOut *Ciphertext) {
|
||||
el0, el1, elOut := evaluator.getElemAndCheckBinary(op0, op1, ctOut, utils.MaxUint64(op0.Degree(), op1.Degree()))
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.ckkscontext.contextQ.AddLvl)
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.context.contextQ.AddLvl)
|
||||
}
|
||||
|
||||
// AddNoMod adds op0 to op1 and returns the result on ctOut, without modular reduction.
|
||||
func (evaluator *Evaluator) AddNoMod(op0, op1 Operand, ctOut *Ciphertext) {
|
||||
el0, el1, elOut := evaluator.getElemAndCheckBinary(op0, op1, ctOut, utils.MaxUint64(op0.Degree(), op1.Degree()))
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.ckkscontext.contextQ.AddNoModLvl)
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.context.contextQ.AddNoModLvl)
|
||||
}
|
||||
|
||||
// AddNew adds op0 to op1 and returns the result on a newly created element.
|
||||
@@ -128,13 +266,13 @@ func (evaluator *Evaluator) Sub(op0, op1 Operand, ctOut *Ciphertext) {
|
||||
|
||||
el0, el1, elOut := evaluator.getElemAndCheckBinary(op0, op1, ctOut, utils.MaxUint64(op0.Degree(), op1.Degree()))
|
||||
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.ckkscontext.contextQ.SubLvl)
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.context.contextQ.SubLvl)
|
||||
|
||||
level := utils.MinUint64(utils.MinUint64(el0.Level(), el1.Level()), elOut.Level())
|
||||
|
||||
if el0.Degree() < el1.Degree() {
|
||||
for i := el0.Degree() + 1; i < el1.Degree()+1; i++ {
|
||||
evaluator.ckkscontext.contextQ.NegLvl(level, elOut.Value()[i], elOut.Value()[i])
|
||||
evaluator.context.contextQ.NegLvl(level, elOut.Value()[i], elOut.Value()[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,13 +283,13 @@ func (evaluator *Evaluator) SubNoMod(op0, op1 Operand, ctOut *Ciphertext) {
|
||||
|
||||
el0, el1, elOut := evaluator.getElemAndCheckBinary(op0, op1, ctOut, utils.MaxUint64(op0.Degree(), op1.Degree()))
|
||||
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.ckkscontext.contextQ.SubNoModLvl)
|
||||
evaluator.evaluateInPlace(el0, el1, elOut, evaluator.context.contextQ.SubNoModLvl)
|
||||
|
||||
level := utils.MinUint64(utils.MinUint64(el0.Level(), el1.Level()), elOut.Level())
|
||||
|
||||
if el0.Degree() < el1.Degree() {
|
||||
for i := el0.Degree() + 1; i < el1.Degree()+1; i++ {
|
||||
evaluator.ckkscontext.contextQ.NegLvl(level, elOut.Value()[i], elOut.Value()[i])
|
||||
evaluator.context.contextQ.NegLvl(level, elOut.Value()[i], elOut.Value()[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +319,7 @@ func (evaluator *Evaluator) evaluateInPlace(c0, c1, ctOut *ckksElement, evaluate
|
||||
minDegree := utils.MinUint64(c0.Degree(), c1.Degree())
|
||||
|
||||
// Else resizes the receiver element
|
||||
ctOut.Resize(evaluator.ckkscontext, maxDegree)
|
||||
ctOut.Resize(evaluator.context.contextQ, maxDegree)
|
||||
evaluator.DropLevel(ctOut.Ciphertext(), ctOut.Level()-utils.MinUint64(c0.Level(), c1.Level()))
|
||||
|
||||
// Checks wether or not the receiver element is the same as one of the input elements
|
||||
@@ -279,11 +417,11 @@ func (evaluator *Evaluator) evaluateInPlace(c0, c1, ctOut *ckksElement, evaluate
|
||||
|
||||
if c0.Degree() > c1.Degree() && tmp0 != ctOut {
|
||||
for i := minDegree + 1; i < maxDegree+1; i++ {
|
||||
evaluator.ckkscontext.contextQ.CopyLvl(level, tmp0.Value()[i], ctOut.Value()[i])
|
||||
evaluator.context.contextQ.CopyLvl(level, tmp0.Value()[i], ctOut.Value()[i])
|
||||
}
|
||||
} else if c1.Degree() > c0.Degree() && tmp1 != ctOut {
|
||||
for i := minDegree + 1; i < maxDegree+1; i++ {
|
||||
evaluator.ckkscontext.contextQ.CopyLvl(level, tmp1.Value()[i], ctOut.Value()[i])
|
||||
evaluator.context.contextQ.CopyLvl(level, tmp1.Value()[i], ctOut.Value()[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,13 +436,13 @@ func (evaluator *Evaluator) Neg(ct0 *Ciphertext, ctOut *Ciphertext) {
|
||||
}
|
||||
|
||||
for i := range ct0.value {
|
||||
evaluator.ckkscontext.contextQ.NegLvl(level, ct0.value[i], ctOut.Value()[i])
|
||||
evaluator.context.contextQ.NegLvl(level, ct0.value[i], ctOut.Value()[i])
|
||||
}
|
||||
}
|
||||
|
||||
// NegNew negates ct0 and returns the result on a newly created element.
|
||||
func (evaluator *Evaluator) NegNew(ct0 *Ciphertext) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.Neg(ct0, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -349,7 +487,7 @@ func (evaluator *Evaluator) AddConst(ct0 *Ciphertext, constant interface{}, ctOu
|
||||
|
||||
var scaledConst, scaledConstReal, scaledConstImag uint64
|
||||
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
// Component wise addition of the following vector to the ciphertext :
|
||||
// [a + b*psi_qi^2, ....., a + b*psi_qi^2, a - b*psi_qi^2, ...., a - b*psi_qi^2] mod Qi
|
||||
@@ -376,7 +514,7 @@ func (evaluator *Evaluator) AddConst(ct0 *Ciphertext, constant interface{}, ctOu
|
||||
p1tmp := ctOut.Value()[0].Coeffs[i]
|
||||
p0tmp := ct0.value[0].Coeffs[i]
|
||||
|
||||
for j := uint64(0); j < evaluator.ckkscontext.n>>1; j++ {
|
||||
for j := uint64(0); j < evaluator.context.n>>1; j++ {
|
||||
p1tmp[j] = ring.CRed(p0tmp[j]+scaledConst, qi)
|
||||
}
|
||||
|
||||
@@ -384,7 +522,7 @@ func (evaluator *Evaluator) AddConst(ct0 *Ciphertext, constant interface{}, ctOu
|
||||
scaledConst = ring.CRed(scaledConstReal+(qi-scaledConstImag), qi)
|
||||
}
|
||||
|
||||
for j := evaluator.ckkscontext.n >> 1; j < evaluator.ckkscontext.n; j++ {
|
||||
for j := evaluator.context.n >> 1; j < evaluator.context.n; j++ {
|
||||
p1tmp[j] = ring.CRed(p0tmp[j]+scaledConst, qi)
|
||||
}
|
||||
}
|
||||
@@ -421,7 +559,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
valueFloat := cReal - float64(valueInt)
|
||||
|
||||
if valueFloat != 0 {
|
||||
scale = evaluator.ckkscontext.scale
|
||||
scale = evaluator.context.scale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,7 +568,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
valueFloat := cImag - float64(valueInt)
|
||||
|
||||
if valueFloat != 0 {
|
||||
scale = evaluator.ckkscontext.scale
|
||||
scale = evaluator.context.scale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +581,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
valueFloat := cReal - float64(valueInt)
|
||||
|
||||
if valueFloat != 0 {
|
||||
scale = evaluator.ckkscontext.scale
|
||||
scale = evaluator.context.scale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +600,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
|
||||
var scaledConst, scaledConstReal, scaledConstImag uint64
|
||||
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
// If a scaling will be required to multiply by the constant,
|
||||
// equalizes scales such that the scales match in the end.
|
||||
@@ -470,19 +608,19 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
|
||||
// If ctOut scaling is smaller than ct0's scale + the default scaling,
|
||||
// then brings ctOut scale to ct0's scale.
|
||||
if ctOut.Scale() < ct0.Scale()*evaluator.ckkscontext.scale {
|
||||
if ctOut.Scale() < ct0.Scale()*evaluator.context.scale {
|
||||
|
||||
if uint64((evaluator.ckkscontext.scale*ct0.Scale())/ctOut.Scale()) != 0 {
|
||||
if uint64((evaluator.context.scale*ct0.Scale())/ctOut.Scale()) != 0 {
|
||||
|
||||
evaluator.MultByConst(ctOut, uint64((evaluator.ckkscontext.scale*ct0.Scale())/ctOut.Scale()), ctOut)
|
||||
evaluator.MultByConst(ctOut, uint64((evaluator.context.scale*ct0.Scale())/ctOut.Scale()), ctOut)
|
||||
|
||||
}
|
||||
|
||||
ctOut.SetScale(evaluator.ckkscontext.scale * ct0.Scale())
|
||||
ctOut.SetScale(evaluator.context.scale * ct0.Scale())
|
||||
|
||||
// If ctOut.Scale() > ((a+bi)*scale)*ct0(x), then sets the scale to
|
||||
// bring c(x)*scale to the level of ctOut(x) scale
|
||||
} else if ctOut.Scale() > ct0.Scale()*evaluator.ckkscontext.scale {
|
||||
} else if ctOut.Scale() > ct0.Scale()*evaluator.context.scale {
|
||||
scale = ctOut.Scale() / ct0.Scale()
|
||||
}
|
||||
|
||||
@@ -534,7 +672,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
for u := range ct0.Value() {
|
||||
p0tmp := ct0.Value()[u].Coeffs[i]
|
||||
p1tmp := ctOut.Value()[u].Coeffs[i]
|
||||
for j := uint64(0); j < evaluator.ckkscontext.n>>1; j++ {
|
||||
for j := uint64(0); j < evaluator.context.n>>1; j++ {
|
||||
p1tmp[j] = ring.CRed(p1tmp[j]+ring.MRed(p0tmp[j], scaledConst, qi, mredParams), qi)
|
||||
}
|
||||
}
|
||||
@@ -547,7 +685,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
for u := range ct0.Value() {
|
||||
p0tmp := ct0.Value()[u].Coeffs[i]
|
||||
p1tmp := ctOut.Value()[u].Coeffs[i]
|
||||
for j := evaluator.ckkscontext.n >> 1; j < evaluator.ckkscontext.n; j++ {
|
||||
for j := evaluator.context.n >> 1; j < evaluator.context.n; j++ {
|
||||
p1tmp[j] = ring.CRed(p1tmp[j]+ring.MRed(p0tmp[j], scaledConst, qi, mredParams), qi)
|
||||
}
|
||||
}
|
||||
@@ -558,7 +696,7 @@ func (evaluator *Evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interfac
|
||||
// The scale of the output element will depend on the scale of the input element and the constant (if the constant
|
||||
// needs to be scaled (its rational part is not zero)). The constant can be an uint64, int64, float64 or complex128.
|
||||
func (evaluator *Evaluator) MultByConstNew(ct0 *Ciphertext, constant interface{}) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.MultByConst(ct0, constant, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -587,7 +725,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
valueFloat := cReal - float64(valueInt)
|
||||
|
||||
if valueFloat != 0 {
|
||||
scale = evaluator.ckkscontext.scale
|
||||
scale = evaluator.context.scale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,7 +734,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
valueFloat := cImag - float64(valueInt)
|
||||
|
||||
if valueFloat != 0 {
|
||||
scale = evaluator.ckkscontext.scale
|
||||
scale = evaluator.context.scale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,7 +747,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
valueFloat := cReal - float64(valueInt)
|
||||
|
||||
if valueFloat != 0 {
|
||||
scale = evaluator.ckkscontext.scale
|
||||
scale = evaluator.context.scale
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,7 +768,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
// [a + b*psi_qi^2, ....., a + b*psi_qi^2, a - b*psi_qi^2, ...., a - b*psi_qi^2] mod Qi
|
||||
// [{ N/2 }{ N/2 }]
|
||||
// Which is equivalent outside of the NTT domain of adding a to the first coefficient of ct0 and b to the N/2th coefficient of ct0.
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
var scaledConst, scaledConstReal, scaledConstImag uint64
|
||||
for i := uint64(0); i < level+1; i++ {
|
||||
|
||||
@@ -658,7 +796,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
for u := range ct0.Value() {
|
||||
p0tmp := ct0.Value()[u].Coeffs[i]
|
||||
p1tmp := ctOut.Value()[u].Coeffs[i]
|
||||
for j := uint64(0); j < evaluator.ckkscontext.n>>1; j++ {
|
||||
for j := uint64(0); j < evaluator.context.n>>1; j++ {
|
||||
p1tmp[j] = ring.MRed(p0tmp[j], scaledConst, qi, mredParams)
|
||||
}
|
||||
}
|
||||
@@ -671,7 +809,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
for u := range ct0.Value() {
|
||||
p0tmp := ct0.Value()[u].Coeffs[i]
|
||||
p1tmp := ctOut.Value()[u].Coeffs[i]
|
||||
for j := evaluator.ckkscontext.n >> 1; j < evaluator.ckkscontext.n; j++ {
|
||||
for j := evaluator.context.n >> 1; j < evaluator.context.n; j++ {
|
||||
p1tmp[j] = ring.MRed(p0tmp[j], scaledConst, qi, mredParams)
|
||||
}
|
||||
}
|
||||
@@ -683,7 +821,7 @@ func (evaluator *Evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, c
|
||||
// MultByiNew multiplies ct0 by the imaginary number i, and returns the result on a newly created element.
|
||||
// Does not change the scale.
|
||||
func (evaluator *Evaluator) MultByiNew(ct0 *Ciphertext) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(1, ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(1, ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.MultByi(ct0, ctOut)
|
||||
return ctOut
|
||||
}
|
||||
@@ -696,7 +834,7 @@ func (evaluator *Evaluator) MultByi(ct0 *Ciphertext, ct1 *Ciphertext) {
|
||||
|
||||
level = utils.MinUint64(ct0.Level(), ct1.Level())
|
||||
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
var imag uint64
|
||||
|
||||
@@ -732,7 +870,7 @@ func (evaluator *Evaluator) MultByi(ct0 *Ciphertext, ct1 *Ciphertext) {
|
||||
// DivByiNew multiplies ct0 by the imaginary number 1/i = -i, and returns the result on a newly created element.
|
||||
// Does not change the scale.
|
||||
func (evaluator *Evaluator) DivByiNew(ct0 *Ciphertext) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(1, ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(1, ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.DivByi(ct0, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -745,7 +883,7 @@ func (evaluator *Evaluator) DivByi(ct0 *Ciphertext, ct1 *Ciphertext) {
|
||||
|
||||
level = utils.MinUint64(ct0.Level(), ct1.Level())
|
||||
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
var imag uint64
|
||||
|
||||
@@ -780,7 +918,7 @@ func (evaluator *Evaluator) DivByi(ct0 *Ciphertext, ct1 *Ciphertext) {
|
||||
// ScaleUpNew multiplies ct0 by 2^scale and sets its scale to its previous scale
|
||||
// plus 2^n. Returns the result on a newly created element.
|
||||
func (evaluator *Evaluator) ScaleUpNew(ct0 *Ciphertext, scale float64) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.ScaleUp(ct0, scale, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -795,7 +933,7 @@ func (evaluator *Evaluator) ScaleUp(ct0 *Ciphertext, scale float64, ctOut *Ciphe
|
||||
|
||||
// MulByPow2New multiplies the ct0 by 2^pow2 and returns the result on a newly created element.
|
||||
func (evaluator *Evaluator) MulByPow2New(ct0 *Ciphertext, pow2 uint64) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.MulByPow2(ct0.Element(), pow2, ctOut.Element())
|
||||
return
|
||||
}
|
||||
@@ -805,7 +943,7 @@ func (evaluator *Evaluator) MulByPow2(ct0 *ckksElement, pow2 uint64, ctOut *ckks
|
||||
var level uint64
|
||||
level = utils.MinUint64(ct0.Level(), ctOut.Level())
|
||||
for i := range ctOut.Value() {
|
||||
evaluator.ckkscontext.contextQ.MulByPow2Lvl(level, ct0.value[i], pow2, ctOut.Value()[i])
|
||||
evaluator.context.contextQ.MulByPow2Lvl(level, ct0.value[i], pow2, ctOut.Value()[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,7 +951,7 @@ func (evaluator *Evaluator) MulByPow2(ct0 *ckksElement, pow2 uint64, ctOut *ckks
|
||||
// To be used in conjonction with function not applying modular reduction.
|
||||
func (evaluator *Evaluator) ReduceNew(ct0 *Ciphertext) (ctOut *Ciphertext) {
|
||||
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
|
||||
_ = evaluator.Reduce(ct0, ctOut)
|
||||
|
||||
@@ -829,7 +967,7 @@ func (evaluator *Evaluator) Reduce(ct0 *Ciphertext, ctOut *Ciphertext) error {
|
||||
}
|
||||
|
||||
for i := range ct0.value {
|
||||
evaluator.ckkscontext.contextQ.ReduceLvl(utils.MinUint64(ct0.Level(), ctOut.Level()), ct0.value[i], ctOut.value[i])
|
||||
evaluator.context.contextQ.ReduceLvl(utils.MinUint64(ct0.Level(), ctOut.Level()), ct0.value[i], ctOut.value[i])
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -867,7 +1005,7 @@ func (evaluator *Evaluator) DropLevel(ct0 *Ciphertext, levels uint64) (err error
|
||||
// some error.
|
||||
func (evaluator *Evaluator) RescaleNew(ct0 *Ciphertext, threshold float64) (ctOut *Ciphertext, err error) {
|
||||
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
|
||||
return ctOut, evaluator.Rescale(ct0, threshold, ctOut)
|
||||
}
|
||||
@@ -887,7 +1025,7 @@ func (evaluator *Evaluator) Rescale(ct0 *Ciphertext, threshold float64, c1 *Ciph
|
||||
panic("cannot rescale -> reciever ciphertext does not match input ciphertext level")
|
||||
}
|
||||
|
||||
if ct0.Scale() >= (threshold*evaluator.ckkscontext.scalechain[c1.Level()])/2 {
|
||||
if ct0.Scale() >= (threshold*evaluator.context.scalechain[c1.Level()])/2 {
|
||||
|
||||
if !ct0.IsNTT() {
|
||||
panic("cannot rescale -> input ciphertext not in NTT")
|
||||
@@ -895,12 +1033,12 @@ func (evaluator *Evaluator) Rescale(ct0 *Ciphertext, threshold float64, c1 *Ciph
|
||||
|
||||
c1.Copy(ct0.Element())
|
||||
|
||||
for c1.Scale() >= (threshold*evaluator.ckkscontext.scalechain[c1.Level()])/2 && c1.Level() != 0 {
|
||||
for c1.Scale() >= (threshold*evaluator.context.scalechain[c1.Level()])/2 && c1.Level() != 0 {
|
||||
|
||||
c1.DivScale(evaluator.ckkscontext.scalechain[c1.Level()])
|
||||
c1.DivScale(evaluator.context.scalechain[c1.Level()])
|
||||
|
||||
for i := range c1.Value() {
|
||||
evaluator.ckkscontext.contextQ.DivRoundByLastModulusNTT(c1.Value()[i])
|
||||
evaluator.context.contextQ.DivRoundByLastModulusNTT(c1.Value()[i])
|
||||
}
|
||||
|
||||
}
|
||||
@@ -930,11 +1068,11 @@ func (evaluator *Evaluator) RescaleMany(ct0 *Ciphertext, nbRescales uint64, c1 *
|
||||
c1.Copy(ct0.Element())
|
||||
|
||||
for i := uint64(0); i < nbRescales; i++ {
|
||||
c1.DivScale(evaluator.ckkscontext.scalechain[c1.Level()-i])
|
||||
c1.DivScale(evaluator.context.scalechain[c1.Level()-i])
|
||||
}
|
||||
|
||||
for i := range c1.Value() {
|
||||
evaluator.ckkscontext.contextQ.DivRoundByLastModulusManyNTT(c1.Value()[i], nbRescales)
|
||||
evaluator.context.contextQ.DivRoundByLastModulusManyNTT(c1.Value()[i], nbRescales)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -947,7 +1085,7 @@ func (evaluator *Evaluator) RescaleMany(ct0 *Ciphertext, nbRescales uint64, c1 *
|
||||
// the resulting ciphertext will be of degree two. This function only accepts plaintexts (degree zero) and/or ciphertexts of degree one.
|
||||
func (evaluator *Evaluator) MulRelinNew(op0, op1 Operand, evakey *EvaluationKey) (ctOut *Ciphertext) {
|
||||
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(1, utils.MinUint64(op0.Level(), op1.Level()), op0.Scale()+op1.Scale())
|
||||
ctOut = NewCiphertext(1, utils.MinUint64(op0.Level(), op1.Level()), op0.Scale()+op1.Scale(), evaluator.context.contextQ)
|
||||
evaluator.MulRelin(op0, op1, evakey, ctOut)
|
||||
|
||||
return ctOut
|
||||
@@ -982,7 +1120,7 @@ func (evaluator *Evaluator) MulRelin(op0, op1 Operand, evakey *EvaluationKey, ct
|
||||
|
||||
elOut.SetScale(el0.Scale() * el1.Scale())
|
||||
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
var c00, c01, c0, c1, c2 *ring.Poly
|
||||
|
||||
@@ -1003,7 +1141,7 @@ func (evaluator *Evaluator) MulRelin(op0, op1 Operand, evakey *EvaluationKey, ct
|
||||
// resizes the cipher text to a degree 2 ciphertext
|
||||
if evakey == nil {
|
||||
|
||||
elOut.Resize(evaluator.ckkscontext, 2)
|
||||
elOut.Resize(evaluator.context.contextQ, 2)
|
||||
c2 = elOut.value[2]
|
||||
|
||||
// If there is however an evaluation key, then
|
||||
@@ -1050,7 +1188,7 @@ func (evaluator *Evaluator) MulRelin(op0, op1 Operand, evakey *EvaluationKey, ct
|
||||
|
||||
} else { // Or copies the result on the output ciphertext if it was one of the inputs
|
||||
if elOut == el0 || elOut == el1 {
|
||||
elOut.Resize(evaluator.ckkscontext, 2)
|
||||
elOut.Resize(evaluator.context.contextQ, 2)
|
||||
context.CopyLvl(level, c0, elOut.value[0])
|
||||
context.CopyLvl(level, c1, elOut.value[1])
|
||||
context.CopyLvl(level, c2, elOut.value[2])
|
||||
@@ -1080,7 +1218,7 @@ func (evaluator *Evaluator) MulRelin(op0, op1 Operand, evakey *EvaluationKey, ct
|
||||
// RelinearizeNew applies the relinearization procedure on ct0 and returns the result on a newly
|
||||
// created ciphertext. Requires the input ciphertext to be of degree two.
|
||||
func (evaluator *Evaluator) RelinearizeNew(ct0 *Ciphertext, evakey *EvaluationKey) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(1, ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(1, ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.Relinearize(ct0, evakey, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -1096,21 +1234,21 @@ func (evaluator *Evaluator) Relinearize(ct0 *Ciphertext, evakey *EvaluationKey,
|
||||
}
|
||||
|
||||
level := utils.MinUint64(ct0.Level(), ctOut.Level())
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
context.CopyLvl(level, ct0.value[0], ctOut.value[0])
|
||||
context.CopyLvl(level, ct0.value[1], ctOut.value[1])
|
||||
|
||||
evaluator.switchKeysInPlace(ct0.value[2], evakey.evakey, ctOut)
|
||||
|
||||
ctOut.Resize(evaluator.ckkscontext, 1)
|
||||
ctOut.Resize(evaluator.context.contextQ, 1)
|
||||
}
|
||||
|
||||
// SwitchKeysNew re-encrypts ct0 under a different key and returns the result on a newly created element.
|
||||
// Requires a switchinkey, which is computed from the key under which the ciphertext is currently encrypted,
|
||||
// and the key under which the ciphertext will be re-encrypted.
|
||||
func (evaluator *Evaluator) SwitchKeysNew(ct0 *Ciphertext, switchingKey *SwitchingKey) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.SwitchKeys(ct0, switchingKey, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -1125,7 +1263,7 @@ func (evaluator *Evaluator) SwitchKeys(ct0 *Ciphertext, switchingKey *SwitchingK
|
||||
}
|
||||
|
||||
level := utils.MinUint64(ct0.Level(), ctOut.Level())
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
context.CopyLvl(level, ct0.value[0], ctOut.value[0])
|
||||
context.CopyLvl(level, ct0.value[1], ctOut.value[1])
|
||||
@@ -1136,7 +1274,7 @@ func (evaluator *Evaluator) SwitchKeys(ct0 *Ciphertext, switchingKey *SwitchingK
|
||||
// RotateColumnsNew rotates the columns of ct0 by k position to the left, and returns the result on a newly created element.
|
||||
// If the provided element is a ciphertext, a keyswitching operation is necessary and a rotation key for the specific rotation needs to be provided.
|
||||
func (evaluator *Evaluator) RotateColumnsNew(ct0 *Ciphertext, k uint64, evakey *RotationKeys) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.RotateColumns(ct0, k, evakey, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -1149,7 +1287,7 @@ func (evaluator *Evaluator) RotateColumns(ct0 *Ciphertext, k uint64, evakey *Rot
|
||||
panic("cannot rotate -> input and output ciphertext must be of degree 1")
|
||||
}
|
||||
|
||||
k &= ((evaluator.ckkscontext.n >> 1) - 1)
|
||||
k &= ((evaluator.context.n >> 1) - 1)
|
||||
|
||||
if k == 0 {
|
||||
|
||||
@@ -1168,7 +1306,7 @@ func (evaluator *Evaluator) RotateColumns(ct0 *Ciphertext, k uint64, evakey *Rot
|
||||
|
||||
// If not looks if the left and right pow2 rotations have been generated
|
||||
hasPow2Rotations := true
|
||||
for i := uint64(1); i < evaluator.ckkscontext.n>>1; i <<= 1 {
|
||||
for i := uint64(1); i < evaluator.context.n>>1; i <<= 1 {
|
||||
if evakey.evakeyRotColLeft[i] == nil || evakey.evakeyRotColRight[i] == nil {
|
||||
hasPow2Rotations = false
|
||||
break
|
||||
@@ -1178,10 +1316,10 @@ func (evaluator *Evaluator) RotateColumns(ct0 *Ciphertext, k uint64, evakey *Rot
|
||||
// If yes, computes the least amount of rotation between left and right required to apply the demanded rotation
|
||||
if hasPow2Rotations {
|
||||
|
||||
if utils.HammingWeight64(k) <= utils.HammingWeight64((evaluator.ckkscontext.n>>1)-k) {
|
||||
if utils.HammingWeight64(k) <= utils.HammingWeight64((evaluator.context.n>>1)-k) {
|
||||
evaluator.rotateColumnsLPow2(ct0, k, evakey, ctOut)
|
||||
} else {
|
||||
evaluator.rotateColumnsRPow2(ct0, (evaluator.ckkscontext.n>>1)-k, evakey, ctOut)
|
||||
evaluator.rotateColumnsRPow2(ct0, (evaluator.context.n>>1)-k, evakey, ctOut)
|
||||
}
|
||||
|
||||
// Else returns an error indicating that the keys have not been generated
|
||||
@@ -1197,17 +1335,17 @@ func (evaluator *Evaluator) RotateColumns(ct0 *Ciphertext, k uint64, evakey *Rot
|
||||
func (evaluator *Evaluator) RotateHoisted(ctIn *Ciphertext, rotations []uint64, rotkeys *RotationKeys) (cOut map[uint64]*Ciphertext) {
|
||||
|
||||
// Pre-computation for rotations using hoisting
|
||||
contextQ := evaluator.ckkscontext.contextQ
|
||||
contextP := evaluator.ckkscontext.contextP
|
||||
contextQ := evaluator.context.contextQ
|
||||
contextP := evaluator.context.contextP
|
||||
|
||||
c2NTT := ctIn.value[1]
|
||||
c2InvNTT := contextQ.NewPoly()
|
||||
contextQ.InvNTTLvl(ctIn.Level(), c2NTT, c2InvNTT)
|
||||
|
||||
c2QiQDecomp := make([]*ring.Poly, evaluator.ckkscontext.beta)
|
||||
c2QiPDecomp := make([]*ring.Poly, evaluator.ckkscontext.beta)
|
||||
c2QiQDecomp := make([]*ring.Poly, evaluator.context.beta)
|
||||
c2QiPDecomp := make([]*ring.Poly, evaluator.context.beta)
|
||||
|
||||
alpha := evaluator.ckkscontext.alpha
|
||||
alpha := evaluator.context.alpha
|
||||
beta := uint64(math.Ceil(float64(ctIn.Level()+1) / float64(alpha)))
|
||||
|
||||
for i := uint64(0); i < beta; i++ {
|
||||
@@ -1220,12 +1358,12 @@ func (evaluator *Evaluator) RotateHoisted(ctIn *Ciphertext, rotations []uint64,
|
||||
|
||||
for _, i := range rotations {
|
||||
|
||||
i &= ((evaluator.ckkscontext.n >> 1) - 1)
|
||||
i &= ((evaluator.context.n >> 1) - 1)
|
||||
|
||||
if i == 0 {
|
||||
cOut[i] = ctIn.CopyNew().Ciphertext()
|
||||
} else {
|
||||
cOut[i] = evaluator.ckkscontext.NewCiphertext(1, ctIn.Level(), ctIn.Scale())
|
||||
cOut[i] = NewCiphertext(1, ctIn.Level(), ctIn.Scale(), evaluator.context.contextQ)
|
||||
evaluator.switchKeyHoisted(ctIn, c2QiQDecomp, c2QiPDecomp, i, rotkeys, cOut[i])
|
||||
}
|
||||
}
|
||||
@@ -1251,8 +1389,8 @@ func (evaluator *Evaluator) switchKeyHoisted(ctIn *Ciphertext, c2QiQDecomp, c2Qi
|
||||
|
||||
level = ctOut.Level()
|
||||
|
||||
contextQ := evaluator.ckkscontext.contextQ
|
||||
contextP := evaluator.ckkscontext.contextP
|
||||
contextQ := evaluator.context.contextQ
|
||||
contextP := evaluator.context.contextP
|
||||
|
||||
if ctIn != ctOut {
|
||||
ring.PermuteNTTWithIndex(ctIn.value[0], evakey.permuteNTTLeftIndex[k], evaluator.ringpool[0])
|
||||
@@ -1283,7 +1421,7 @@ func (evaluator *Evaluator) switchKeyHoisted(ctIn *Ciphertext, c2QiQDecomp, c2Qi
|
||||
|
||||
reduce = 0
|
||||
|
||||
alpha := evaluator.ckkscontext.alpha
|
||||
alpha := evaluator.context.alpha
|
||||
beta := uint64(math.Ceil(float64(level+1) / float64(alpha)))
|
||||
|
||||
// Key switching with crt decomposition for the Qi
|
||||
@@ -1296,7 +1434,7 @@ func (evaluator *Evaluator) switchKeyHoisted(ctIn *Ciphertext, c2QiQDecomp, c2Qi
|
||||
contextQ.MulCoeffsMontgomeryAndAddNoModLvl(level, evakey.evakeyRotColLeft[k].evakey[i][1], c2QiQPermute, pool3Q)
|
||||
|
||||
// We continue with the keyswitch primes.
|
||||
for j, keysindex := uint64(0), evaluator.ckkscontext.levels; j < uint64(len(evaluator.ckkscontext.specialprimes)); j, keysindex = j+1, keysindex+1 {
|
||||
for j, keysindex := uint64(0), evaluator.context.levels; j < uint64(len(evaluator.context.specialprimes)); j, keysindex = j+1, keysindex+1 {
|
||||
|
||||
pj := contextP.Modulus[j]
|
||||
mredParams := contextP.GetMredParams()[j]
|
||||
@@ -1332,8 +1470,8 @@ func (evaluator *Evaluator) switchKeyHoisted(ctIn *Ciphertext, c2QiQDecomp, c2Qi
|
||||
|
||||
//Independant of context (parameter : level)
|
||||
// Computes pool2Q = pool2Q/pool2P and pool3Q = pool3Q/pool3P
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.ckkscontext.rescaleParamsKeys, level, pool2Q, pool2P, pool2Q, evaluator.keyswitchpool[0])
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.ckkscontext.rescaleParamsKeys, level, pool3Q, pool3P, pool3Q, evaluator.keyswitchpool[0])
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.context.rescaleParamsKeys, level, pool2Q, pool2P, pool2Q, evaluator.keyswitchpool[0])
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.context.rescaleParamsKeys, level, pool3Q, pool3P, pool3Q, evaluator.keyswitchpool[0])
|
||||
|
||||
//Independant of context (parameter : level)
|
||||
contextQ.AddLvl(level, ctOut.value[0], pool2Q, ctOut.value[0])
|
||||
@@ -1355,7 +1493,7 @@ func (evaluator *Evaluator) rotateColumnsPow2(ct0 *Ciphertext, k uint64, permute
|
||||
evakeyIndex = 1
|
||||
|
||||
level := utils.MinUint64(ct0.Level(), ctOut.Level())
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
context.CopyLvl(level, ct0.value[0], ctOut.value[0])
|
||||
context.CopyLvl(level, ct0.value[1], ctOut.value[1])
|
||||
@@ -1376,7 +1514,7 @@ func (evaluator *Evaluator) rotateColumnsPow2(ct0 *Ciphertext, k uint64, permute
|
||||
// created element. If the provided element is a ciphertext, a keyswitching operation is necessary and a rotation key
|
||||
// for the row rotation needs to be provided.
|
||||
func (evaluator *Evaluator) ConjugateNew(ct0 *Ciphertext, evakey *RotationKeys) (ctOut *Ciphertext) {
|
||||
ctOut = evaluator.ckkscontext.NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale())
|
||||
ctOut = NewCiphertext(ct0.Degree(), ct0.Level(), ct0.Scale(), evaluator.context.contextQ)
|
||||
evaluator.Conjugate(ct0, evakey, ctOut)
|
||||
return
|
||||
}
|
||||
@@ -1412,7 +1550,7 @@ func (evaluator *Evaluator) permuteNTT(ct0 *Ciphertext, index []uint64, evakey *
|
||||
ring.PermuteNTTWithIndex(ct0.value[1], index, el1)
|
||||
|
||||
level := utils.MinUint64(ct0.Level(), ctOut.Level())
|
||||
context := evaluator.ckkscontext.contextQ
|
||||
context := evaluator.context.contextQ
|
||||
|
||||
context.CopyLvl(level, el0, ctOut.value[0])
|
||||
context.CopyLvl(level, el1, ctOut.value[1])
|
||||
@@ -1426,8 +1564,8 @@ func (evaluator *Evaluator) switchKeysInPlace(cx *ring.Poly, evakey *SwitchingKe
|
||||
|
||||
level = ctOut.Level()
|
||||
|
||||
contextQ := evaluator.ckkscontext.contextQ
|
||||
contextP := evaluator.ckkscontext.contextP
|
||||
contextQ := evaluator.context.contextQ
|
||||
contextP := evaluator.context.contextP
|
||||
|
||||
for i := range evaluator.poolQ {
|
||||
evaluator.poolQ[i].Zero()
|
||||
@@ -1456,7 +1594,7 @@ func (evaluator *Evaluator) switchKeysInPlace(cx *ring.Poly, evakey *SwitchingKe
|
||||
|
||||
reduce = 0
|
||||
|
||||
alpha := evaluator.ckkscontext.alpha
|
||||
alpha := evaluator.context.alpha
|
||||
beta := uint64(math.Ceil(float64(level+1) / float64(alpha)))
|
||||
|
||||
// Key switching with crt decomposition for the Qi
|
||||
@@ -1468,7 +1606,7 @@ func (evaluator *Evaluator) switchKeysInPlace(cx *ring.Poly, evakey *SwitchingKe
|
||||
contextQ.MulCoeffsMontgomeryAndAddNoModLvl(level, evakey.evakey[i][1], c2QiQ, pool3Q)
|
||||
|
||||
// We continue with the keyswitch primes.
|
||||
for j, keysindex := uint64(0), evaluator.ckkscontext.levels; j < uint64(len(evaluator.ckkscontext.specialprimes)); j, keysindex = j+1, keysindex+1 {
|
||||
for j, keysindex := uint64(0), evaluator.context.levels; j < uint64(len(evaluator.context.specialprimes)); j, keysindex = j+1, keysindex+1 {
|
||||
|
||||
pj := contextP.Modulus[j]
|
||||
mredParams := contextP.GetMredParams()[j]
|
||||
@@ -1505,8 +1643,8 @@ func (evaluator *Evaluator) switchKeysInPlace(cx *ring.Poly, evakey *SwitchingKe
|
||||
|
||||
//Independant of context (parameter : level)
|
||||
// Computes pool2Q = pool2Q/pool2P and pool3Q = pool3Q/pool3P
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.ckkscontext.rescaleParamsKeys, level, pool2Q, pool2P, pool2Q, evaluator.keyswitchpool[0])
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.ckkscontext.rescaleParamsKeys, level, pool3Q, pool3P, pool3Q, evaluator.keyswitchpool[0])
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.context.rescaleParamsKeys, level, pool2Q, pool2P, pool2Q, evaluator.keyswitchpool[0])
|
||||
evaluator.baseconverter.ModDownSplitedNTT(contextQ, contextP, evaluator.context.rescaleParamsKeys, level, pool3Q, pool3P, pool3Q, evaluator.keyswitchpool[0])
|
||||
|
||||
//Independant of context (parameter : level)
|
||||
contextQ.AddLvl(level, ctOut.value[0], pool2Q, ctOut.value[0])
|
||||
@@ -1517,12 +1655,12 @@ func (evaluator *Evaluator) decomposeAndSplitNTT(level, beta uint64, c2NTT, c2In
|
||||
|
||||
// Decomposes the input polynomial into the target CRT basis.
|
||||
|
||||
contextQ := evaluator.ckkscontext.contextQ
|
||||
contextP := evaluator.ckkscontext.contextP
|
||||
contextQ := evaluator.context.contextQ
|
||||
contextP := evaluator.context.contextP
|
||||
|
||||
evaluator.decomposer.DecomposeAndSplit(level, beta, c2InvNTT, c2QiQ, c2QiP)
|
||||
|
||||
p0idxst := beta * evaluator.ckkscontext.alpha
|
||||
p0idxst := beta * evaluator.context.alpha
|
||||
p0idxed := p0idxst + evaluator.decomposer.Xalpha()[beta]
|
||||
|
||||
// c2_qi = cx mod qi mod qi
|
||||
|
||||
@@ -75,12 +75,12 @@ func (el *ckksElement) DivScale(scale float64) {
|
||||
}
|
||||
|
||||
// Resize resizes the degree of the target element.
|
||||
func (el *ckksElement) Resize(ckkscontext *Context, degree uint64) {
|
||||
func (el *ckksElement) Resize(ringCtx *ring.Context, degree uint64) {
|
||||
if el.Degree() > degree {
|
||||
el.value = el.value[:degree+1]
|
||||
} else if el.Degree() < degree {
|
||||
for el.Degree() < degree {
|
||||
el.value = append(el.value, []*ring.Poly{ckkscontext.contextQ.NewPolyLvl(el.Level())}...)
|
||||
el.value = append(el.value, []*ring.Poly{ringCtx.NewPolyLvl(el.Level())}...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func computePowerBasis(n uint64, C map[uint64]*Ciphertext, evaluator *Evaluator,
|
||||
// Computes C[n] = C[a]*C[b]
|
||||
C[n] = evaluator.MulRelinNew(C[a], C[b], evakey)
|
||||
|
||||
evaluator.Rescale(C[n], evaluator.ckkscontext.scale, C[n])
|
||||
evaluator.Rescale(C[n], evaluator.context.scale, C[n])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func recurse(maxDegree, L, M uint64, coeffs map[uint64]complex128, C map[uint64]
|
||||
|
||||
evaluator.Add(res, tmp, res)
|
||||
|
||||
evaluator.Rescale(res, evaluator.ckkscontext.scale, res)
|
||||
evaluator.Rescale(res, evaluator.context.scale, res)
|
||||
|
||||
return res
|
||||
|
||||
@@ -141,7 +141,7 @@ func recurse(maxDegree, L, M uint64, coeffs map[uint64]complex128, C map[uint64]
|
||||
|
||||
func evaluatePolyFromPowerBasis(coeffs map[uint64]complex128, C map[uint64]*Ciphertext, evaluator *Evaluator, evakey *EvaluationKey) (res *Ciphertext) {
|
||||
|
||||
res = evaluator.ckkscontext.NewCiphertext(1, C[1].Level(), C[1].Scale())
|
||||
res = NewCiphertext(1, C[1].Level(), C[1].Scale(), evaluator.context.contextQ)
|
||||
|
||||
if math.Abs(real(coeffs[0])) > 1e-15 || math.Abs(imag(coeffs[0])) > 1e-15 {
|
||||
evaluator.AddConst(res, coeffs[0], res)
|
||||
@@ -153,7 +153,7 @@ func evaluatePolyFromPowerBasis(coeffs map[uint64]complex128, C map[uint64]*Ciph
|
||||
}
|
||||
}
|
||||
|
||||
evaluator.Rescale(res, evaluator.ckkscontext.scale, res)
|
||||
evaluator.Rescale(res, evaluator.context.scale, res)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -371,6 +371,8 @@ func benchRefresh(b *testing.B) {
|
||||
contextKeys := bfvContext.ContextKeys()
|
||||
sk0Shards := params.sk0Shards
|
||||
|
||||
ringCtx := bfv.NewCiphertextRingContext(¶meters)
|
||||
|
||||
type Party struct {
|
||||
*RefreshProtocol
|
||||
s *ring.Poly
|
||||
@@ -403,13 +405,6 @@ func benchRefresh(b *testing.B) {
|
||||
})
|
||||
|
||||
b.Run(testString("Finalize", ¶meters), func(b *testing.B) {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctOut := bfv.NewCiphertext(1, ringCtx)
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.Finalize(ciphertext, crp, p.share, ctOut) // TODO: why does this fail ?
|
||||
|
||||
@@ -165,12 +165,7 @@ func testRelinKeyGen(t *testing.T) {
|
||||
parties := testParams.parties
|
||||
|
||||
for _, parameters := range testParams.contexts {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(¶meters)
|
||||
|
||||
params := genDBFVContext(¶meters)
|
||||
|
||||
@@ -263,12 +258,7 @@ func testRelinKeyGenNaive(t *testing.T) {
|
||||
parties := testParams.parties
|
||||
|
||||
for _, parameters := range testParams.contexts {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(¶meters)
|
||||
|
||||
params := genDBFVContext(¶meters)
|
||||
|
||||
@@ -344,12 +334,7 @@ func testKeyswitching(t *testing.T) {
|
||||
parties := testParams.parties
|
||||
|
||||
for _, parameters := range testParams.contexts {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(¶meters)
|
||||
|
||||
params := genDBFVContext(¶meters)
|
||||
|
||||
@@ -408,12 +393,7 @@ func testPublicKeySwitching(t *testing.T) {
|
||||
parties := testParams.parties
|
||||
|
||||
for _, parameters := range testParams.contexts {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(¶meters)
|
||||
|
||||
params := genDBFVContext(¶meters)
|
||||
|
||||
@@ -529,12 +509,7 @@ func testRotKeyGenRotCols(t *testing.T) {
|
||||
parties := testParams.parties
|
||||
|
||||
for _, parameters := range testParams.contexts {
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(parameters.N, parameters.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(¶meters)
|
||||
|
||||
params := genDBFVContext(¶meters)
|
||||
|
||||
|
||||
@@ -373,7 +373,9 @@ func benchRefresh(b *testing.B) {
|
||||
crpGenerator.Seed([]byte{})
|
||||
crp := crpGenerator.ClockNew()
|
||||
|
||||
ciphertext := ckksContext.NewCiphertext(1, levelStart, ckksContext.Scale())
|
||||
ringCtx := ckks.NewCiphertextRingContext(parameters)
|
||||
|
||||
ciphertext := ckks.NewCiphertext(1, levelStart, ckksContext.Scale(), ringCtx)
|
||||
|
||||
ckksContext.ContextQ().UniformPoly(ciphertext.Value()[0])
|
||||
ckksContext.ContextQ().UniformPoly(ciphertext.Value()[1])
|
||||
|
||||
@@ -78,7 +78,7 @@ func genDCKKSContext(contextParameters *ckks.Parameters) (params *dckksContext)
|
||||
params.ckksContext = ckks.NewContext(contextParameters)
|
||||
|
||||
params.encoder = ckks.NewEncoder(contextParameters)
|
||||
params.evaluator = params.ckksContext.NewEvaluator()
|
||||
params.evaluator = ckks.NewEvaluator(contextParameters)
|
||||
|
||||
kgen := params.ckksContext.NewKeyGenerator()
|
||||
|
||||
@@ -105,7 +105,7 @@ func genDCKKSContext(contextParameters *ckks.Parameters) (params *dckksContext)
|
||||
params.pk0 = kgen.NewPublicKey(params.sk0)
|
||||
params.pk1 = kgen.NewPublicKey(params.sk1)
|
||||
|
||||
params.encryptorPk0 = params.ckksContext.NewEncryptorFromPk(params.pk0)
|
||||
params.encryptorPk0 = ckks.NewEncryptorFromPk(params.pk0, contextParameters)
|
||||
|
||||
params.decryptorSk0 = params.ckksContext.NewDecryptor(params.sk0)
|
||||
|
||||
@@ -166,7 +166,7 @@ func testPublicKeyGen(t *testing.T) {
|
||||
P0.GenPublicKey(P0.s1, crp, pk)
|
||||
|
||||
// Verifies that decrypt((encryptp(collectiveSk, m), collectivePk) = m
|
||||
encryptorTest := ckksContext.NewEncryptorFromPk(pk)
|
||||
encryptorTest := ckks.NewEncryptorFromPk(pk, parameters)
|
||||
|
||||
coeffs, _, ciphertext := newTestVectors(params, encryptorTest, 1, t)
|
||||
|
||||
@@ -369,6 +369,8 @@ func testKeyswitching(t *testing.T) {
|
||||
sk0Shards := params.sk0Shards
|
||||
sk1Shards := params.sk1Shards
|
||||
|
||||
ringCtx := ckks.NewCiphertextRingContext(parameters)
|
||||
|
||||
t.Run(fmt.Sprintf("parties=%d/logN=%d/logQ=%d/levels=%d/scale=%f",
|
||||
parties,
|
||||
ckksContext.LogN(),
|
||||
@@ -405,7 +407,7 @@ func testKeyswitching(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
ksCiphertext := ckksContext.NewCiphertext(1, ciphertext.Level(), ciphertext.Scale())
|
||||
ksCiphertext := ckks.NewCiphertext(1, ciphertext.Level(), ciphertext.Scale(), ringCtx)
|
||||
|
||||
P0.KeySwitch(P0.share, ciphertext, ksCiphertext)
|
||||
|
||||
@@ -433,6 +435,8 @@ func testPublicKeySwitching(t *testing.T) {
|
||||
sk0Shards := params.sk0Shards
|
||||
pk1 := params.pk1
|
||||
|
||||
ringCtx := ckks.NewCiphertextRingContext(parameters)
|
||||
|
||||
t.Run(fmt.Sprintf("parties=%d/logN=%d/logQ=%d/levels=%d/scale=%f",
|
||||
parties,
|
||||
ckksContext.LogN(),
|
||||
@@ -461,7 +465,7 @@ func testPublicKeySwitching(t *testing.T) {
|
||||
}
|
||||
P0 := pcksParties[0]
|
||||
|
||||
ciphertextSwitched := ckksContext.NewCiphertext(1, ciphertext.Level(), ciphertext.Scale())
|
||||
ciphertextSwitched := ckks.NewCiphertext(1, ciphertext.Level(), ciphertext.Scale(), ringCtx)
|
||||
|
||||
for i, p := range pcksParties {
|
||||
p.GenShare(p.s, pk1, ciphertext, p.share)
|
||||
@@ -559,6 +563,8 @@ func testRotKeyGenCols(t *testing.T) {
|
||||
decryptorSk0 := params.decryptorSk0
|
||||
sk0Shards := params.sk0Shards
|
||||
|
||||
ringCtx := ckks.NewCiphertextRingContext(parameters)
|
||||
|
||||
t.Run(fmt.Sprintf("parties=%d/logN=%d/logQ=%d/levels=%d/scale=%f", parties, ckksContext.LogN(), ckksContext.LogQ(), ckksContext.Levels(), ckksContext.Scale()), func(t *testing.T) {
|
||||
|
||||
type Party struct {
|
||||
@@ -590,7 +596,7 @@ func testRotKeyGenCols(t *testing.T) {
|
||||
|
||||
coeffs, _, ciphertext := newTestVectors(params, encryptorPk0, 1, t)
|
||||
|
||||
receiver := ckksContext.NewCiphertext(ciphertext.Degree(), ciphertext.Level(), ciphertext.Scale())
|
||||
receiver := ckks.NewCiphertext(ciphertext.Degree(), ciphertext.Level(), ciphertext.Scale(), ringCtx)
|
||||
|
||||
for k := uint64(1); k < contextKeys.N>>1; k <<= 1 {
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ func chebyshevinterpolation() {
|
||||
|
||||
// Encryptor
|
||||
var encryptor *ckks.Encryptor
|
||||
encryptor = ckkscontext.NewEncryptorFromPk(pk)
|
||||
encryptor = ckks.NewEncryptorFromPk(pk, params)
|
||||
|
||||
// Decryptor
|
||||
var decryptor *ckks.Decryptor
|
||||
@@ -55,7 +55,7 @@ func chebyshevinterpolation() {
|
||||
|
||||
// Evaluator
|
||||
var evaluator *ckks.Evaluator
|
||||
evaluator = ckkscontext.NewEvaluator()
|
||||
evaluator = ckks.NewEvaluator(params)
|
||||
|
||||
// Values to encrypt
|
||||
values := make([]complex128, ckkscontext.Slots())
|
||||
|
||||
@@ -231,12 +231,7 @@ func main() {
|
||||
plainMask := make([]*bfv.Plaintext, N, N)
|
||||
encPartial := make([]*bfv.Ciphertext, N, N)
|
||||
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(params.N, params.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(params)
|
||||
|
||||
// Ciphertexts to be retrieved.
|
||||
for i := range encInputs {
|
||||
|
||||
@@ -172,12 +172,7 @@ func main() {
|
||||
l.Printf("\tSetup done (cloud: %s, party: %s)\n",
|
||||
elapsedRKGCloud+elapsedCKGCloud, elapsedRKGParty+elapsedCKGParty)
|
||||
|
||||
ringCtx := ring.NewContext()
|
||||
ringCtx.SetParameters(params.N, params.Qi)
|
||||
err = ringCtx.GenNTTParams()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ringCtx := bfv.NewCiphertextRingContext(params)
|
||||
|
||||
// Pre-loading memory
|
||||
l.Println("> Memory alloc Phase")
|
||||
|
||||
Reference in New Issue
Block a user