gnark-plonky2-verifier/plonk/gates/reducing_gate.go
plonk/gates/reducing_gate.goRaw
1package gates
2
3import (
4 "fmt"
5 "regexp"
6 "strconv"
7
8 "github.com/consensys/gnark/frontend"
9 gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
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 * gl.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, gl.D}
47}
48
49func (g *ReducingGate) wiresAlpha() Range {
50 return Range{gl.D, 2 * gl.D}
51}
52
53func (g *ReducingGate) wiresOldAcc() Range {
54 return Range{2 * gl.D, 3 * gl.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() + gl.D*i, g.startAccs() + gl.D*(i+1)}
75}
76
77func (g *ReducingGate) EvalUnfiltered(
78 api frontend.API,
79 glApi gl.Chip,
80 vars EvaluationVars,
81) []gl.QuadraticExtensionVariable {
82 alpha := vars.GetLocalExtAlgebra(g.wiresAlpha())
83 oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc())
84
85 coeffs := []gl.QuadraticExtensionVariable{}
86 coeffsRange := g.wiresCoeff()
87 for i := coeffsRange.start; i < coeffsRange.end; i++ {
88 coeffs = append(coeffs, vars.localWires[i])
89 }
90
91 accs := []gl.QuadraticExtensionAlgebraVariable{}
92 for i := uint64(0); i < g.numCoeffs; i++ {
93 accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
94 }
95
96 constraints := []gl.QuadraticExtensionVariable{}
97 acc := oldAcc
98 for i := uint64(0); i < g.numCoeffs; i++ {
99 coeff := coeffs[i].ToQuadraticExtensionAlgebra()
100 tmp := glApi.MulExtensionAlgebra(acc, alpha)
101 tmp = glApi.AddExtensionAlgebra(tmp, coeff)
102 tmp = glApi.SubExtensionAlgebra(tmp, accs[i])
103 for j := 0; j < gl.D; j++ {
104 constraints = append(constraints, tmp[j])
105 }
106 acc = accs[i]
107 }
108
109 return constraints
110}