mirror of
https://github.com/luxfi/lattice.git
synced 2026-09-24 00:25:44 +00:00
- Update module path to github.com/luxfi/lattice/v7 - Add GPU acceleration with Metal (macOS) and CUDA backends - Enhance threshold FHE operations - Revert to vanilla Apache 2.0 license (remove tfhe) - Update Go version to 1.25.5 - Merge upstream lattigo improvements
121 lines
2.8 KiB
Go
121 lines
2.8 KiB
Go
package bgv
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"slices"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/luxfi/lattice/v7/core/rlwe"
|
|
"github.com/luxfi/lattice/v7/ring"
|
|
"github.com/luxfi/lattice/v7/utils/sampling"
|
|
)
|
|
|
|
type TestContext struct {
|
|
Params Parameters
|
|
Ecd *Encoder
|
|
|
|
Prng sampling.PRNG
|
|
Sampler *ring.UniformSampler
|
|
|
|
Kgen *rlwe.KeyGenerator
|
|
Sk *rlwe.SecretKey
|
|
Pk *rlwe.PublicKey
|
|
|
|
Enc *rlwe.Encryptor
|
|
Dec *rlwe.Decryptor
|
|
|
|
Evl *Evaluator
|
|
}
|
|
|
|
func NewTestContext(params ParametersLiteral, scaleInvariant bool) *TestContext {
|
|
tc := new(TestContext)
|
|
|
|
var err error
|
|
|
|
tc.Params, err = NewParametersFromLiteral(params)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
tc.Ecd = NewEncoder(tc.Params)
|
|
|
|
tc.Prng, err = sampling.NewPRNG()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
tc.Sampler = ring.NewUniformSampler(tc.Prng, tc.Params.RingT())
|
|
|
|
tc.Kgen = rlwe.NewKeyGenerator(tc.Params)
|
|
tc.Sk, tc.Pk = tc.Kgen.GenKeyPairNew()
|
|
|
|
tc.Enc = rlwe.NewEncryptor(tc.Params, tc.Pk)
|
|
tc.Dec = rlwe.NewDecryptor(tc.Params, tc.Sk)
|
|
|
|
tc.Evl = NewEvaluator(tc.Params, rlwe.NewMemEvaluationKeySet(tc.Kgen.GenRelinearizationKeyNew(tc.Sk)), scaleInvariant)
|
|
|
|
return tc
|
|
}
|
|
|
|
func (tc TestContext) String() string {
|
|
return fmt.Sprintf("LogN=%d/logQ=%d/logP=%d/LogSlots=%dx%d/logT=%d/Qi=%d/Pi=%d",
|
|
tc.Params.LogN(),
|
|
int(math.Round(tc.Params.LogQ())),
|
|
int(math.Round(tc.Params.LogP())),
|
|
tc.Params.LogMaxDimensions().Rows,
|
|
tc.Params.LogMaxDimensions().Cols,
|
|
int(math.Round(tc.Params.LogT())),
|
|
tc.Params.QCount(),
|
|
tc.Params.PCount())
|
|
}
|
|
|
|
func VerifyTestVectors(params Parameters, encoder *Encoder, decryptor *rlwe.Decryptor, have interface{}, want []uint64, isBatched bool, t *testing.T) {
|
|
var values []uint64
|
|
if isBatched {
|
|
values = make([]uint64, params.MaxSlots())
|
|
} else {
|
|
values = make([]uint64, params.N())
|
|
}
|
|
|
|
switch have := have.(type) {
|
|
case *rlwe.Plaintext:
|
|
require.NoError(t, encoder.Decode(have, values))
|
|
case *rlwe.Ciphertext:
|
|
require.NoError(t, encoder.Decode(decryptor.DecryptNew(have), values))
|
|
default:
|
|
t.Error("invalid unsupported test object type")
|
|
}
|
|
|
|
fmt.Println("have", values[:10])
|
|
fmt.Println("want", want[:10])
|
|
require.True(t, slices.Equal(values, want))
|
|
}
|
|
|
|
func NewTestVector(params Parameters, encoder *Encoder, encryptor *rlwe.Encryptor, level int, scale rlwe.Scale, batched bool) (values []uint64, pt *rlwe.Plaintext, ct *rlwe.Ciphertext) {
|
|
if batched {
|
|
values = make([]uint64, params.MaxSlots())
|
|
} else {
|
|
values = make([]uint64, params.N())
|
|
}
|
|
|
|
for i := range values {
|
|
values[i] = sampling.RandUint64() % params.PlaintextModulus()
|
|
}
|
|
|
|
pt = NewPlaintext(params, level)
|
|
pt.IsBatched = batched
|
|
pt.Scale = scale
|
|
if err := encoder.Encode(values, pt); err != nil {
|
|
panic(err)
|
|
}
|
|
if encryptor != nil {
|
|
var err error
|
|
ct, err = encryptor.EncryptNew(pt)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
return
|
|
}
|