Skip to content

Commit

Permalink
[1/N] Chunk encoding optimization: Support encoding format with gnark (
Browse files Browse the repository at this point in the history
  • Loading branch information
jianoaix authored and pschork committed Jun 26, 2024
1 parent 66e6ff3 commit 55547f6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
36 changes: 36 additions & 0 deletions encoding/serialization.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/gob"
"encoding/json"
"errors"
"fmt"

"github.com/consensys/gnark-crypto/ecc/bn254"
Expand All @@ -22,6 +23,41 @@ func (c *Frame) Deserialize(data []byte) (*Frame, error) {
return c, err
}

func (c *Frame) SerializeGnark() ([]byte, error) {
coded := make([]byte, 0, bn254.SizeOfG1AffineCompressed+BYTES_PER_SYMBOL*len(c.Coeffs))
// This is compressed format with just 32 bytes.
proofBytes := c.Proof.Bytes()
coded = append(coded, proofBytes[:]...)
for _, coeff := range c.Coeffs {
coded = append(coded, coeff.Marshal()...)
}
return coded, nil
}

func (c *Frame) DeserializeGnark(data []byte) (*Frame, error) {
var f Frame
buf := data
err := f.Proof.Unmarshal(buf[:bn254.SizeOfG1AffineCompressed])
if err != nil {
return nil, err
}
buf = buf[bn254.SizeOfG1AffineCompressed:]
if len(buf)%BYTES_PER_SYMBOL != 0 {
return nil, errors.New("invalid chunk length")
}
f.Coeffs = make([]Symbol, len(buf)/BYTES_PER_SYMBOL)
i := 0
for len(buf) > 0 {
if len(buf) < BYTES_PER_SYMBOL {
return nil, errors.New("invalid chunk length")
}
f.Coeffs[i].Unmarshal(buf[:BYTES_PER_SYMBOL])
i++
buf = buf[BYTES_PER_SYMBOL:]
}
return &f, nil
}

func (f *Frame) Encode() ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
Expand Down
47 changes: 47 additions & 0 deletions encoding/serialization_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package encoding_test

import (
"testing"

"github.com/Layr-Labs/eigenda/encoding"
"github.com/consensys/gnark-crypto/ecc/bn254/fp"
"github.com/consensys/gnark-crypto/ecc/bn254/fr"
"github.com/stretchr/testify/assert"
)

func TestSerDeserGnark(t *testing.T) {
var XCoord, YCoord fp.Element
_, err := XCoord.SetString("21661178944771197726808973281966770251114553549453983978976194544185382599016")
assert.NoError(t, err)
_, err = YCoord.SetString("9207254729396071334325696286939045899948985698134704137261649190717970615186")
assert.NoError(t, err)

numCoeffs := 64
var f encoding.Frame
f.Proof = encoding.Proof{
X: XCoord,
Y: YCoord,
}
for i := 0; i < numCoeffs; i++ {
f.Coeffs = append(f.Coeffs, fr.NewElement(uint64(i)))
}

gnark, err := f.SerializeGnark()
assert.Nil(t, err)
// The gnark encoding via f.Serialize() will generate less bytes
// than gob.
assert.Equal(t, 32*(1+numCoeffs), len(gnark))
gob, err := f.Serialize()
assert.Nil(t, err)
// 2080 with gnark v.s. 2574 with gob
assert.Equal(t, 2574, len(gob))

// Verify the deserialization can get back original data
c, err := new(encoding.Frame).DeserializeGnark(gnark)
assert.Nil(t, err)
assert.True(t, f.Proof.Equal(&c.Proof))
assert.Equal(t, len(f.Coeffs), len(c.Coeffs))
for i := 0; i < len(f.Coeffs); i++ {
assert.True(t, f.Coeffs[i].Equal(&c.Coeffs[i]))
}
}

0 comments on commit 55547f6

Please sign in to comment.