Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Move polynomial file into its own package #88

Merged
merged 2 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions internal/erasure_code/erasure_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (

"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/crate-crypto/go-eth-kzg/internal/domain"
kzgmulti "github.com/crate-crypto/go-eth-kzg/internal/kzg_multi"
"github.com/crate-crypto/go-eth-kzg/internal/poly"
)

// BlockErasureIndex is used to indicate the index of the block erasure that is missing
Expand Down Expand Up @@ -140,7 +140,7 @@ func (dr *DataRecovery) RecoverPolynomialCoefficients(data []fr.Element, missing
}

// vanishingPolyCoeff returns the polynomial that has roots at the given points
func vanishingPolyCoeff(xs []fr.Element) kzgmulti.PolynomialCoeff {
func vanishingPolyCoeff(xs []fr.Element) poly.PolynomialCoeff {
result := []fr.Element{fr.One()}

for _, x := range xs {
Expand All @@ -149,7 +149,7 @@ func vanishingPolyCoeff(xs []fr.Element) kzgmulti.PolynomialCoeff {

negX := fr.Element{}
negX.Neg(&x)
result = kzgmulti.PolyMul(result, []fr.Element{negX, fr.One()})
result = poly.PolyMul(result, []fr.Element{negX, fr.One()})
}

return result
Expand Down
4 changes: 2 additions & 2 deletions internal/erasure_code/erasure_code_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import (
"testing"

"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
kzgmulti "github.com/crate-crypto/go-eth-kzg/internal/kzg_multi"
poly "github.com/crate-crypto/go-eth-kzg/internal/poly"
)

func TestVanishingPoly(t *testing.T) {
points := []fr.Element{fr.NewElement(1), fr.NewElement(2), fr.NewElement(3), fr.NewElement(4)}
vanishingPoly := vanishingPolyCoeff(points)
for _, point := range points {
eval := kzgmulti.PolyEval(vanishingPoly, point)
eval := poly.PolyEval(vanishingPoly, point)
if !eval.IsZero() {
t.Fatalf("expected evaluation at the vanishing polynomial to be zero")
}
Expand Down
3 changes: 2 additions & 1 deletion internal/kzg_multi/kzg_prove.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/crate-crypto/go-eth-kzg/internal/kzg_multi/fk20"
"github.com/crate-crypto/go-eth-kzg/internal/poly"
)

func ComputeMultiPointKZGProofs(fk20 *fk20.FK20, poly PolynomialCoeff) ([]bls12381.G1Affine, [][]fr.Element, error) {
func ComputeMultiPointKZGProofs(fk20 *fk20.FK20, poly poly.PolynomialCoeff) ([]bls12381.G1Affine, [][]fr.Element, error) {
proofs, err := fk20.ComputeMultiOpenProof(poly)
if err != nil {
return nil, nil, err
Expand Down
15 changes: 8 additions & 7 deletions internal/kzg_multi/kzg_prove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import (
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/crate-crypto/go-eth-kzg/internal/kzg"
"github.com/crate-crypto/go-eth-kzg/internal/kzg_multi/fk20"
"github.com/crate-crypto/go-eth-kzg/internal/poly"
)

func NaiveComputeMultiPointKZGProofs(fk20 *fk20.FK20, poly PolynomialCoeff, inputPoints [][]fr.Element, ck *kzg.CommitKey) ([]bls12381.G1Affine, [][]fr.Element, error) {
func NaiveComputeMultiPointKZGProofs(fk20 *fk20.FK20, poly poly.PolynomialCoeff, inputPoints [][]fr.Element, ck *kzg.CommitKey) ([]bls12381.G1Affine, [][]fr.Element, error) {
outputPointsSet := make([][]fr.Element, len(inputPoints))
proofs := make([]bls12381.G1Affine, len(inputPoints))

Expand All @@ -26,14 +27,14 @@ func NaiveComputeMultiPointKZGProofs(fk20 *fk20.FK20, poly PolynomialCoeff, inpu
// computeMultiPointKZGProof create a proof that when a polynomial f(x), is evaluated at a set of points `z_i`, the output is `y_i = f(z_i)`.
//
// The `y_i` values are computed and returned as part of the output.
func computeMultiPointKZGProof(poly PolynomialCoeff, inputPoints []fr.Element, ck *kzg.CommitKey) (bls12381.G1Affine, []fr.Element, error) {
func computeMultiPointKZGProof(polyCoeff poly.PolynomialCoeff, inputPoints []fr.Element, ck *kzg.CommitKey) (bls12381.G1Affine, []fr.Element, error) {
// Compute the evaluations of the polynomial on the input points
outputPoints := evalPolynomialOnInputPoints(poly, inputPoints)
outputPoints := evalPolynomialOnInputPoints(polyCoeff, inputPoints)

// Compute the quotient polynomial by dividing the polynomial by each input point
var quotient PolynomialCoeff = poly
var quotient poly.PolynomialCoeff = polyCoeff
for _, inputPoint := range inputPoints {
quotient = DividePolyByXminusA(quotient, inputPoint)
quotient = poly.DividePolyByXminusA(quotient, inputPoint)
}

// Commit to the quotient polynomial
Expand All @@ -46,11 +47,11 @@ func computeMultiPointKZGProof(poly PolynomialCoeff, inputPoints []fr.Element, c
}

// evalPolynomialOnInputPoints evaluates a polynomial on a set of input points.
func evalPolynomialOnInputPoints(poly PolynomialCoeff, inputPoints []fr.Element) []fr.Element {
func evalPolynomialOnInputPoints(polyCoeff poly.PolynomialCoeff, inputPoints []fr.Element) []fr.Element {
result := make([]fr.Element, 0, len(inputPoints))

for _, x := range inputPoints {
eval := PolyEval(poly, x)
eval := poly.PolyEval(polyCoeff, x)
result = append(result, eval)
}

Expand Down
7 changes: 4 additions & 3 deletions internal/kzg_multi/kzg_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/crate-crypto/go-eth-kzg/internal/kzg"
"github.com/crate-crypto/go-eth-kzg/internal/poly"
)

// vanishingPolyCoeff returns the polynomial that has roots at the given points
func vanishingPolyCoeff(xs []fr.Element) PolynomialCoeff {
func vanishingPolyCoeff(xs []fr.Element) poly.PolynomialCoeff {
result := []fr.Element{fr.One()}

for _, x := range xs {
Expand All @@ -16,7 +17,7 @@ func vanishingPolyCoeff(xs []fr.Element) PolynomialCoeff {

negX := fr.Element{}
negX.Neg(&x)
result = PolyMul(result, []fr.Element{negX, fr.One()})
result = poly.PolyMul(result, []fr.Element{negX, fr.One()})
}

return result
Expand All @@ -32,7 +33,7 @@ func VerifyMultiPointKZGProof(commitment, proof bls12381.G1Affine, outputPoints,
return err
}

interpolatedPoly := Interpolate(inputPoints, outputPoints)
interpolatedPoly := poly.LagrangeInterpolate(inputPoints, outputPoints)
interpolatedPolyComm, err := kzg.CommitG1(interpolatedPoly, openKey)
if err != nil {
return err
Expand Down
3 changes: 2 additions & 1 deletion internal/kzg_multi/kzg_verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"testing"

"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/crate-crypto/go-eth-kzg/internal/poly"
)

func TestVanishingPoly(t *testing.T) {
points := []fr.Element{fr.NewElement(1), fr.NewElement(2), fr.NewElement(3), fr.NewElement(4)}
vanishingPoly := vanishingPolyCoeff(points)
for _, point := range points {
eval := PolyEval(vanishingPoly, point)
eval := poly.PolyEval(vanishingPoly, point)
if !eval.IsZero() {
t.Fatalf("expected evaluation at the vanishing polynomial to be zero")
}
Expand Down
31 changes: 26 additions & 5 deletions internal/kzg_multi/poly.go → internal/poly/poly.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package kzgmulti
package poly

import (
"slices"

"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
)

// A polynomial in lagrange form
type Polynomial = []fr.Element

// A polynomial in monomial form
type PolynomialCoeff = []fr.Element

// PolyAdd adds two polynomials in coefficient form and returns the result.
// The resulting polynomial has a degree equal to the maximum degree of the input polynomials.
func PolyAdd(a, b PolynomialCoeff) PolynomialCoeff {
minPolyLen := min(numCoeffs(a), numCoeffs(b))
maxPolyLen := max(numCoeffs(a), numCoeffs(b))
Expand All @@ -34,6 +40,8 @@ func PolyAdd(a, b PolynomialCoeff) PolynomialCoeff {
return result
}

// PolyMul multiplies two polynomials in coefficient form and returns the result.
// The degree of the resulting polynomial is the sum of the degrees of the input polynomials.
func PolyMul(a, b PolynomialCoeff) PolynomialCoeff {
// The degree of result will be degree(a) + degree(b) = numCoeffs(a) + numCoeffs(b) - 1
productDegree := numCoeffs(a) + numCoeffs(b)
Expand All @@ -50,7 +58,11 @@ func PolyMul(a, b PolynomialCoeff) PolynomialCoeff {
return result
}

func Interpolate(xVec, yVec []fr.Element) PolynomialCoeff {
// LagrangeInterpolate computes the polynomial in coefficient form that passes through the given points.
// It takes two slices of equal length: xVec (x-coordinates) and yVec (y-coordinates).
//
// Note: This will only be used in tests.
func LagrangeInterpolate(xVec, yVec []fr.Element) PolynomialCoeff {
n := len(xVec)
if n != len(yVec) {
panic("Input vectors must have the same length")
Expand Down Expand Up @@ -81,6 +93,8 @@ func Interpolate(xVec, yVec []fr.Element) PolynomialCoeff {
return result
}

// equalPoly checks if two polynomials in coefficient form are equal.
// It removes trailing zeros (normalizes) before comparison.
func equalPoly(a, b PolynomialCoeff) bool {
a = removeTrailingZeros(a)
b = removeTrailingZeros(b)
Expand All @@ -103,8 +117,8 @@ func equalPoly(a, b PolynomialCoeff) bool {
return true
}

// PolyEval evaluates a polynomial f(x) at a point `z`; f(z)
// We denote `z` as `inputPoint`
// PolyEval evaluates a polynomial f(x) at a point z, computing f(z).
// The polynomial is given in coefficient form, and `z` is denoted as inputPoint.
func PolyEval(poly PolynomialCoeff, inputPoint fr.Element) fr.Element {
result := fr.NewElement(0)

Expand All @@ -119,6 +133,8 @@ func PolyEval(poly PolynomialCoeff, inputPoint fr.Element) fr.Element {

// DividePolyByXminusA computes f(x) / (x - a) and returns the quotient.
//
// Note: (x-a) is not a factor of f(x), the remainder will not be returned.
//
// This was copied and modified from the gnark codebase.
func DividePolyByXminusA(poly PolynomialCoeff, a fr.Element) []fr.Element {
// clone the slice so we do not modify the slice in place
Expand All @@ -143,7 +159,12 @@ func numCoeffs(p PolynomialCoeff) uint64 {
// Removes the higher coefficients from the polynomial
// that are zero.
//
// This has no impact on the actual polynomial. Its just normalizing.
// This method assumes that the slice is a polynomial where
// the higher coefficients are placed at the end of the slice,
// ie f(x) = 5 + 6x + 10x^2 would be [5, 6, 10] as a slice.
//
// This therefore has no impact on the polynomial and is just
// normalizing the polynomial.
func removeTrailingZeros(slice []fr.Element) []fr.Element {
for len(slice) > 0 && slice[len(slice)-1].IsZero() {
slice = slice[:len(slice)-1]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kzgmulti
package poly

import (
"testing"
Expand Down Expand Up @@ -29,7 +29,7 @@ func TestPolyMul(t *testing.T) {
func TestPolyInterpolate(t *testing.T) {
points := []fr.Element{fr.NewElement(1), fr.NewElement(2), fr.NewElement(3), fr.NewElement(4)}
values := []fr.Element{fr.NewElement(1), fr.NewElement(2), fr.NewElement(3), fr.NewElement(4)}
poly := Interpolate(points, values)
poly := LagrangeInterpolate(points, values)
for i, point := range points {
eval := PolyEval(poly, point)
if !eval.Equal(&values[i]) {
Expand Down
Loading