gnark-plonky2-verifier/verifier/internal/gates/reducing_gate.go
verifier/internal/gates/reducing_gate.goRaw
1package gates
2
3import (
4 "fmt"
5 "regexp"
6 "strconv"
7
8 "github.com/consensys/gnark/frontend"
9 "github.com/succinctlabs/gnark-plonky2-verifier/field"
10)
11
12var reducingGateRegex = regexp.MustCompile("ReducingGate { num_coeffs: (?P<numCoeffs>[0-9]+) }")
13
14func deserializeReducingGate(parameters map[string]string) Gate {
15 // Has the format "ReducingGate { num_coeffs: 33 }"
16 numCoeffs, hasNumCoeffs := parameters["numCoeffs"]
17 if !hasNumCoeffs {
18 panic("Missing field num_coeffs in ReducingGate")
19 }
20
21 numCoeffsInt, err := strconv.Atoi(numCoeffs)
22 if err != nil {
23 panic("Invalid num_coeffs field in ReducingGate")
24 }
25
26 return NewReducingGate(uint64(numCoeffsInt))
27}
28
29type ReducingGate struct {
30 numCoeffs uint64
31}
32
33const START_COEFFS_REDUCING_GATE = 3 * field.D
34
35func NewReducingGate(numCoeffs uint64) *ReducingGate {
36 return &ReducingGate{
37 numCoeffs: numCoeffs,
38 }
39}
40
41func (g *ReducingGate) Id() string {
42 return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs)
43}
44
45func (g *ReducingGate) wiresOutput() Range {
46 return Range{0, field.D}
47}
48
49func (g *ReducingGate) wiresAlpha() Range {
50 return Range{field.D, 2 * field.D}
51}
52
53func (g *ReducingGate) wiresOldAcc() Range {
54 return Range{2 * field.D, 3 * field.D}
55}
56
57func (g *ReducingGate) wiresCoeff() Range {
58 return Range{START_COEFFS_REDUCING_GATE, START_COEFFS_REDUCING_GATE + g.numCoeffs}
59}
60
61func (g *ReducingGate) startAccs() uint64 {
62 return START_COEFFS_REDUCING_GATE + g.numCoeffs
63}
64
65func (g *ReducingGate) wiresAccs(i uint64) Range {
66 if i >= g.numCoeffs {
67 panic("Accumulator index out of bounds")
68 }
69
70 if i == g.numCoeffs-1 {
71 return g.wiresOutput()
72 }
73
74 return Range{g.startAccs() + field.D*i, g.startAccs() + field.D*(i+1)}
75}
76
77func (g *ReducingGate) EvalUnfiltered(api frontend.API, qeAPI *field.QuadraticExtensionAPI, vars EvaluationVars) []field.QuadraticExtension {
78 alpha := vars.GetLocalExtAlgebra(g.wiresAlpha())
79 oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc())
80
81 coeffs := []field.QuadraticExtension{}
82 coeffsRange := g.wiresCoeff()
83 for i := coeffsRange.start; i < coeffsRange.end; i++ {
84 coeffs = append(coeffs, vars.localWires[i])
85 }
86
87 accs := []field.QEAlgebra{}
88 for i := uint64(0); i < g.numCoeffs; i++ {
89 accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
90 }
91
92 constraints := []field.QuadraticExtension{}
93 acc := oldAcc
94 for i := uint64(0); i < g.numCoeffs; i++ {
95 var coeff field.QEAlgebra
96 for j := 0; j < field.D; j++ {
97 coeff[j] = qeAPI.ZERO_QE
98 }
99 coeff[0] = coeffs[i]
100 tmp := qeAPI.MulExtensionAlgebra(acc, alpha)
101 tmp = qeAPI.AddExtensionAlgebra(tmp, coeff)
102 tmp = qeAPI.SubExtensionAlgebra(tmp, accs[i])
103 for j := 0; j < field.D; j++ {
104 constraints = append(constraints, tmp[j])
105 }
106 acc = accs[i]
107 }
108
109 return constraints
110}