diff --git a/constraint/bls12-377/gkr.go b/constraint/bls12-377/gkr.go index 31dc279700..0a5bcdebef 100644 --- a/constraint/bls12-377/gkr.go +++ b/constraint/bls12-377/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/constraint/bls12-381/gkr.go b/constraint/bls12-381/gkr.go index 5adfe3ec50..bd55673cd1 100644 --- a/constraint/bls12-381/gkr.go +++ b/constraint/bls12-381/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/constraint/bls24-315/gkr.go b/constraint/bls24-315/gkr.go index 048f8fa911..61925e2be8 100644 --- a/constraint/bls24-315/gkr.go +++ b/constraint/bls24-315/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" "github.com/consensys/gnark-crypto/ecc/bls24-315/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bls24-315/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/constraint/bls24-317/gkr.go b/constraint/bls24-317/gkr.go index f81157a0cf..4b18be9567 100644 --- a/constraint/bls24-317/gkr.go +++ b/constraint/bls24-317/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" "github.com/consensys/gnark-crypto/ecc/bls24-317/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bls24-317/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/constraint/bn254/gkr.go b/constraint/bn254/gkr.go index d834f7caca..a3730d97d3 100644 --- a/constraint/bn254/gkr.go +++ b/constraint/bn254/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark-crypto/ecc/bn254/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bn254/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/constraint/bw6-633/gkr.go b/constraint/bw6-633/gkr.go index fd3feedb08..db66fd871d 100644 --- a/constraint/bw6-633/gkr.go +++ b/constraint/bw6-633/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" "github.com/consensys/gnark-crypto/ecc/bw6-633/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bw6-633/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/constraint/bw6-761/gkr.go b/constraint/bw6-761/gkr.go index 5d3edc00cf..2c3ddabbc0 100644 --- a/constraint/bw6-761/gkr.go +++ b/constraint/bw6-761/gkr.go @@ -17,6 +17,7 @@ package cs import ( + "fmt" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/gkr" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/polynomial" @@ -36,28 +37,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -89,7 +94,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -183,82 +191,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} diff --git a/go.mod b/go.mod index afac14d9ee..6d5c31a169 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/bits-and-blooms/bitset v1.7.0 github.com/blang/semver/v4 v4.0.0 github.com/consensys/bavard v0.1.13 - github.com/consensys/gnark-crypto v0.11.1-0.20230609175512-0ee617fa6d43 + github.com/consensys/gnark-crypto v0.11.1-0.20230629152742-006af12e9de7 github.com/fxamacker/cbor/v2 v2.4.0 github.com/google/go-cmp v0.5.9 github.com/google/pprof v0.0.0-20230309165930-d61513b1440d diff --git a/go.sum b/go.sum index cfb27fb3eb..40c0e57497 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,10 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.11.1-0.20230609175512-0ee617fa6d43 h1:6VCNdjn2RmxgG2ZklMmSGov9BtCNfVF4VjqAngysiPU= github.com/consensys/gnark-crypto v0.11.1-0.20230609175512-0ee617fa6d43/go.mod h1:6C2ytC8zmP8uH2GKVfPOjf0Vw3KwMAaUxlCPK5WQqmw= +github.com/consensys/gnark-crypto v0.11.1-0.20230629143946-34cd64d142f4 h1:uCq6iyRURo+QHvPhwyF+0YcB1Pz5XoYxQSidnOEoORY= +github.com/consensys/gnark-crypto v0.11.1-0.20230629143946-34cd64d142f4/go.mod h1:6C2ytC8zmP8uH2GKVfPOjf0Vw3KwMAaUxlCPK5WQqmw= +github.com/consensys/gnark-crypto v0.11.1-0.20230629152742-006af12e9de7 h1:h/yBT40UqdgzNdvpufozZO8lMbPMTbrAJJQ5kSC6T/o= +github.com/consensys/gnark-crypto v0.11.1-0.20230629152742-006af12e9de7/go.mod h1:6C2ytC8zmP8uH2GKVfPOjf0Vw3KwMAaUxlCPK5WQqmw= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/generator/backend/template/representations/gkr.go.tmpl b/internal/generator/backend/template/representations/gkr.go.tmpl index 9c66dd8cf0..9f6735ab4c 100644 --- a/internal/generator/backend/template/representations/gkr.go.tmpl +++ b/internal/generator/backend/template/representations/gkr.go.tmpl @@ -1,4 +1,5 @@ import ( + "fmt" {{- template "import_fr" .}} {{- template "import_gkr" .}} {{- template "import_polynomial" .}} @@ -18,28 +19,32 @@ type GkrSolvingData struct { workers *utils.WorkerPool } -func convertCircuit(noPtr constraint.GkrCircuit) gkr.Circuit { +func convertCircuit(noPtr constraint.GkrCircuit) (gkr.Circuit, error) { resCircuit := make(gkr.Circuit, len(noPtr)) + var found bool for i := range noPtr { - resCircuit[i].Gate = GkrGateRegistry[noPtr[i].Gate] + if resCircuit[i].Gate, found = gkr.Gates[noPtr[i].Gate]; !found && noPtr[i].Gate != "" { + return nil, fmt.Errorf("gate \"%s\" not found", noPtr[i].Gate) + } resCircuit[i].Inputs = algo_utils.Map(noPtr[i].Inputs, algo_utils.SlicePtrAt(resCircuit)) } - return resCircuit + return resCircuit, nil } -func (d *GkrSolvingData) init(info constraint.GkrInfo) gkrAssignment { - d.circuit = convertCircuit(info.Circuit) +func (d *GkrSolvingData) init(info constraint.GkrInfo) (assignment gkrAssignment, err error) { + if d.circuit, err = convertCircuit(info.Circuit); err != nil { + return + } d.memoryPool = polynomial.NewPool(d.circuit.MemoryRequirements(info.NbInstances)...) d.workers = utils.NewWorkerPool() - assignmentsSequential := make(gkrAssignment, len(d.circuit)) + assignment = make(gkrAssignment, len(d.circuit)) d.assignments = make(gkr.WireAssignment, len(d.circuit)) - for i := range assignmentsSequential { - assignmentsSequential[i] = d.memoryPool.Make(info.NbInstances) - d.assignments[&d.circuit[i]] = assignmentsSequential[i] + for i := range assignment { + assignment[i] = d.memoryPool.Make(info.NbInstances) + d.assignments[&d.circuit[i]] = assignment[i] } - - return assignmentsSequential + return } func (d *GkrSolvingData) dumpAssignments() { @@ -71,7 +76,10 @@ func GkrSolveHint(info constraint.GkrInfo, solvingData *GkrSolvingData) hint.Hin circuit := info.Circuit nbInstances := info.NbInstances offsets := info.AssignmentOffsets() - assignment := solvingData.init(info) + assignment, err := solvingData.init(info) + if err != nil { + return err + } chunks := circuit.Chunks(nbInstances) solveTask := func(chunkOffset int) utils.Task { @@ -165,82 +173,5 @@ func GkrProveHint(hashName string, data *GkrSolvingData) hint.Hint { } } -var GkrGateRegistry = map[string]gkr.Gate{ // TODO: Migrate to gnark-crypto - "mul": mulGate(2), - "add": addGate{}, - "sub": subGate{}, - "neg": negGate{}, -} - // TODO: Move to gnark-crypto -var HashBuilderRegistry = make(map[string]func() hash.Hash) - -type mulGate int -type addGate struct{} -type subGate struct{} -type negGate struct{} - -func (g mulGate) Evaluate(x ...fr.Element) (res fr.Element) { - if len(x) != int(g) { - panic("wrong input count") - } - switch len(x) { - case 0: - res.SetOne() - case 1: - res.Set(&x[0]) - default: - res.Mul(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Mul(&res, &x[2]) - } - } - return -} - -func (g mulGate) Degree() int { - return int(g) -} - -func (g addGate) Evaluate(x ...fr.Element) (res fr.Element) { - switch len(x) { - case 0: - // set zero - case 1: - res.Set(&x[0]) - case 2: - res.Add(&x[0], &x[1]) - for i := 2; i < len(x); i++ { - res.Add(&res, &x[2]) - } - } - return -} - -func (g addGate) Degree() int { - return 1 -} - -func (g subGate) Evaluate(element ...fr.Element) (diff fr.Element) { - if len(element) > 2 { - panic("not implemented") //TODO - } - diff.Sub(&element[0], &element[1]) - return -} - -func (g subGate) Degree() int { - return 1 -} - -func (g negGate) Evaluate(element ...fr.Element) (neg fr.Element) { - if len(element) != 1 { - panic("univariate gate") - } - neg.Neg(&element[0]) - return -} - -func (g negGate) Degree() int { - return 1 -} \ No newline at end of file +var HashBuilderRegistry = make(map[string]func() hash.Hash) \ No newline at end of file diff --git a/internal/tinyfield/element.go b/internal/tinyfield/element.go index f987f62b2d..85d289e751 100644 --- a/internal/tinyfield/element.go +++ b/internal/tinyfield/element.go @@ -677,6 +677,11 @@ func (z *Element) Marshal() []byte { return b[:] } +// Unmarshal is an alias for SetBytes, it sets z to the value of e. +func (z *Element) Unmarshal(e []byte) { + z.SetBytes(e) +} + // SetBytes interprets e as the bytes of a big-endian unsigned integer, // sets z to that value, and returns z. func (z *Element) SetBytes(e []byte) *Element { diff --git a/std/gkr/api.go b/std/gkr/api.go index ad67fb6fcb..d13c65e2d0 100644 --- a/std/gkr/api.go +++ b/std/gkr/api.go @@ -9,7 +9,7 @@ func frontendVarToInt(a constraint.GkrVariable) int { return int(a) } -func (api *API) newNonInputVariable(gate string, in []constraint.GkrVariable) constraint.GkrVariable { +func (api *API) NamedGate(gate string, in ...constraint.GkrVariable) constraint.GkrVariable { api.toStore.Circuit = append(api.toStore.Circuit, constraint.GkrWire{ Gate: gate, Inputs: algo_utils.Map(in, frontendVarToInt), @@ -18,30 +18,30 @@ func (api *API) newNonInputVariable(gate string, in []constraint.GkrVariable) co return constraint.GkrVariable(len(api.toStore.Circuit) - 1) } -func (api *API) newVar2PlusIn(gate string, in1, in2 constraint.GkrVariable, in ...constraint.GkrVariable) constraint.GkrVariable { +func (api *API) namedGate2PlusIn(gate string, in1, in2 constraint.GkrVariable, in ...constraint.GkrVariable) constraint.GkrVariable { inCombined := make([]constraint.GkrVariable, 2+len(in)) inCombined[0] = in1 inCombined[1] = in2 for i := range in { inCombined[i+2] = in[i] } - return api.newNonInputVariable(gate, inCombined) + return api.NamedGate(gate, inCombined...) } func (api *API) Add(i1, i2 constraint.GkrVariable, in ...constraint.GkrVariable) constraint.GkrVariable { - return api.newVar2PlusIn("add", i1, i2, in...) + return api.namedGate2PlusIn("add", i1, i2, in...) } func (api *API) Neg(i1 constraint.GkrVariable) constraint.GkrVariable { - return api.newNonInputVariable("neg", []constraint.GkrVariable{i1}) + return api.NamedGate("neg", i1) } func (api *API) Sub(i1, i2 constraint.GkrVariable, in ...constraint.GkrVariable) constraint.GkrVariable { - return api.newVar2PlusIn("sub", i1, i2, in...) + return api.namedGate2PlusIn("sub", i1, i2, in...) } func (api *API) Mul(i1, i2 constraint.GkrVariable, in ...constraint.GkrVariable) constraint.GkrVariable { - return api.newVar2PlusIn("mul", i1, i2, in...) + return api.namedGate2PlusIn("mul", i1, i2, in...) } // TODO @Tabaie This can be useful diff --git a/std/gkr/api_test.go b/std/gkr/api_test.go index a41670be0e..d39b103962 100644 --- a/std/gkr/api_test.go +++ b/std/gkr/api_test.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/consensys/gnark-crypto/kzg" "github.com/consensys/gnark/backend/plonk" + bn254r1cs "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/test" "github.com/stretchr/testify/require" "hash" @@ -14,11 +15,11 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/gkr" bn254MiMC "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark/constraint" - bn254r1cs "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/frontend/cs/scs" @@ -450,8 +451,8 @@ func init() { } func registerMiMCGate() { - RegisteredGates["mimc"] = MiMCCipherGate{Ark: 0} - bn254r1cs.GkrGateRegistry["mimc"] = mimcCipherGate{} + Gates["mimc"] = MiMCCipherGate{Ark: 0} + gkr.Gates["mimc"] = mimcCipherGate{} } type constHashBn254 int // TODO @Tabaie move to gnark-crypto @@ -634,6 +635,7 @@ func BenchmarkMiMCNoGkrFullDepthSolve(b *testing.B) { } func TestMiMCFullDepthNoDepSolve(t *testing.T) { + registerMiMC() for i := 0; i < 100; i++ { circuit, assignment := mimcNoDepCircuits(5, 1<<2) testGroth16(t, circuit, assignment) diff --git a/std/gkr/compile.go b/std/gkr/compile.go index 0b1199787c..7f8dc97925 100644 --- a/std/gkr/compile.go +++ b/std/gkr/compile.go @@ -229,7 +229,7 @@ func newCircuitDataForSnark(info constraint.GkrInfo, assignment assignment) circ for i := range circuit { w := info.Circuit[i] circuit[i] = Wire{ - Gate: ite(w.IsInput(), RegisteredGates[w.Gate], Gate(IdentityGate{})), + Gate: ite(w.IsInput(), Gates[w.Gate], Gate(IdentityGate{})), Inputs: algo_utils.Map(w.Inputs, circuitAt), nbUniqueOutputs: w.NbUniqueOutputs, } diff --git a/std/gkr/gkr.go b/std/gkr/gkr.go index e10e0c98b5..646ca45553 100644 --- a/std/gkr/gkr.go +++ b/std/gkr/gkr.go @@ -549,13 +549,22 @@ func (g MulGate) Degree() int { type AddGate struct{} func (a AddGate) Evaluate(api frontend.API, v ...frontend.Variable) frontend.Variable { - var rest []frontend.Variable - if len(v) >= 2 { - rest = v[2:] + switch len(v) { + case 0: + return 0 + case 1: + return v[0] } + rest := v[2:] return api.Add(v[0], v[1], rest...) } func (a AddGate) Degree() int { return 1 } + +var Gates = map[string]Gate{ + "identity": IdentityGate{}, + "add": AddGate{}, + "mul": MulGate{}, +} diff --git a/std/gkr/gkr_test.go b/std/gkr/gkr_test.go index 4149ea8022..a16165a40d 100644 --- a/std/gkr/gkr_test.go +++ b/std/gkr/gkr_test.go @@ -241,7 +241,7 @@ func (c CircuitInfo) toCircuit() (circuit Circuit, err error) { } var found bool - if circuit[i].Gate, found = RegisteredGates[wireInfo.Gate]; !found && wireInfo.Gate != "" { + if circuit[i].Gate, found = Gates[wireInfo.Gate]; !found && wireInfo.Gate != "" { err = fmt.Errorf("undefined gate \"%s\"", wireInfo.Gate) } } @@ -252,7 +252,7 @@ func (c CircuitInfo) toCircuit() (circuit Circuit, err error) { type _select int func init() { - RegisteredGates["select-input-3"] = _select(2) + Gates["select-input-3"] = _select(2) } func (g _select) Evaluate(_ frontend.API, in ...frontend.Variable) frontend.Variable { @@ -483,3 +483,25 @@ func (c *constHashCircuit) Define(api frontend.API) error { func TestConstHash(t *testing.T) { test.NewAssert(t).SolvingSucceeded(&constHashCircuit{}, &constHashCircuit{X: 1}) } + +var mimcSnarkTotalCalls = 0 + +type MiMCCipherGate struct { + Ark frontend.Variable +} + +func (m MiMCCipherGate) Evaluate(api frontend.API, input ...frontend.Variable) frontend.Variable { + mimcSnarkTotalCalls++ + + if len(input) != 2 { + panic("mimc has fan-in 2") + } + sum := api.Add(input[0], input[1], m.Ark) + + sumCubed := api.Mul(sum, sum, sum) // sum^3 + return api.Mul(sumCubed, sumCubed, sum) +} + +func (m MiMCCipherGate) Degree() int { + return 7 +} diff --git a/std/gkr/registry.go b/std/gkr/registry.go deleted file mode 100644 index 03f5035964..0000000000 --- a/std/gkr/registry.go +++ /dev/null @@ -1,32 +0,0 @@ -package gkr - -import "github.com/consensys/gnark/frontend" - -var RegisteredGates = map[string]Gate{ - "identity": IdentityGate{}, - "add": AddGate{}, - "mul": MulGate{}, - "mimc": MiMCCipherGate{Ark: 0}, //TODO: Add ark -} - -var mimcSnarkTotalCalls = 0 - -type MiMCCipherGate struct { - Ark frontend.Variable -} - -func (m MiMCCipherGate) Evaluate(api frontend.API, input ...frontend.Variable) frontend.Variable { - mimcSnarkTotalCalls++ - - if len(input) != 2 { - panic("mimc has fan-in 2") - } - sum := api.Add(input[0], input[1], m.Ark) - - sumCubed := api.Mul(sum, sum, sum) // sum^3 - return api.Mul(sumCubed, sumCubed, sum) -} - -func (m MiMCCipherGate) Degree() int { - return 7 -}