arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/plonky2_verifier/exponentiation_gate.go
plonky2_verifier/exponentiation_gate.goRaw
  1package plonky2_verifier
  2
  3import (
  4	"fmt"
  5	. "gnark-plonky2-verifier/field"
  6	"regexp"
  7	"strconv"
  8)
  9
 10var exponentiationGateRegex = regexp.MustCompile("ExponentiationGate { num_power_bits: (?P<numPowerBits>[0-9]+), _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=(?P<base>[0-9]+)>")
 11
 12func deserializeExponentiationGate(parameters map[string]string) gate {
 13	// Has the format "ExponentiationGate { num_power_bits: 67, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>"
 14	numPowerBits, hasNumPowerBits := parameters["numPowerBits"]
 15	if !hasNumPowerBits {
 16		panic("Missing field num_power_bits in ExponentiationGate")
 17	}
 18
 19	numPowerBitsInt, err := strconv.Atoi(numPowerBits)
 20	if err != nil {
 21		panic("Invalid num_power_bits field in ExponentiationGate")
 22	}
 23
 24	return NewExponentiationGate(uint64(numPowerBitsInt))
 25}
 26
 27type ExponentiationGate struct {
 28	numPowerBits uint64
 29}
 30
 31func NewExponentiationGate(numPowerBits uint64) *ExponentiationGate {
 32	return &ExponentiationGate{
 33		numPowerBits: numPowerBits,
 34	}
 35}
 36
 37func (g *ExponentiationGate) Id() string {
 38	return fmt.Sprintf("ExponentiationGate { num_power_bits: %d }", g.numPowerBits)
 39}
 40
 41func (g *ExponentiationGate) wireBase() uint64 {
 42	return 0
 43}
 44
 45// / The `i`th bit of the exponent, in little-endian order.
 46func (g *ExponentiationGate) wirePowerBit(i uint64) uint64 {
 47	if i >= g.numPowerBits {
 48		panic("Invalid power bit index")
 49	}
 50	return 1 + i
 51}
 52
 53func (g *ExponentiationGate) wireOutput() uint64 {
 54	return 1 + g.numPowerBits
 55}
 56
 57func (g *ExponentiationGate) wireIntermediateValue(i uint64) uint64 {
 58	if i >= g.numPowerBits {
 59		panic("Invalid intermediate value index")
 60	}
 61	return 2 + g.numPowerBits + i
 62}
 63
 64func (g *ExponentiationGate) EvalUnfiltered(p *PlonkChip, vars EvaluationVars) []QuadraticExtension {
 65	base := vars.localWires[g.wireBase()]
 66
 67	var powerBits []QuadraticExtension
 68	for i := uint64(0); i < g.numPowerBits; i++ {
 69		powerBits = append(powerBits, vars.localWires[g.wirePowerBit(i)])
 70	}
 71
 72	var intermediateValues []QuadraticExtension
 73	for i := uint64(0); i < g.numPowerBits; i++ {
 74		intermediateValues = append(intermediateValues, vars.localWires[g.wireIntermediateValue(i)])
 75	}
 76
 77	output := vars.localWires[g.wireOutput()]
 78
 79	var constraints []QuadraticExtension
 80
 81	for i := uint64(0); i < g.numPowerBits; i++ {
 82		var prevIntermediateValue QuadraticExtension
 83		if i == 0 {
 84			prevIntermediateValue = p.qeAPI.ONE_QE
 85		} else {
 86			prevIntermediateValue = p.qeAPI.SquareExtension(intermediateValues[i-1])
 87		}
 88
 89		// powerBits is in LE order, but we accumulate in BE order.
 90		curBit := powerBits[g.numPowerBits-i-1]
 91
 92		// Do a polynomial representation of generaized select (where the selector variable doesn't have to be binary)
 93		// if b { x } else { y }
 94		// i.e. `bx - (by-y)`.
 95		tmp := p.qeAPI.MulExtension(curBit, p.qeAPI.ONE_QE)
 96		tmp = p.qeAPI.SubExtension(tmp, p.qeAPI.ONE_QE)
 97		mulBy := p.qeAPI.MulExtension(curBit, base)
 98		mulBy = p.qeAPI.SubExtension(mulBy, tmp)
 99		intermediateValueDiff := p.qeAPI.MulExtension(prevIntermediateValue, mulBy)
100		intermediateValueDiff = p.qeAPI.SubExtension(intermediateValueDiff, intermediateValues[i])
101		constraints = append(constraints, intermediateValueDiff)
102	}
103
104	outputDiff := p.qeAPI.SubExtension(output, intermediateValues[g.numPowerBits-1])
105	constraints = append(constraints, outputDiff)
106
107	return constraints
108}