arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/plonky2_verifier/quadratic_extension.go
plonky2_verifier/quadratic_extension.goRaw
  1package plonky2_verifier
  2
  3import (
  4	"fmt"
  5	. "gnark-ed25519/field"
  6	"math/bits"
  7
  8	"github.com/consensys/gnark/frontend"
  9)
 10
 11type QuadraticExtensionAPI struct {
 12	fieldAPI frontend.API
 13
 14	W        F
 15	DTH_ROOT F
 16
 17	ONE_QE  QuadraticExtension
 18	ZERO_QE QuadraticExtension
 19}
 20
 21func NewQuadraticExtensionAPI(fieldAPI frontend.API, degreeBits uint64) *QuadraticExtensionAPI {
 22	// TODO:  Should degreeBits be verified that it fits within the field and that degree is within uint64?
 23
 24	return &QuadraticExtensionAPI{
 25		fieldAPI: fieldAPI,
 26
 27		W:        NewFieldElement(7),
 28		DTH_ROOT: NewFieldElement(18446744069414584320),
 29
 30		ONE_QE:  QuadraticExtension{ONE_F, ZERO_F},
 31		ZERO_QE: QuadraticExtension{ZERO_F, ZERO_F},
 32	}
 33}
 34
 35func (c *QuadraticExtensionAPI) SquareExtension(a QuadraticExtension) QuadraticExtension {
 36	return c.MulExtension(a, a)
 37}
 38
 39func (c *QuadraticExtensionAPI) MulExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
 40	c_0 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[0]).(F), c.fieldAPI.Mul(c.W, a[1], b[1])).(F)
 41	c_1 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[1]).(F), c.fieldAPI.Mul(a[1], b[0])).(F)
 42	return QuadraticExtension{c_0, c_1}
 43}
 44
 45func (c *QuadraticExtensionAPI) AddExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
 46	c_0 := c.fieldAPI.Add(a[0], b[0]).(F)
 47	c_1 := c.fieldAPI.Add(a[1], b[1]).(F)
 48	return QuadraticExtension{c_0, c_1}
 49}
 50
 51func (c *QuadraticExtensionAPI) SubExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
 52	c_0 := c.fieldAPI.Sub(a[0], b[0]).(F)
 53	c_1 := c.fieldAPI.Sub(a[1], b[1]).(F)
 54	return QuadraticExtension{c_0, c_1}
 55}
 56
 57func (c *QuadraticExtensionAPI) DivExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
 58	return c.MulExtension(a, c.InverseExtension(b))
 59}
 60
 61func (c *QuadraticExtensionAPI) IsZero(a QuadraticExtension) frontend.Variable {
 62	return c.fieldAPI.Mul(c.fieldAPI.IsZero(a[0]), c.fieldAPI.IsZero(a[1]))
 63}
 64
 65// TODO: Instead of calculating the inverse within the circuit, can witness the
 66// inverse and assert that a_inverse * a = 1.  Should reduce # of constraints.
 67func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension {
 68	// First assert that a doesn't have 0 value coefficients
 69	a0_is_zero := c.fieldAPI.IsZero(a[0])
 70	a1_is_zero := c.fieldAPI.IsZero(a[1])
 71
 72	// assert that a0_is_zero OR a1_is_zero == false
 73	c.fieldAPI.AssertIsEqual(c.fieldAPI.Mul(a0_is_zero, a1_is_zero).(F), ZERO_F)
 74
 75	a_pow_r_minus_1 := QuadraticExtension{a[0], c.fieldAPI.Mul(a[1], c.DTH_ROOT).(F)}
 76	a_pow_r := c.MulExtension(a_pow_r_minus_1, a)
 77	return c.ScalarMulExtension(a_pow_r_minus_1, c.fieldAPI.Inverse(a_pow_r[0]).(F))
 78}
 79
 80func (c *QuadraticExtensionAPI) ScalarMulExtension(a QuadraticExtension, scalar F) QuadraticExtension {
 81	return QuadraticExtension{c.fieldAPI.Mul(a[0], scalar).(F), c.fieldAPI.Mul(a[1], scalar).(F)}
 82}
 83
 84func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension {
 85	return QuadraticExtension{a, ZERO_F}
 86}
 87
 88// / Exponentiate `base` to the power of a known `exponent`.
 89func (c *QuadraticExtensionAPI) ExpU64Extension(a QuadraticExtension, exponent uint64) QuadraticExtension {
 90	switch exponent {
 91	case 0:
 92		return c.ONE_QE
 93	case 1:
 94		return a
 95	case 2:
 96		return c.SquareExtension(a)
 97	default:
 98	}
 99
100	current := a
101	product := c.ONE_QE
102
103	for i := 0; i < bits.Len64(exponent); i++ {
104		if i != 0 {
105			current = c.SquareExtension(current)
106		}
107
108		if (exponent >> i & 1) != 0 {
109			product = c.MulExtension(product, current)
110		}
111	}
112
113	return product
114}
115
116func (c *QuadraticExtensionAPI) ReduceWithPowers(terms []QuadraticExtension, scalar QuadraticExtension) QuadraticExtension {
117	sum := c.ZERO_QE
118
119	for i := len(terms) - 1; i >= 0; i-- {
120		sum = c.AddExtension(
121			c.MulExtension(
122				sum,
123				scalar,
124			),
125			terms[i],
126		)
127	}
128
129	return sum
130}
131
132func (c *QuadraticExtensionAPI) Select(b0 frontend.Variable, qe0, qe1 QuadraticExtension) QuadraticExtension {
133	var retQE QuadraticExtension
134
135	for i := 0; i < 2; i++ {
136		retQE[i] = c.fieldAPI.Select(b0, qe0[i], qe1[i]).(F)
137	}
138
139	return retQE
140}
141
142func (c *QuadraticExtensionAPI) Lookup2(b0 frontend.Variable, b1 frontend.Variable, qe0, qe1, qe2, qe3 QuadraticExtension) QuadraticExtension {
143	var retQE QuadraticExtension
144
145	for i := 0; i < 2; i++ {
146		retQE[i] = c.fieldAPI.Lookup2(b0, b1, qe0[i], qe1[i], qe2[i], qe3[i]).(F)
147	}
148
149	return retQE
150}
151
152func (c *QuadraticExtensionAPI) AssertIsEqual(a, b QuadraticExtension) {
153	for i := 0; i < 2; i++ {
154		c.fieldAPI.AssertIsEqual(a[0], b[0])
155	}
156}
157
158func (c *QuadraticExtensionAPI) Println(a QuadraticExtension) {
159	fmt.Print("Degree 0 coefficient")
160	c.fieldAPI.Println(a[0])
161
162	fmt.Print("Degree 1 coefficient")
163	c.fieldAPI.Println(a[1])
164}