arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
reducing extension gate (#12)

Kevin Jue kjue235@gmail.com
Wed, 17 May 2023 17:40:43 -0700
commit

2823cfbbcba050a440278f03447ad95060673c1c

parent

c98d65b48a714f86e23aa32fe955d07780f601ef

M field/field.go → field/field.go

@@ -7,13 +7,13 @@ "github.com/consensys/gnark/frontend"

"github.com/consensys/gnark/std/math/emulated" ) +const D = 2 + type EmulatedField = emulated.Goldilocks type F = emulated.Element[EmulatedField] type QuadraticExtension = [2]F -type QEAlgebra = [2]QuadraticExtension +type QEAlgebra = [D]QuadraticExtension type Hash = [4]F - -const D = 2 var TEST_CURVE = ecc.BN254
M plonky2_verifier/arithmetic_extension_gate.go → plonky2_verifier/arithmetic_extension_gate.go

@@ -52,7 +52,9 @@ computed_output := p.qeAPI.ScalarMulExtensionAlgebra(const1, addend)

computed_output = p.qeAPI.AddExtensionAlgebra(computed_output, scaled_mul) diff := p.qeAPI.SubExtensionAlgebra(output, computed_output) - constraints = append(constraints, diff[0], diff[1]) + for j := 0; j < D; j++ { + constraints = append(constraints, diff[j]) + } } return constraints
M plonky2_verifier/gate.go → plonky2_verifier/gate.go

@@ -122,6 +122,24 @@

return NewMultiplicationExtensionGate(uint64(numOps)) } + if strings.HasPrefix(gateId, "ReducingExtensionGate") { + // Has the format "ReducingExtensionGate { num_coeffs: 33 }" + + regEx := "ReducingExtensionGate { num_coeffs: (?P<numCoeffs>[0-9]+) }" + r, err := regexp.Compile(regEx) + if err != nil { + panic("Invalid ReducingExtensionGate regular expression") + } + + matches := getRegExMatches(r, gateId) + numCoeffs, hasNumCoeffs := matches["numCoeffs"] + if !hasNumCoeffs { + panic("Invalid ReducingExtensionGate ID") + } + + return NewReducingExtensionGate(uint64(numCoeffs)) + } + return nil //panic(fmt.Sprintf("Unknown gate ID %s", gateId)) }
M plonky2_verifier/gate_test.go → plonky2_verifier/gate_test.go

@@ -769,6 +769,7 @@ {&RandomAccessGate{bits: 4, numCopies: 4, numExtraConstants: 2}, randomAccessGateExpectedConstraints},

{&PoseidonGate{}, poseidonGateExpectedConstraints}, {&ArithmeticExtensionGate{numOps: 10}, arithmeticExtensionGateExpectedConstraints}, {&MultiplicationExtensionGate{numOps: 13}, mulExtensionGateExpectedConstraints}, + {&ReducingExtensionGate{numCoeffs: 33}, reducingExtensionGateExpectedConstraints}, } for _, test := range gateTests {
M plonky2_verifier/multiplication_extension_gate.go → plonky2_verifier/multiplication_extension_gate.go

@@ -44,7 +44,9 @@ mul := p.qeAPI.MulExtensionAlgebra(multiplicand0, multiplicand1)

computed_output := p.qeAPI.ScalarMulExtensionAlgebra(const0, mul) diff := p.qeAPI.SubExtensionAlgebra(output, computed_output) - constraints = append(constraints, diff[0], diff[1]) + for j := 0; j < D; j++ { + constraints = append(constraints, diff[j]) + } } return constraints
A plonky2_verifier/reducing_extension_gate.go

@@ -0,0 +1,84 @@

+package plonky2_verifier + +import ( + "fmt" + . "gnark-plonky2-verifier/field" +) + +type ReducingExtensionGate struct { + numCoeffs uint64 +} + +const START_COEFFS = 3 * D + +func NewReducingExtensionGate(numCoeffs uint64) *ReducingExtensionGate { + return &ReducingExtensionGate{ + numCoeffs: numCoeffs, + } +} + +func (g *ReducingExtensionGate) Id() string { + return fmt.Sprintf("ReducingExtensionGate { num_ops: %d }", g.numCoeffs) +} + +func (g *ReducingExtensionGate) wiresOutput() Range { + return Range{0, D} +} + +func (g *ReducingExtensionGate) wiresAlpha() Range { + return Range{D, 2 * D} +} + +func (g *ReducingExtensionGate) wiresOldAcc() Range { + return Range{2 * D, 3 * D} +} + +func (g *ReducingExtensionGate) wiresCoeff(i uint64) Range { + return Range{START_COEFFS + D*i, START_COEFFS + D*(i+1)} +} + +func (g *ReducingExtensionGate) startAccs() uint64 { + return START_COEFFS + g.numCoeffs*D +} + +func (g *ReducingExtensionGate) wiresAccs(i uint64) Range { + if i >= g.numCoeffs { + panic("Accumulator index out of bounds") + } + + if i == g.numCoeffs-1 { + return g.wiresOutput() + } + + return Range{g.startAccs() + D*i, g.startAccs() + D*(i+1)} +} + +func (g *ReducingExtensionGate) EvalUnfiltered(p *PlonkChip, vars EvaluationVars) []QuadraticExtension { + alpha := vars.GetLocalExtAlgebra(g.wiresAlpha()) + oldAcc := vars.GetLocalExtAlgebra(g.wiresOldAcc()) + + coeffs := []QEAlgebra{} + for i := uint64(0); i < g.numCoeffs; i++ { + coeffs = append(coeffs, vars.GetLocalExtAlgebra(g.wiresCoeff(i))) + } + + accs := []QEAlgebra{} + for i := uint64(0); i < g.numCoeffs; i++ { + accs = append(accs, vars.GetLocalExtAlgebra(g.wiresAccs(i))) + } + + constraints := []QuadraticExtension{} + acc := oldAcc + for i := uint64(0); i < g.numCoeffs; i++ { + coeff := coeffs[i] + tmp := p.qeAPI.MulExtensionAlgebra(acc, alpha) + tmp = p.qeAPI.AddExtensionAlgebra(tmp, coeff) + tmp = p.qeAPI.SubExtensionAlgebra(tmp, accs[i]) + for j := uint64(0); j < D; j++ { + constraints = append(constraints, tmp[j]) + } + acc = accs[i] + } + + return constraints +}
M plonky2_verifier/vars.go → plonky2_verifier/vars.go

@@ -16,9 +16,14 @@ }

func (e *EvaluationVars) GetLocalExtAlgebra(wireRange Range) QEAlgebra { // For now, only support degree 2 - if wireRange.end-wireRange.start != 2 { - panic("Only degree 2 supported") + if wireRange.end-wireRange.start != D { + panic("Range must be of size D") + } + + var ret QEAlgebra + for i := wireRange.start; i < wireRange.end; i++ { + ret[i-wireRange.start] = e.localWires[i] } - return QEAlgebra{e.localWires[wireRange.start], e.localWires[wireRange.end-1]} + return ret }