@ -0,0 +1,80 @@ |
|||
package plonky2_verifier |
|||
|
|||
import ( |
|||
. "gnark-ed25519/field" |
|||
|
|||
"github.com/consensys/gnark/frontend" |
|||
) |
|||
|
|||
type QuadraticExtensionAPI struct { |
|||
field frontend.API |
|||
|
|||
W F |
|||
DTH_ROOT F |
|||
ZERO_F F |
|||
DEGREE_BITS_F F |
|||
|
|||
ONE QuadraticExtension |
|||
DEGREE_BITS_QE QuadraticExtension |
|||
} |
|||
|
|||
func NewQuadraticExtensionAPI(field frontend.API, degreeBits uint64) *QuadraticExtensionAPI { |
|||
// TODO: Should degreeBits be verified that it fits within the field?
|
|||
|
|||
return &QuadraticExtensionAPI{ |
|||
field: field, |
|||
|
|||
W: NewFieldElement(7), |
|||
DTH_ROOT: NewFieldElement(18446744069414584320), |
|||
ZERO_F: NewFieldElement(0), |
|||
DEGREE_BITS_F: NewFieldElement(degreeBits), |
|||
|
|||
ONE: QuadraticExtension{NewFieldElement(1), NewFieldElement(0)}, |
|||
DEGREE_BITS_QE: QuadraticExtension{NewFieldElement(degreeBits), NewFieldElement(0)}, |
|||
} |
|||
} |
|||
|
|||
func (c *QuadraticExtensionAPI) SquareExtension(a QuadraticExtension) QuadraticExtension { |
|||
return c.MulExtension(a, a) |
|||
} |
|||
|
|||
func (c *QuadraticExtensionAPI) MulExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension { |
|||
c_0 := c.field.Add(c.field.Mul(a[0], b[0]).(F), c.field.Mul(c.W, a[1], b[1])).(F) |
|||
c_1 := c.field.Add(c.field.Mul(a[0], b[1]).(F), c.field.Mul(a[1], b[0])).(F) |
|||
return QuadraticExtension{c_0, c_1} |
|||
} |
|||
|
|||
func (c *QuadraticExtensionAPI) AddExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension { |
|||
c_0 := c.field.Add(a[0], b[0]).(F) |
|||
c_1 := c.field.Add(a[1], b[1]).(F) |
|||
return QuadraticExtension{c_0, c_1} |
|||
} |
|||
|
|||
func (c *QuadraticExtensionAPI) SubExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension { |
|||
c_0 := c.field.Sub(a[0], b[0]).(F) |
|||
c_1 := c.field.Sub(a[1], b[1]).(F) |
|||
return QuadraticExtension{c_0, c_1} |
|||
} |
|||
|
|||
func (c *QuadraticExtensionAPI) DivExtension(a QuadraticExtension, b QuadraticExtension) QuadraticExtension { |
|||
return c.MulExtension(a, c.InverseExtension(b)) |
|||
} |
|||
|
|||
// TODO: Instead of calculating the inverse within the circuit, can witness the
|
|||
// inverse and assert that a_inverse * a = 1. Should reduce # of constraints.
|
|||
func (c *QuadraticExtensionAPI) InverseExtension(a QuadraticExtension) QuadraticExtension { |
|||
// First assert that a doesn't have 0 value coefficients
|
|||
a0_is_zero := c.field.IsZero(a[0]) |
|||
a1_is_zero := c.field.IsZero(a[1]) |
|||
|
|||
// assert that a0_is_zero OR a1_is_zero == false
|
|||
c.field.AssertIsEqual(c.field.Mul(a0_is_zero, a1_is_zero).(F), c.ZERO_F) |
|||
|
|||
a_pow_r_minus_1 := QuadraticExtension{a[0], c.field.Mul(a[1], c.DTH_ROOT).(F)} |
|||
a_pow_r := c.MulExtension(a_pow_r_minus_1, a) |
|||
return c.ScalarMulExtension(a_pow_r_minus_1, c.field.Inverse(a_pow_r[0]).(F)) |
|||
} |
|||
|
|||
func (c *QuadraticExtensionAPI) ScalarMulExtension(a QuadraticExtension, scalar F) QuadraticExtension { |
|||
return QuadraticExtension{c.field.Mul(a[0], scalar).(F), c.field.Mul(a[1], scalar).(F)} |
|||
} |
@ -0,0 +1,81 @@ |
|||
package plonky2_verifier |
|||
|
|||
import ( |
|||
"gnark-ed25519/field" |
|||
. "gnark-ed25519/field" |
|||
"testing" |
|||
|
|||
"github.com/consensys/gnark/frontend" |
|||
"github.com/consensys/gnark/test" |
|||
) |
|||
|
|||
// TODO: ADD MORE TEST CASES!!!
|
|||
|
|||
// Test for quadratic extension multiplication
|
|||
type TestQuadraticExtensionMulCircuit struct { |
|||
qeAPI *QuadraticExtensionAPI |
|||
|
|||
operand1 QuadraticExtension |
|||
operand2 QuadraticExtension |
|||
expectedResult QuadraticExtension |
|||
} |
|||
|
|||
func (c *TestQuadraticExtensionMulCircuit) Define(api frontend.API) error { |
|||
field := field.NewFieldAPI(api) |
|||
degreeBits := 3 |
|||
c.qeAPI = NewQuadraticExtensionAPI(field, uint64(degreeBits)) |
|||
|
|||
actualRes := c.qeAPI.MulExtension(c.operand1, c.operand2) |
|||
|
|||
field.AssertIsEqual(actualRes[0], c.expectedResult[0]) |
|||
field.AssertIsEqual(actualRes[1], c.expectedResult[1]) |
|||
|
|||
return nil |
|||
} |
|||
func TestQuadraticExtensionMul(t *testing.T) { |
|||
assert := test.NewAssert(t) |
|||
|
|||
operand1 := QuadraticExtension{NewFieldElement(4994088319481652598), NewFieldElement(16489566008211790727)} |
|||
operand2 := QuadraticExtension{NewFieldElement(3797605683985595697), NewFieldElement(13424401189265534004)} |
|||
expectedResult := QuadraticExtension{NewFieldElement(15052319864161058789), NewFieldElement(16841416332519902625)} |
|||
|
|||
circuit := TestQuadraticExtensionMulCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult} |
|||
witness := TestQuadraticExtensionMulCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult} |
|||
err := test.IsSolved(&circuit, &witness, TEST_CURVE.ScalarField()) |
|||
assert.NoError(err) |
|||
} |
|||
|
|||
// Test for quadratic extension division
|
|||
type TestQuadraticExtensionDivCircuit struct { |
|||
qeAPI *QuadraticExtensionAPI |
|||
|
|||
operand1 QuadraticExtension |
|||
operand2 QuadraticExtension |
|||
expectedResult QuadraticExtension |
|||
} |
|||
|
|||
func (c *TestQuadraticExtensionDivCircuit) Define(api frontend.API) error { |
|||
field := field.NewFieldAPI(api) |
|||
degreeBits := 3 |
|||
c.qeAPI = NewQuadraticExtensionAPI(field, uint64(degreeBits)) |
|||
|
|||
actualRes := c.qeAPI.DivExtension(c.operand1, c.operand2) |
|||
|
|||
field.AssertIsEqual(actualRes[0], c.expectedResult[0]) |
|||
field.AssertIsEqual(actualRes[1], c.expectedResult[1]) |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func TestQuadraticExtensionDiv(t *testing.T) { |
|||
assert := test.NewAssert(t) |
|||
|
|||
operand1 := QuadraticExtension{NewFieldElement(4994088319481652598), NewFieldElement(16489566008211790727)} |
|||
operand2 := QuadraticExtension{NewFieldElement(7166004739148609569), NewFieldElement(14655965871663555016)} |
|||
expectedResult := QuadraticExtension{NewFieldElement(15052319864161058789), NewFieldElement(16841416332519902625)} |
|||
|
|||
circuit := TestQuadraticExtensionDivCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult} |
|||
witness := TestQuadraticExtensionDivCircuit{operand1: operand1, operand2: operand2, expectedResult: expectedResult} |
|||
err := test.IsSolved(&circuit, &witness, TEST_CURVE.ScalarField()) |
|||
assert.NoError(err) |
|||
} |