From e0657bfd9f580025bf09789ada3e890129caf9b4 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Wed, 23 Nov 2022 16:38:23 +0000 Subject: [PATCH 1/5] change PolyLinComb to also take the expected degree as a parameter --- bls/globals.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bls/globals.go b/bls/globals.go index dd6d1bf..dad60de 100644 --- a/bls/globals.go +++ b/bls/globals.go @@ -152,20 +152,19 @@ func EvaluatePolyInEvaluationForm(yFr *Fr, poly []Fr, x *Fr, rootsOfUnity []Fr, MulModFr(yFr, &y, &tmp) } -func PolyLinComb(vectors [][]Fr, scalars []Fr) ([]Fr, error) { +func PolyLinComb(vectors [][]Fr, scalars []Fr, polyDegree int) ([]Fr, error) { l := len(vectors) if l == 0 { - return nil, errors.New("input vectors can't be empty") + return make([]Fr, polyDegree), nil } if len(scalars) != l { return nil, errors.New("scalars should have same length as input vectors") } - vlen := len(vectors[0]) - r := make([]Fr, vlen) + r := make([]Fr, polyDegree) for j, v := range vectors { - if len(v) != vlen { + if len(v) != polyDegree { return nil, errors.New("input vectors should all be of identical length") } s := &scalars[j] From 5346fffd554b6144fc821e90333267c716e28bed Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Wed, 23 Nov 2022 16:39:27 +0000 Subject: [PATCH 2/5] - modify tests to match polyLinComb refactor. - Add a test to check that when we do a LinCombG1 with no elements, it returns the Zero element --- bls/bls_test.go | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/bls/bls_test.go b/bls/bls_test.go index cf02c84..6de8cf0 100644 --- a/bls/bls_test.go +++ b/bls/bls_test.go @@ -66,6 +66,16 @@ func TestPointG2Marshalling(t *testing.T) { } } +func TestEmptyG1Lincomb(t *testing.T) { + out := LinCombG1([]G1Point{}, []Fr{}) + if out == nil { + t.Fatal("got nil, expected result when given 0 points and 0 scalars should be the zero group element") + } + + if !EqualG1(out, &ZeroG1) { + t.Fatalf("Expected zero group element, got:\n%s", StrG1(out)) + } +} func TestPolyLincomb(t *testing.T) { var x1, x2, x3, x4 Fr SetFr(&x1, "1") @@ -73,31 +83,37 @@ func TestPolyLincomb(t *testing.T) { SetFr(&x3, "3") SetFr(&x4, "4") vec := []Fr{x1, x2, x3, x4} + degree := len(vec) // Happy path: valid inputs - r, err := PolyLinComb([][]Fr{vec, vec, vec, vec}, vec) + r, err := PolyLinComb([][]Fr{vec, vec, vec, vec}, vec, degree) if err != nil { t.Fatal(err) } - if len(r) != 4 { - t.Fatalf("Expected result of length 4, got %v", len(r)) + if len(r) != degree { + t.Fatalf("Expected result of length %v, got %v", degree, len(r)) } // Error path: empty input - r, err = PolyLinComb([][]Fr{}, []Fr{}) - if err == nil { - t.Fatal("Expected error, got none") + r, err = PolyLinComb([][]Fr{}, []Fr{}, degree) + if err != nil { + t.Fatalf("Expected the zero polynomial of degree %v \ngot an error: %v", degree, err) + } + for i := 0; i < degree; i++ { + if !EqualFr(&r[i], &ZERO) { + t.Fatal("Expected the zero polynomial") + } } // Error path: vectors not same length shortVec := []Fr{x1, x2, x3} - r, err = PolyLinComb([][]Fr{vec, vec, shortVec, vec}, vec) + _, err = PolyLinComb([][]Fr{vec, vec, shortVec, vec}, vec, degree) if err == nil { t.Fatal("Expected error, got none") } // Error path: Scalar vector size doesn't match - r, err = PolyLinComb([][]Fr{vec, vec, vec, vec}, shortVec) + _, err = PolyLinComb([][]Fr{vec, vec, vec, vec}, shortVec, degree) if err == nil { t.Fatal("Expected error, got none") } From 363b22e94e1935579994da05ac9df9dc22d6ea02 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Wed, 23 Nov 2022 16:40:27 +0000 Subject: [PATCH 3/5] Modidy Eth package to match consensus-specs PR 3093 --- eth/helpers.go | 62 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/eth/helpers.go b/eth/helpers.go index 1448137..4d09db5 100644 --- a/eth/helpers.go +++ b/eth/helpers.go @@ -157,20 +157,12 @@ func BytesToBLSField(h [32]byte) *bls.Fr { // https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md#compute_aggregated_poly_and_commitment func ComputeAggregatedPolyAndCommitment(blobs Polynomials, commitments KZGCommitmentSequence) ([]bls.Fr, *bls.G1Point, *bls.Fr, error) { // create challenges - r, err := HashToBLSField(blobs, commitments) + powers, evaluationChallenge, err := ComputeChallenges(blobs, commitments) if err != nil { return nil, nil, nil, err } - powers := ComputePowers(r, len(blobs)) - if len(powers) == 0 { - return nil, nil, nil, errors.New("powers can't be 0 length") - } - - var evaluationChallenge bls.Fr - bls.MulModFr(&evaluationChallenge, r, &powers[len(powers)-1]) - - aggregatedPoly, err := bls.PolyLinComb(blobs, powers) + aggregatedPoly, err := bls.PolyLinComb(blobs, powers, FieldElementsPerBlob) if err != nil { return nil, nil, nil, err } @@ -186,7 +178,7 @@ func ComputeAggregatedPolyAndCommitment(blobs Polynomials, commitments KZGCommit bls.CopyG1(&commitmentsG1[i], p) } aggregatedCommitmentG1 := bls.LinCombG1(commitmentsG1, powers) - return aggregatedPoly, aggregatedCommitmentG1, &evaluationChallenge, nil + return aggregatedPoly, aggregatedCommitmentG1, evaluationChallenge, nil } // ComputeAggregateKZGProofFromPolynomials implements compute_aggregate_kzg_proof from the EIP-4844 @@ -239,28 +231,57 @@ func EvaluatePolynomialInEvaluationForm(poly []bls.Fr, x *bls.Fr) *bls.Fr { return &result } -// HashToBLSField implements hash_to_bls_field from the EIP-4844 consensus specs: -// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md#hash_to_bls_field -func HashToBLSField(polys Polynomials, comms KZGCommitmentSequence) (*bls.Fr, error) { +func ComputeChallenges(polys Polynomials, comms KZGCommitmentSequence) ([]bls.Fr, *bls.Fr, error) { + hash, err := hashPolysComms(polys, comms) + if err != nil { + return nil, nil, err + } + + var linCombChallengeTranscript = append(hash[:], 0) + var evalChallengeTranscript = append(hash[:], 1) + + shaHashToField := func(input []byte) *bls.Fr { + sha := sha256.New() + sha.Write(input) + + var hash32 [32]byte + copy(hash32[:], sha.Sum(nil)) + + return BytesToBLSField(hash32) + } + + linCombChallenge := shaHashToField(linCombChallengeTranscript) + evalChallenge := shaHashToField(evalChallengeTranscript) + + rPowers := ComputePowers(linCombChallenge, len(polys)) + + return rPowers, evalChallenge, nil + +} + +// Adds the domain separator, polynomials and commitments into a buffer, returning the +// hash of this buffer +func hashPolysComms(polys Polynomials, comms KZGCommitmentSequence) ([32]byte, error) { sha := sha256.New() + var hash [32]byte _, err := sha.Write([]byte(FIAT_SHAMIR_PROTOCOL_DOMAIN)) if err != nil { - return nil, err + return hash, err } bytes := make([]byte, 8) binary.LittleEndian.PutUint64(bytes, uint64(FieldElementsPerBlob)) _, err = sha.Write(bytes) if err != nil { - return nil, err + return hash, err } bytes = make([]byte, 8) binary.LittleEndian.PutUint64(bytes, uint64(len(polys))) _, err = sha.Write(bytes) if err != nil { - return nil, err + return hash, err } for _, poly := range polys { @@ -268,7 +289,7 @@ func HashToBLSField(polys Polynomials, comms KZGCommitmentSequence) (*bls.Fr, er b32 := bls.FrTo32(&fe) _, err := sha.Write(b32[:]) if err != nil { - return nil, err + return hash, err } } } @@ -277,12 +298,11 @@ func HashToBLSField(polys Polynomials, comms KZGCommitmentSequence) (*bls.Fr, er c := comms.At(i) _, err := sha.Write(c[:]) if err != nil { - return nil, err + return hash, err } } - var hash [32]byte copy(hash[:], sha.Sum(nil)) - return BytesToBLSField(hash), nil + return hash, nil } func BlobToPolynomial(b Blob) (Polynomial, bool) { From dcead1d066a60e0e6f97a4319baf1ae4477528e2 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Wed, 23 Nov 2022 16:46:52 +0000 Subject: [PATCH 4/5] Add spec comment for ComputeChallenges --- eth/helpers.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eth/helpers.go b/eth/helpers.go index 4d09db5..9efcf7a 100644 --- a/eth/helpers.go +++ b/eth/helpers.go @@ -231,6 +231,8 @@ func EvaluatePolynomialInEvaluationForm(poly []bls.Fr, x *bls.Fr) *bls.Fr { return &result } +// ComputeChallenges implements compute_challenges from the EIP-4844 consensus spec: +// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md#compute_challenges func ComputeChallenges(polys Polynomials, comms KZGCommitmentSequence) ([]bls.Fr, *bls.Fr, error) { hash, err := hashPolysComms(polys, comms) if err != nil { From 7eab2c90f28dc4a583b48ee6551bd1c138a9dd17 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Wed, 23 Nov 2022 17:55:16 +0000 Subject: [PATCH 5/5] remove error handling from sha256 write method --- eth/helpers.go | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/eth/helpers.go b/eth/helpers.go index 9efcf7a..36ed442 100644 --- a/eth/helpers.go +++ b/eth/helpers.go @@ -267,41 +267,26 @@ func hashPolysComms(polys Polynomials, comms KZGCommitmentSequence) ([32]byte, e sha := sha256.New() var hash [32]byte - _, err := sha.Write([]byte(FIAT_SHAMIR_PROTOCOL_DOMAIN)) - if err != nil { - return hash, err - } + sha.Write([]byte(FIAT_SHAMIR_PROTOCOL_DOMAIN)) bytes := make([]byte, 8) binary.LittleEndian.PutUint64(bytes, uint64(FieldElementsPerBlob)) - _, err = sha.Write(bytes) - if err != nil { - return hash, err - } + sha.Write(bytes) bytes = make([]byte, 8) binary.LittleEndian.PutUint64(bytes, uint64(len(polys))) - _, err = sha.Write(bytes) - if err != nil { - return hash, err - } + sha.Write(bytes) for _, poly := range polys { for _, fe := range poly { b32 := bls.FrTo32(&fe) - _, err := sha.Write(b32[:]) - if err != nil { - return hash, err - } + sha.Write(b32[:]) } } l := comms.Len() for i := 0; i < l; i++ { c := comms.At(i) - _, err := sha.Write(c[:]) - if err != nil { - return hash, err - } + sha.Write(c[:]) } copy(hash[:], sha.Sum(nil)) return hash, nil