gnark-plonky2-verifier/verifier/internal/gates/reducing_extension_gate.go
verifier/internal/gates/reducing_extension_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 reducingExtensionGateRegex = regexp.MustCompile("ReducingExtensionGate { num_coeffs: (?P<numCoeffs>[0-9]+) }")
13
14func deserializeReducingExtensionGate(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 ReducingExtensionGate")
19 }
20
21 numCoeffsInt, err := strconv.Atoi(numCoeffs)
22 if err != nil {
23 panic("Invalid num_coeffs field in ReducingExtensionGate")
24 }
25
26 return NewReducingExtensionGate(uint64(numCoeffsInt))
27}
28
29type ReducingExtensionGate struct {
30 numCoeffs uint64
31}
32
33const START_COEFFS_REDUCING_EXTENSION_GATE = 3 * field.D
34
35func NewReducingExtensionGate(numCoeffs uint64) *ReducingExtensionGate {
36 return &ReducingExtensionGate{
37 numCoeffs: numCoeffs,
38 }
39}
40
41func (g *ReducingExtensionGate) Id() string {
42 return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs)
43}
44
45func (g *ReducingExtensionGate) wiresOutput() Range {
46 return Range{0, field.D}
47}
48
49func (g *ReducingExtensionGate) wiresAlpha() Range {
50 return Range{field.D, 2 * field.D}
51}
52
53func (g *ReducingExtensionGate) wiresOldAcc() Range {
54 return Range{2 * field.D, 3 * field.D}
55}
56
57func (g *ReducingExtensionGate) wiresCoeff(i uint64) Range {
58 return Range{START_COEFFS_REDUCING_EXTENSION_GATE + field.D*i, START_COEFFS_REDUCING_EXTENSION_GATE + field.D*(i+1)}
59}
60
61func (g *ReducingExtensionGate) startAccs() uint64 {
62 return START_COEFFS_REDUCING_EXTENSION_GATE + g.numCoeffs*field.D
63}
64
65func (g *ReducingExtensionGate) 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 *ReducingExtensionGate) 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.QEAlgebra{}
82 for i := uint64(0); i < g.numCoeffs; i++ {
83 coeffs = append(coeffs, vars.GetLocalExtAlgebra(g.wiresCoeff(i)))
84 }
85
86 accs := []field.QEAlgebra{}
87 for i := uint64(0); i < g.numCoeffs; i++ {
88 accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i)))
89 }
90
91 constraints := []field.QuadraticExtension{}
92 acc := oldAcc
93 for i := uint64(0); i < g.numCoeffs; i++ {
94 coeff := coeffs[i]
95 tmp := qeAPI.MulExtensionAlgebra(acc, alpha)
96 tmp = qeAPI.AddExtensionAlgebra(tmp, coeff)
97 tmp = qeAPI.SubExtensionAlgebra(tmp, accs[i])
98 for j := uint64(0); j < field.D; j++ {
99 constraints = append(constraints, tmp[j])
100 }
101 acc = accs[i]
102 }
103
104 return constraints
105}