arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/plonk/gates/base_sum_gate.go
plonk/gates/base_sum_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 baseSumGateRegex = regexp.MustCompile(`BaseSumGate { num_limbs: (?P<numLimbs>[0-9]+) } \+ Base: (?P<base>[0-9]+)`)
13
14func deserializeBaseSumGate(parameters map[string]string) Gate {
15
16	// Has the format "BaseSumGate { num_limbs: 32 } + Base: 2"
17	numLimbs, hasNumLimbs := parameters["numLimbs"]
18	base, hasBase := parameters["base"]
19	if !hasNumLimbs || !hasBase {
20		panic("Missing field num_limbs or base in BaseSumGate")
21	}
22
23	numLimbsInt, err := strconv.Atoi(numLimbs)
24	if err != nil {
25		panic("Invalid num_limbs field in BaseSumGate")
26	}
27
28	baseInt, err := strconv.Atoi(base)
29	if err != nil {
30		panic("Invalid base field in BaseSumGate")
31	}
32
33	return NewBaseSumGate(uint64(numLimbsInt), uint64(baseInt))
34}
35
36const (
37	BASESUM_GATE_WIRE_SUM    = 0
38	BASESUM_GATE_START_LIMBS = 1
39)
40
41type BaseSumGate struct {
42	numLimbs uint64
43	base     uint64
44}
45
46func NewBaseSumGate(numLimbs uint64, base uint64) *BaseSumGate {
47	return &BaseSumGate{
48		numLimbs: numLimbs,
49		base:     base,
50	}
51}
52
53func (g *BaseSumGate) Id() string {
54	return fmt.Sprintf("BaseSumGate { num_limbs: %d } + Base: %d", g.numLimbs, g.base)
55}
56
57func (g *BaseSumGate) limbs() []uint64 {
58	limbIndices := make([]uint64, g.numLimbs)
59	for i := uint64(0); i < g.numLimbs; i++ {
60		limbIndices[i] = uint64(BASESUM_GATE_START_LIMBS + i)
61	}
62
63	return limbIndices
64}
65
66func (g *BaseSumGate) EvalUnfiltered(
67	api frontend.API,
68	glApi *gl.Chip,
69	vars EvaluationVars,
70) []gl.QuadraticExtensionVariable {
71	sum := vars.localWires[BASESUM_GATE_WIRE_SUM]
72	limbs := make([]gl.QuadraticExtensionVariable, g.numLimbs)
73	limbIndices := g.limbs()
74	for i, limbIdx := range limbIndices {
75		limbs[i] = vars.localWires[limbIdx]
76	}
77
78	baseQe := gl.NewQuadraticExtensionVariable(gl.NewVariable(g.base), gl.Zero())
79	computedSum := glApi.ReduceWithPowers(
80		limbs,
81		baseQe,
82	)
83
84	var constraints []gl.QuadraticExtensionVariable
85	constraints = append(constraints, glApi.SubExtension(computedSum, sum))
86	for _, limb := range limbs {
87		acc := gl.OneExtension()
88		for i := uint64(0); i < g.base; i++ {
89			difference := glApi.SubExtension(limb, gl.NewQuadraticExtensionVariable(gl.NewVariable(i), gl.Zero()))
90			acc = glApi.MulExtension(acc, difference)
91		}
92		constraints = append(constraints, acc)
93	}
94
95	return constraints
96}