Skip to content

Commit

Permalink
adding deneb p2p containers (#7401)
Browse files Browse the repository at this point in the history
This PR adds the new p2p containers from Deneb into Caplin 
#7389
  • Loading branch information
enriavil1 authored Apr 29, 2023
1 parent 250a0a4 commit f363eb1
Show file tree
Hide file tree
Showing 2 changed files with 345 additions and 0 deletions.
200 changes: 200 additions & 0 deletions cl/cltypes/beacon_blob_side_car.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package cltypes

import (
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/cltypes/ssz"
"github.com/ledgerwatch/erigon/cl/merkle_tree"
)

type Root [32]byte
type Slot uint64
type Blob gokzg4844.Blob
type KZGCommitment gokzg4844.KZGCommitment // [48]byte
type KZGProof gokzg4844.KZGProof // [48]byte

type BlobSideCar struct {
BlockRoot Root
Index uint64 // index of blob in block
Slot Slot
BlockParentRoot Root
ProposerIndex uint64 // validator index
Blob Blob
KZGCommitment KZGCommitment
KZGProof KZGProof
}

// https://github.com/ethereum/consensus-specs/blob/3a2304981a3b820a22b518fe4859f4bba0ebc83b/specs/deneb/polynomial-commitments.md#custom-types
const BYTES_PER_FIELD_ELEMENT = 32
const FIELD_ELEMENTS_PER_BLOB = 4096
const BYTES_PER_BLOB = uint64(BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB)

func (b *BlobSideCar) Copy() *BlobSideCar {
copied := *b
return &copied
}

func (b *BlobSideCar) EncodeSSZ(buf []byte) ([]byte, error) {
buf = append(buf, b.BlockRoot[:]...)
buf = append(buf, ssz.Uint64SSZ(b.Index)...)
buf = append(buf, ssz.Uint64SSZ(uint64(b.Slot))...)
buf = append(buf, b.BlockParentRoot[:]...)
buf = append(buf, ssz.Uint64SSZ(b.ProposerIndex)...)
buf = append(buf, b.Blob[:]...)
buf = append(buf, b.KZGCommitment[:]...)
buf = append(buf, b.KZGProof[:]...)

return buf, nil
}

func (b *BlobSideCar) DecodeSSZ(buf []byte) error {
pos := 0 // current position at the buffer

copy(b.BlockRoot[:], buf[pos:32])
pos += 32

b.Index = ssz.UnmarshalUint64SSZ(buf[pos : pos+8])
pos += 8

b.Slot = Slot(ssz.UnmarshalUint64SSZ(buf[pos:]))
pos += 8

copy(b.BlockParentRoot[:], buf[pos:pos+32])
pos += 32

b.ProposerIndex = ssz.UnmarshalUint64SSZ(buf[pos : pos+8])
pos += 8

copy(b.Blob[:], buf[pos:pos+int(BYTES_PER_BLOB)])
pos += int(BYTES_PER_BLOB)

copy(b.KZGCommitment[:], buf[pos:pos+48])
pos += 48

copy(b.KZGProof[:], buf[pos:pos+48])

return nil
}

func (b *BlobSideCar) EncodingSizeSSZ() int {
return 131_256
}

func (b *BlobSideCar) HashSSZ() (libcommon.Hash, error) {
KZGCommitmentLeave, err := merkle_tree.PublicKeyRoot(b.KZGCommitment)
if err != nil {
return libcommon.Hash{}, err
}
KZGProofLeave, err := merkle_tree.PublicKeyRoot(b.KZGProof)
if err != nil {
return libcommon.Hash{}, err
}

blobLeave := [][32]byte{}
previous_pos := 0
for pos := 32; pos < int(BYTES_PER_BLOB)/32; pos += 32 {
blobLeave = append(blobLeave, libcommon.BytesToHash(b.Blob[previous_pos:pos]))
previous_pos = pos
}

blobRoot, err := merkle_tree.ArraysRoot(blobLeave, 4096)
if err != nil {
return libcommon.Hash{}, err
}

return merkle_tree.ArraysRoot([][32]byte{
b.BlockRoot,
merkle_tree.Uint64Root(b.Index),
merkle_tree.Uint64Root(uint64(b.Slot)),
b.BlockParentRoot,
merkle_tree.Uint64Root(b.ProposerIndex),
blobRoot,
KZGCommitmentLeave,
KZGProofLeave,
}, 8)
}

type SignedBlobSideCar struct {
Message BlobSideCar
Signature [96]byte
}

func (b *SignedBlobSideCar) Copy() *SignedBlobSideCar {
copy := *b
return &copy
}

func (b *SignedBlobSideCar) EncodeSSZ(buf []byte) ([]byte, error) {
encodedMessage, _ := b.Message.EncodeSSZ([]byte{})

buf = append(buf, encodedMessage...)
buf = append(buf, b.Signature[:]...)

return buf, nil
}

func (b *SignedBlobSideCar) DecodeSSZ(buf []byte) error {
pos := b.Message.EncodingSizeSSZ()
err := b.Message.DecodeSSZ(buf[:pos])
if err != nil {
return err
}
copy(b.Signature[:], buf[pos:])

return nil
}

func (b *SignedBlobSideCar) EncodingSizeSSZ() int {
return b.Message.EncodingSizeSSZ() + 96
}

func (b *SignedBlobSideCar) HashSSZ() (libcommon.Hash, error) {
messageLeave, err := b.Message.HashSSZ()
if err != nil {
return libcommon.Hash{}, err
}

signatureLeave, err := merkle_tree.SignatureRoot(b.Signature)
if err != nil {
return libcommon.Hash{}, err
}

return merkle_tree.ArraysRoot([][32]byte{
messageLeave,
signatureLeave,
}, 2)
}

type BlobIdentifier struct {
BlockRoot Root
Index uint64
}

func (b *BlobIdentifier) Copy() *BlobIdentifier {
copy := *b
return &copy
}

func (b *BlobIdentifier) EncodeSSZ(buf []byte) ([]byte, error) {
buf = append(buf, b.BlockRoot[:]...)
buf = append(buf, ssz.Uint64SSZ(b.Index)...)

return buf, nil
}

func (b *BlobIdentifier) DecodeSSZ(buf []byte) error {
copy(b.BlockRoot[:], buf[:32])
b.Index = ssz.UnmarshalUint64SSZ(buf[32:])
return nil
}

func (b *BlobIdentifier) EncodingSizeSSZ() int {
return 40
}

func (b *BlobIdentifier) HashSSZ() (libcommon.Hash, error) {
return merkle_tree.ArraysRoot([][32]byte{
b.BlockRoot,
merkle_tree.Uint64Root(b.Index),
}, 2)
}
145 changes: 145 additions & 0 deletions cl/cltypes/beacon_blob_side_car_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package cltypes_test

import (
"bytes"
"testing"

"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/stretchr/testify/assert"
)

func TestBlobSideCar_EncodeDecodeSSZ(t *testing.T) {
blockRoot := cltypes.Root{1, 2, 3}
index := uint64(123)
slot := cltypes.Slot(456)
blockParentRoot := cltypes.Root{4, 5, 6}
proposerIndex := uint64(789)
blob := cltypes.Blob{}
kzgCommitment := cltypes.KZGCommitment{7, 8, 9}
kzgProof := cltypes.KZGProof{10, 11, 12}

sideCar := &cltypes.BlobSideCar{
BlockRoot: blockRoot,
Index: index,
Slot: slot,
BlockParentRoot: blockParentRoot,
ProposerIndex: proposerIndex,
Blob: blob,
KZGCommitment: kzgCommitment,
KZGProof: kzgProof,
}

encoded, err := sideCar.EncodeSSZ([]byte{})
if err != nil {
t.Fatal(err)
}

decoded := &cltypes.BlobSideCar{}
err = decoded.DecodeSSZ(encoded)
if err != nil {
t.Fatal(err)
}

if decoded.BlockRoot != blockRoot {
t.Errorf("unexpected BlockRoot: got %v, want %v", decoded.BlockRoot, blockRoot)
}
if decoded.Index != index {
t.Errorf("unexpected Index: got %d, want %d", decoded.Index, index)
}
if decoded.Slot != slot {
t.Errorf("unexpected Slot: got %d, want %d", decoded.Slot, slot)
}
if decoded.BlockParentRoot != blockParentRoot {
t.Errorf("unexpected BlockParentRoot: got %v, want %v", decoded.BlockParentRoot, blockParentRoot)
}
if decoded.ProposerIndex != proposerIndex {
t.Errorf("unexpected ProposerIndex: got %d, want %d", decoded.ProposerIndex, proposerIndex)
}
if !bytes.Equal(decoded.Blob[:], blob[:]) {
t.Errorf("unexpected Blob: got %v, want %v", decoded.Blob, blob)
}
if decoded.KZGCommitment != kzgCommitment {
t.Errorf("unexpected KZGCommitment: got %v, want %v", decoded.KZGCommitment, kzgCommitment)
}
if decoded.KZGProof != kzgProof {
t.Errorf("unexpected KZGProof: got %v, want %v", decoded.KZGProof, kzgProof)
}
}

func TestSignedBlobSideCar(t *testing.T) {
// Create a BlobSideCar to use as the message for SignedBlobSideCar
blob := cltypes.Blob{1, 2, 3, 4, 5, 6, 7, 8}
blobSideCar := cltypes.BlobSideCar{
BlockRoot: cltypes.Root{1},
Index: 2,
Slot: 3,
BlockParentRoot: cltypes.Root{4},
ProposerIndex: 5,
Blob: blob,
KZGCommitment: cltypes.KZGCommitment{6},
KZGProof: cltypes.KZGProof{7},
}

// Create a SignedBlobSideCar with the BlobSideCar and a signature
signature := [96]byte{8}
signedBlobSideCar := cltypes.SignedBlobSideCar{
Message: blobSideCar,
Signature: signature,
}

// Encode the SignedBlobSideCar
encoded, err := signedBlobSideCar.EncodeSSZ(nil)
assert.NoError(t, err)

// Decode the encoded SignedBlobSideCar
decoded := cltypes.SignedBlobSideCar{}
err = decoded.DecodeSSZ(encoded)
assert.NoError(t, err)

// Assert that the decoded SignedBlobSideCar is equal to the original SignedBlobSideCar
assert.Equal(t, signedBlobSideCar.Message.BlockRoot, decoded.Message.BlockRoot)
assert.Equal(t, signedBlobSideCar.Message.Index, decoded.Message.Index)
assert.Equal(t, signedBlobSideCar.Message.Slot, decoded.Message.Slot)
assert.Equal(t, signedBlobSideCar.Message.BlockParentRoot, decoded.Message.BlockParentRoot)
assert.Equal(t, signedBlobSideCar.Message.ProposerIndex, decoded.Message.ProposerIndex)
assert.True(t, bytes.Equal(signedBlobSideCar.Message.Blob[:], decoded.Message.Blob[:]))
assert.Equal(t, signedBlobSideCar.Message.KZGCommitment, decoded.Message.KZGCommitment)
assert.Equal(t, signedBlobSideCar.Message.KZGProof, decoded.Message.KZGProof)
assert.Equal(t, signedBlobSideCar.Signature, decoded.Signature)
}

func TestBlobIdentifier_EncodeDecodeSSZ(t *testing.T) {
blockRoot := cltypes.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
index := uint64(123456)

blobID := &cltypes.BlobIdentifier{
BlockRoot: blockRoot,
Index: index,
}

// encode to SSZ
encoded, err := blobID.EncodeSSZ(nil)
if err != nil {
t.Fatalf("EncodeSSZ failed: %v", err)
}

// decode from SSZ
decoded := &cltypes.BlobIdentifier{}
if err := decoded.DecodeSSZ(encoded); err != nil {
t.Fatalf("DecodeSSZ failed: %v", err)
}

// compare original and decoded values
if !bytes.Equal(blobID.BlockRoot[:], decoded.BlockRoot[:]) {
t.Errorf("BlockRoot mismatch: expected %v, got %v", blobID.BlockRoot, decoded.BlockRoot)
}
if blobID.Index != decoded.Index {
t.Errorf("Index mismatch: expected %v, got %v", blobID.Index, decoded.Index)
}

// check SSZ encoding size
expectedSize := blobID.EncodingSizeSSZ()
if len(encoded) != expectedSize {
t.Errorf("Encoding size mismatch: expected %d, got %d", expectedSize, len(encoded))
}
}

0 comments on commit f363eb1

Please sign in to comment.