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

Refactor 4844 code to match consensus-specs PR 3093 #32

Merged
merged 5 commits into from
Nov 29, 2022
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
32 changes: 24 additions & 8 deletions bls/bls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,38 +66,54 @@ 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")
SetFr(&x2, "2")
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")
}
Expand Down
9 changes: 4 additions & 5 deletions bls/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
protolambda marked this conversation as resolved.
Show resolved Hide resolved
l := len(vectors)
protolambda marked this conversation as resolved.
Show resolved Hide resolved
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]
Expand Down
79 changes: 43 additions & 36 deletions eth/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
Expand Down Expand Up @@ -239,50 +231,65 @@ 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) {
sha := sha256.New()

_, err := sha.Write([]byte(FIAT_SHAMIR_PROTOCOL_DOMAIN))
// 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 {
return nil, err
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

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 nil, err
}
sha.Write(bytes)

bytes = make([]byte, 8)
binary.LittleEndian.PutUint64(bytes, uint64(len(polys)))
_, err = sha.Write(bytes)
if err != nil {
return nil, err
}
sha.Write(bytes)

for _, poly := range polys {
for _, fe := range poly {
b32 := bls.FrTo32(&fe)
_, err := sha.Write(b32[:])
if err != nil {
return nil, 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 nil, err
}
sha.Write(c[:])
}
var hash [32]byte
copy(hash[:], sha.Sum(nil))
return BytesToBLSField(hash), nil
return hash, nil
}

func BlobToPolynomial(b Blob) (Polynomial, bool) {
Expand Down