From 2823cfbbcba050a440278f03447ad95060673c1c Mon Sep 17 00:00:00 2001 From: Kevin Jue Date: Wed, 17 May 2023 17:40:43 -0700 Subject: [PATCH] reducing extension gate (#12) --- field/field.go | 6 +- plonky2_verifier/arithmetic_extension_gate.go | 4 +- plonky2_verifier/gate.go | 18 ++++ plonky2_verifier/gate_test.go | 1 + .../multiplication_extension_gate.go | 4 +- plonky2_verifier/reducing_extension_gate.go | 84 +++++++++++++++++++ plonky2_verifier/vars.go | 11 ++- 7 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 plonky2_verifier/reducing_extension_gate.go diff --git a/field/field.go b/field/field.go index 4bd7ffe..16e4e1f 100644 --- a/field/field.go +++ b/field/field.go @@ -7,14 +7,14 @@ import ( "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 func NewFieldElement(x uint64) F { diff --git a/plonky2_verifier/arithmetic_extension_gate.go b/plonky2_verifier/arithmetic_extension_gate.go index 25f47d4..727f53a 100644 --- a/plonky2_verifier/arithmetic_extension_gate.go +++ b/plonky2_verifier/arithmetic_extension_gate.go @@ -52,7 +52,9 @@ func (g *ArithmeticExtensionGate) EvalUnfiltered(p *PlonkChip, vars EvaluationVa 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 diff --git a/plonky2_verifier/gate.go b/plonky2_verifier/gate.go index 7a92d79..b0321d4 100644 --- a/plonky2_verifier/gate.go +++ b/plonky2_verifier/gate.go @@ -122,6 +122,24 @@ func GateInstanceFromId(gateId string) gate { return NewMultiplicationExtensionGate(uint64(numOps)) } + if strings.HasPrefix(gateId, "ReducingExtensionGate") { + // Has the format "ReducingExtensionGate { num_coeffs: 33 }" + + regEx := "ReducingExtensionGate { num_coeffs: (?P[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)) } diff --git a/plonky2_verifier/gate_test.go b/plonky2_verifier/gate_test.go index 8efd21c..ac40641 100644 --- a/plonky2_verifier/gate_test.go +++ b/plonky2_verifier/gate_test.go @@ -769,6 +769,7 @@ func TestGates(t *testing.T) { {&PoseidonGate{}, poseidonGateExpectedConstraints}, {&ArithmeticExtensionGate{numOps: 10}, arithmeticExtensionGateExpectedConstraints}, {&MultiplicationExtensionGate{numOps: 13}, mulExtensionGateExpectedConstraints}, + {&ReducingExtensionGate{numCoeffs: 33}, reducingExtensionGateExpectedConstraints}, } for _, test := range gateTests { diff --git a/plonky2_verifier/multiplication_extension_gate.go b/plonky2_verifier/multiplication_extension_gate.go index 2ac82da..d33914d 100644 --- a/plonky2_verifier/multiplication_extension_gate.go +++ b/plonky2_verifier/multiplication_extension_gate.go @@ -44,7 +44,9 @@ func (g *MultiplicationExtensionGate) EvalUnfiltered(p *PlonkChip, vars Evaluati 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 diff --git a/plonky2_verifier/reducing_extension_gate.go b/plonky2_verifier/reducing_extension_gate.go new file mode 100644 index 0000000..fd504ed --- /dev/null +++ b/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 +} diff --git a/plonky2_verifier/vars.go b/plonky2_verifier/vars.go index d2e6aa7..9ca9efc 100644 --- a/plonky2_verifier/vars.go +++ b/plonky2_verifier/vars.go @@ -16,9 +16,14 @@ func (e *EvaluationVars) RemovePrefix(numSelectors uint64) { 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") } - return QEAlgebra{e.localWires[wireRange.start], e.localWires[wireRange.end-1]} + var ret QEAlgebra + for i := wireRange.start; i < wireRange.end; i++ { + ret[i-wireRange.start] = e.localWires[i] + } + + return ret }