Skip to content

Commit

Permalink
prepared ckks support, bgv tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianMct committed Apr 3, 2024
1 parent 3475db4 commit e47c18c
Show file tree
Hide file tree
Showing 19 changed files with 377 additions and 367 deletions.
44 changes: 15 additions & 29 deletions circuits/circuits.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
package circuits

import (
"context"
"fmt"

"github.com/ChristianMct/helium"
"github.com/ChristianMct/helium/protocols"
"github.com/ChristianMct/helium/session"
"github.com/ChristianMct/helium/utils"
"github.com/tuneinsight/lattigo/v5/core/rlwe"
"github.com/tuneinsight/lattigo/v5/ring"
"github.com/tuneinsight/lattigo/v5/ring/ringqp"
"github.com/tuneinsight/lattigo/v5/schemes/bgv"
"github.com/tuneinsight/lattigo/v5/he"
)

// Circuit is a type for representing circuits, which are Go functions interacting with
Expand All @@ -20,6 +20,8 @@ type Circuit func(Runtime) error
// Runtime defines the interface that is available to circuits to access
// their execution context.
type Runtime interface {
Parameters() session.FHEParameters

// Input reads an input operand with the given label from the context.
// When specifying the label, the user:
// - can use a placeholder id for the node, the mapping for which is provided in the Signature.
Expand All @@ -36,7 +38,9 @@ type Runtime interface {
// When specifying the label, the user:
// - can use a placeholder id for the node, the mapping for which is provided in the Signature.
// - can omit the session-id part as it wil be automatically resolved by the runtime.
NewOperand(OperandLabel) Operand
NewOperand(OperandLabel) *Operand

EvalLocal(needRlk bool, galKeys []uint64, f func(he.Evaluator) error) error // TODO Eval once freed // TODO NEXT: node allocates evaluators and pass them here.

// DEC performes the decryption of in, with private output to rec.
// The decrypted operand is considered an output for the this circuit and the
Expand All @@ -51,14 +55,14 @@ type Runtime interface {
// It expect the users to provide the key-switch parameters, including the level
// at which the operation is performed and the smudging parameter.
PCKS(in Operand, rec helium.NodeID, params map[string]string) error
}

// Parameters returns the encryption parameters for the circuit.
Parameters() bgv.Parameters

// NewEvaluator returns a new evaluator to be used in this circuit.
NewEvaluator() Evaluator

Evaluator
// PublicKeyProvider is an interface for querying public encryption- and evaluation-keys.
// The setup service is a notable implementation of this interface.
type PublicKeyProvider interface {
GetCollectivePublicKey(context.Context) (*rlwe.PublicKey, error)
GetGaloisKey(ctx context.Context, galEl uint64) (*rlwe.GaloisKey, error)
GetRelinearizationKey(context.Context) (*rlwe.RelinearizationKey, error)
}

// Name is a type for circuit names.
Expand Down Expand Up @@ -125,24 +129,6 @@ type Output struct {
Operand
}

// Evaluator is an interface that is directly supported by circuit runtimes.
type Evaluator interface {
Add(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error)
Sub(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error)
Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error)
MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error)
MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error)
MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error)
MulThenAdd(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error)
Relinearize(op0, op1 *rlwe.Ciphertext) (err error)
Rescale(op0, op1 *rlwe.Ciphertext) (err error)
InnerSum(ctIn *rlwe.Ciphertext, batchSize, n int, opOut *rlwe.Ciphertext) (err error)
AutomorphismHoisted(level int, ctIn *rlwe.Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, opOut *rlwe.Ciphertext) (err error)

DecomposeNTT(levelQ, levelP, nbPi int, c2 ring.Poly, c2IsNTT bool, decompQP []ringqp.Poly)
NewDecompQPBuffer() []ringqp.Poly
}

var statusToString = []string{"COMPLETED", "STARTED", "EXECUTING", "FAILED"}

func (t EventType) String() string {
Expand Down
212 changes: 109 additions & 103 deletions circuits/parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ import (

"github.com/ChristianMct/helium"
"github.com/ChristianMct/helium/protocols"
"github.com/ChristianMct/helium/session"
"github.com/ChristianMct/helium/utils"
"github.com/tuneinsight/lattigo/v5/core/rlwe"
"github.com/tuneinsight/lattigo/v5/ring"
"github.com/tuneinsight/lattigo/v5/ring/ringqp"
"github.com/tuneinsight/lattigo/v5/schemes/bgv"
"github.com/tuneinsight/lattigo/v5/he"
)

// Parse parses a circuit and returns its metadata.
// The parsing is done by symbolic execution of the circuit.
func Parse(c Circuit, cd Descriptor, params bgv.Parameters) (*Metadata, error) {
func Parse(c Circuit, cd Descriptor, params session.FHEParameters) (*Metadata, error) {
dummyCtx := newCircuitParserCtx(cd, params)
if err := c(dummyCtx); err != nil {
return nil, fmt.Errorf("error while parsing circuit: %w", err)
Expand All @@ -26,15 +24,15 @@ func Parse(c Circuit, cd Descriptor, params bgv.Parameters) (*Metadata, error) {
}

type circuitParserContext struct {
dummyEvaluator
//dummyEvaluator
cd Descriptor
md Metadata
SubCtx map[helium.CircuitID]*circuitParserContext
params bgv.Parameters
params session.FHEParameters
l sync.Mutex
}

func newCircuitParserCtx(cd Descriptor, params bgv.Parameters) *circuitParserContext {
func newCircuitParserCtx(cd Descriptor, params session.FHEParameters) *circuitParserContext {
cpc := &circuitParserContext{
cd: cd,
md: Metadata{
Expand All @@ -50,7 +48,7 @@ func newCircuitParserCtx(cd Descriptor, params bgv.Parameters) *circuitParserCon
SubCtx: make(map[helium.CircuitID]*circuitParserContext, 0),
params: params,
}
cpc.dummyEvaluator.ctx = cpc
//cpc.dummyEvaluator.ctx = cpc
return cpc
}

Expand Down Expand Up @@ -91,11 +89,11 @@ func (e *circuitParserContext) Load(in OperandLabel) *Operand {
return &Operand{OperandLabel: in} // TODO: collect ciphertext dependencies
}

func (e *circuitParserContext) NewOperand(opl OperandLabel) Operand {
func (e *circuitParserContext) NewOperand(opl OperandLabel) *Operand {
e.l.Lock()
defer e.l.Unlock()
e.md.Ops.Add(opl.ForCircuit(e.cd.CircuitID).ForMapping(e.cd.NodeMapping))
return Operand{OperandLabel: opl}
return &Operand{OperandLabel: opl}
}

func (e *circuitParserContext) Set(op Operand) {
Expand Down Expand Up @@ -208,105 +206,113 @@ func (e *circuitParserContext) PCKS(in Operand, rec helium.NodeID, params map[st
return nil
}

func (e *circuitParserContext) Parameters() bgv.Parameters {
func (e *circuitParserContext) Parameters() session.FHEParameters {
e.l.Lock()
defer e.l.Unlock()
return e.params
}

func (e *circuitParserContext) MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
e.l.Lock()
defer e.l.Unlock()
e.md.NeedRlk = true
return nil
}

func (e *circuitParserContext) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
e.l.Lock()
defer e.l.Unlock()
e.md.NeedRlk = true
return nil, nil
}

func (e *circuitParserContext) Relinearize(op0 *rlwe.Ciphertext, op1 *rlwe.Ciphertext) (err error) {
e.l.Lock()
defer e.l.Unlock()
e.md.NeedRlk = true
return nil
}

func (e *circuitParserContext) InnerSum(ctIn *rlwe.Ciphertext, batchSize int, n int, opOut *rlwe.Ciphertext) (err error) {
func (e *circuitParserContext) EvalLocal(needRlk bool, galKeys []uint64, f func(he.Evaluator) error) error {
e.l.Lock()
defer e.l.Unlock()
e.md.GaloisKeys.AddAll(utils.NewSet(e.ctx.params.GaloisElementsForInnerSum(batchSize, n)))
e.md.NeedRlk = needRlk
e.md.GaloisKeys.AddAll(utils.NewSet(galKeys))
return nil
}

func (e *circuitParserContext) AutomorphismHoisted(level int, ctIn *rlwe.Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, opOut *rlwe.Ciphertext) (err error) {
e.l.Lock()
defer e.l.Unlock()
e.md.GaloisKeys.Add(galEl)
return nil
}

type dummyEvaluator struct{ ctx *circuitParserContext }

func (de *dummyEvaluator) Add(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) Sub(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
return nil, nil
}

func (de *dummyEvaluator) MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
return nil, nil
}

func (de *dummyEvaluator) Relinearize(op0 *rlwe.Ciphertext, op1 *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) MulThenAdd(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) Rescale(op0 *rlwe.Ciphertext, op1 *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) InnerSum(ctIn *rlwe.Ciphertext, batchSize int, n int, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) NewEvaluator() Evaluator {
return de
}

func (de *dummyEvaluator) EvalWithKey(_ rlwe.EvaluationKeySet) Evaluator {
return de
}

func (de *dummyEvaluator) NewDecompQPBuffer() []ringqp.Poly {
return nil
}

func (de *dummyEvaluator) AutomorphismHoisted(level int, ctIn *rlwe.Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, opOut *rlwe.Ciphertext) (err error) {
return nil
}

func (de *dummyEvaluator) DecomposeNTT(levelQ, levelP, nbPi int, c2 ring.Poly, c2IsNTT bool, decompQP []ringqp.Poly) {

}
// func (e *circuitParserContext) MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
// e.l.Lock()
// defer e.l.Unlock()
// e.md.NeedRlk = true
// return nil
// }

// func (e *circuitParserContext) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
// e.l.Lock()
// defer e.l.Unlock()
// e.md.NeedRlk = true
// return nil, nil
// }

// func (e *circuitParserContext) Relinearize(op0 *rlwe.Ciphertext, op1 *rlwe.Ciphertext) (err error) {
// e.l.Lock()
// defer e.l.Unlock()
// e.md.NeedRlk = true
// return nil
// }

// func (e *circuitParserContext) InnerSum(ctIn *rlwe.Ciphertext, batchSize int, n int, opOut *rlwe.Ciphertext) (err error) {
// e.l.Lock()
// defer e.l.Unlock()
// e.md.GaloisKeys.AddAll(utils.NewSet(e.ctx.params.GaloisElementsForInnerSum(batchSize, n)))
// return nil
// }

// func (e *circuitParserContext) AutomorphismHoisted(level int, ctIn *rlwe.Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, opOut *rlwe.Ciphertext) (err error) {
// e.l.Lock()
// defer e.l.Unlock()
// e.md.GaloisKeys.Add(galEl)
// return nil
// }

// type dummyEvaluator struct{ ctx *circuitParserContext }

// func (de *dummyEvaluator) Add(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) Sub(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
// return nil, nil
// }

// func (de *dummyEvaluator) MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
// return nil, nil
// }

// func (de *dummyEvaluator) Relinearize(op0 *rlwe.Ciphertext, op1 *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) MulThenAdd(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) Rescale(op0 *rlwe.Ciphertext, op1 *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) InnerSum(ctIn *rlwe.Ciphertext, batchSize int, n int, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) NewEvaluator() Evaluator {
// return de
// }

// func (de *dummyEvaluator) EvalWithKey(_ rlwe.EvaluationKeySet) Evaluator {
// return de
// }

// func (de *dummyEvaluator) NewDecompQPBuffer() []ringqp.Poly {
// return nil
// }

// func (de *dummyEvaluator) AutomorphismHoisted(level int, ctIn *rlwe.Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, opOut *rlwe.Ciphertext) (err error) {
// return nil
// }

// func (de *dummyEvaluator) DecomposeNTT(levelQ, levelP, nbPi int, c2 ring.Poly, c2IsNTT bool, decompQP []ringqp.Poly) {

// }
Loading

0 comments on commit e47c18c

Please sign in to comment.