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 . "gnark-ed25519/field"
7 "math/bits"
8
9 "github.com/consensys/gnark/frontend"
10)
11
12type QuadraticExtensionAPI struct {
13 fieldAPI frontend.API
14
15 W F
16 DTH_ROOT F
17
18 ONE QuadraticExtension
19 ZERO_QE QuadraticExtension
20}
21
22func NewQuadraticExtensionAPI(fieldAPI frontend.API, degreeBits uint64) *QuadraticExtensionAPI {
23 // TODO: Should degreeBits be verified that it fits within the field and that degree is within uint64?
24
25 return &QuadraticExtensionAPI{
26 fieldAPI: fieldAPI,
27
28 W: NewFieldElement(7),
29 DTH_ROOT: NewFieldElement(18446744069414584320),
30
31 ONE: QuadraticExtension{ONE_F, ZERO_F},
32 ZERO_QE: QuadraticExtension{ZERO_F, ZERO_F},
33 }
34}
35
36func (c *QuadraticExtensionAPI) SquareExtension(a QuadraticExtension) QuadraticExtension {
37 return c.MulExtension(a, a)
38}
39
40func (c *QuadraticExtensionAPI) MulExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
41 c_0 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[0]).(F), c.fieldAPI.Mul(c.W, a[1], b[1])).(F)
42 c_1 := c.fieldAPI.Add(c.fieldAPI.Mul(a[0], b[1]).(F), c.fieldAPI.Mul(a[1], b[0])).(F)
43 return QuadraticExtension{c_0, c_1}
44}
45
46func (c *QuadraticExtensionAPI) AddExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
47 c_0 := c.fieldAPI.Add(a[0], b[0]).(F)
48 c_1 := c.fieldAPI.Add(a[1], b[1]).(F)
49 return QuadraticExtension{c_0, c_1}
50}
51
52func (c *QuadraticExtensionAPI) SubExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
53 c_0 := c.fieldAPI.Sub(a[0], b[0]).(F)
54 c_1 := c.fieldAPI.Sub(a[1], b[1]).(F)
55 return QuadraticExtension{c_0, c_1}
56}
57
58func (c *QuadraticExtensionAPI) DivExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension {
59 return c.MulExtension(a, c.InverseExtension(b))
60}
61
62// TODO: Instead of calculating the inverse within the circuit, can witness the
63// inverse and assert that a_inverse * a = 1. Should reduce # of constraints.
64func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension {
65 // First assert that a doesn't have 0 value coefficients
66 a0_is_zero := c.fieldAPI.IsZero(a[0])
67 a1_is_zero := c.fieldAPI.IsZero(a[1])
68
69 // assert that a0_is_zero OR a1_is_zero == false
70 c.fieldAPI.AssertIsEqual(c.fieldAPI.Mul(a0_is_zero, a1_is_zero).(F), field.ZERO_F)
71
72 a_pow_r_minus_1 := QuadraticExtension{a[0], c.fieldAPI.Mul(a[1], c.DTH_ROOT).(F)}
73 a_pow_r := c.MulExtension(a_pow_r_minus_1, a)
74 return c.ScalarMulExtension(a_pow_r_minus_1, c.fieldAPI.Inverse(a_pow_r[0]).(F))
75}
76
77func (c *QuadraticExtensionAPI) ScalarMulExtension(a QuadraticExtension, scalar F) QuadraticExtension {
78 return QuadraticExtension{c.fieldAPI.Mul(a[0], scalar).(F), c.fieldAPI.Mul(a[1], scalar).(F)}
79}
80
81func (c *QuadraticExtensionAPI) FieldToQE(a F) QuadraticExtension {
82 return QuadraticExtension{a, field.ZERO_F}
83}
84
85// / Exponentiate `base` to the power of a known `exponent`.
86func (c *QuadraticExtensionAPI) ExpU64Extension(a QuadraticExtension, exponent uint64) QuadraticExtension {
87 switch exponent {
88 case 0:
89 return c.ONE
90 case 1:
91 return a
92 case 2:
93 return c.SquareExtension(a)
94 default:
95 }
96
97 current := a
98 product := c.ONE
99
100 for i := 0; i < bits.Len64(exponent); i++ {
101 if i != 0 {
102 current = c.SquareExtension(current)
103 }
104
105 if (exponent >> i & 1) != 0 {
106 product = c.MulExtension(product, current)
107 }
108 }
109
110 return product
111}
112
113func (c *QuadraticExtensionAPI) Println(a QuadraticExtension) {
114 fmt.Print("Degree 0 coefficient")
115 c.fieldAPI.Println(a[0])
116
117 fmt.Print("Degree 1 coefficient")
118 c.fieldAPI.Println(a[1])
119}