Skip to content

Commit

Permalink
Merge branch 'main' into remove-blobsidecarst
Browse files Browse the repository at this point in the history
  • Loading branch information
abi87 committed Dec 18, 2024
2 parents 07e1692 + c08698e commit 15a2f20
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 61 deletions.
40 changes: 37 additions & 3 deletions consensus-types/types/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/berachain/beacon-kit/primitives/crypto"
"github.com/berachain/beacon-kit/primitives/eip4844"
"github.com/berachain/beacon-kit/primitives/math"
"github.com/berachain/beacon-kit/primitives/math/log"
"github.com/berachain/beacon-kit/primitives/version"
fastssz "github.com/ferranbt/fastssz"
"github.com/karalabe/ssz"
Expand Down Expand Up @@ -68,9 +69,8 @@ func (b *BeaconBlockBody) Empty(forkVersion uint32) *BeaconBlockBody {
}
}

// BlockBodyKZGOffset returns the offset of the KZG commitments in the block
// body.
// TODO: I still feel like we need to clean this up somehow.
// BlockBodyKZGOffset returns the offset of the KZG commitments in the
// serialized block body.
func BlockBodyKZGOffset(
slot math.Slot,
cs chain.ChainSpec,
Expand All @@ -83,6 +83,40 @@ func BlockBodyKZGOffset(
}
}

// BlockBodyKZGPosition returns the index of the KZG Commitments in the
// block body.
func BlockBodyKZGPosition(
forkVersion uint32,
) (uint64, error) {
switch forkVersion {
case version.Deneb:
return KZGPositionDeneb, nil
default:
return 0, ErrForkVersionNotSupported
}
}

// KZGCommitmentInclusionProofDepth as per the Ethereum 2.0 Specification:
// https://ethereum.github.io/consensus-specs/specs/deneb/p2p-interface/#preset
func KZGCommitmentInclusionProofDepth(
slot math.Slot,
cs chain.ChainSpec,
) (uint8, error) {
const maxUint8 = 255
switch cs.ActiveForkVersionForSlot(slot) {
case version.Deneb:
sum := uint64(log.ILog2Floor(uint64(KZGMerkleIndexDeneb))) +
uint64(log.ILog2Ceil(cs.MaxBlobCommitmentsPerBlock())) + 1
if sum > maxUint8 {
return 0, ErrInclusionProofDepthExceeded
}
//#nosec:G701 // we handle the overflow above, so this is safe
return uint8(sum), nil
default:
return 0, ErrForkVersionNotSupported
}
}

// BeaconBlockBody represents the body of a beacon block in the Deneb
// chain.
type BeaconBlockBody struct {
Expand Down
4 changes: 4 additions & 0 deletions consensus-types/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ var (
// version is not supported.
ErrForkVersionNotSupported = errors.New("fork version not supported")

// ErrInclusionProofDepthExceeded is an error for when the
// KZG_COMMITMENT_INCLUSION_PROOF_DEPTH calculation overflows.
ErrInclusionProofDepthExceeded = errors.New("inclusion proof depth exceeded")

// ErrNilPayloadHeader is an error for when the payload header is nil.
ErrNilPayloadHeader = errors.New("nil payload header")
)
26 changes: 14 additions & 12 deletions da/blob/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ type SidecarFactory[
] struct {
// chainSpec defines the specifications of the blockchain.
chainSpec ChainSpec
// kzgPosition is the position of the KZG commitment in the block.
//
// TODO: This needs to be made configurable / modular.
kzgPosition uint64
// metrics is used to collect and report factory metrics.
metrics *factoryMetrics
}
Expand All @@ -51,15 +47,11 @@ func NewSidecarFactory[
BeaconBlockT BeaconBlock,
](
chainSpec ChainSpec,
// todo: calculate from config.
kzgPosition uint64,
telemetrySink TelemetrySink,
) *SidecarFactory[BeaconBlockT] {
return &SidecarFactory[BeaconBlockT]{
chainSpec: chainSpec,
// TODO: This should be configurable / modular.
kzgPosition: kzgPosition,
metrics: newFactoryMetrics(telemetrySink),
metrics: newFactoryMetrics(telemetrySink),
}
}

Expand Down Expand Up @@ -106,11 +98,19 @@ func (f *SidecarFactory[BeaconBlockT]) BuildSidecars(
}
sigHeader := ctypes.NewSignedBeaconBlockHeader(header, signature)

// Calculate offsets
kzgPosition, err := ctypes.BlockBodyKZGPosition(
f.chainSpec.ActiveForkVersionForSlot(header.GetSlot()),
)
if err != nil {
return nil, err
}

for i := range numBlobs {
g.Go(func() error {
//nolint:govet // shadow
inclusionProof, err := f.BuildKZGInclusionProof(
body, math.U64(i),
body, math.U64(i), kzgPosition,
)
if err != nil {
return err
Expand All @@ -134,6 +134,7 @@ func (f *SidecarFactory[BeaconBlockT]) BuildSidecars(
func (f *SidecarFactory[_]) BuildKZGInclusionProof(
body *ctypes.BeaconBlockBody,
index math.U64,
kzgPosition uint64,
) ([]common.Root, error) {
startTime := time.Now()
defer f.metrics.measureBuildKZGInclusionProofDuration(startTime)
Expand All @@ -146,7 +147,7 @@ func (f *SidecarFactory[_]) BuildKZGInclusionProof(
}

// Build the merkle proof for the body root.
bodyProof, err := f.BuildBlockBodyProof(body)
bodyProof, err := f.BuildBlockBodyProof(body, kzgPosition)
if err != nil {
return nil, err
}
Expand All @@ -159,6 +160,7 @@ func (f *SidecarFactory[_]) BuildKZGInclusionProof(
// BuildBlockBodyProof builds a block body proof.
func (f *SidecarFactory[_]) BuildBlockBodyProof(
body *ctypes.BeaconBlockBody,
kzgPosition uint64,
) ([]common.Root, error) {
startTime := time.Now()
defer f.metrics.measureBuildBlockBodyProofDuration(startTime)
Expand All @@ -170,7 +172,7 @@ func (f *SidecarFactory[_]) BuildBlockBodyProof(
return nil, err
}

return tree.MerkleProof(f.kzgPosition)
return tree.MerkleProof(kzgPosition)
}

// BuildCommitmentProof builds a commitment proof.
Expand Down
25 changes: 6 additions & 19 deletions da/blob/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ type Processor[
chainSpec chain.ChainSpec
// verifier is responsible for verifying the blobs.
verifier *verifier
// blockBodyOffsetFn is a function that calculates the block body offset
// based on the slot and chain specifications.
blockBodyOffsetFn func(math.Slot, chain.ChainSpec) (uint64, error)
// metrics is used to collect and report processor metrics.
metrics *processorMetrics
}
Expand All @@ -59,22 +56,20 @@ func NewProcessor[
logger log.Logger,
chainSpec chain.ChainSpec,
proofVerifier kzg.BlobProofVerifier,
blockBodyOffsetFn func(math.Slot, chain.ChainSpec) (uint64, error),
telemetrySink TelemetrySink,
) *Processor[
AvailabilityStoreT,
ConsensusSidecarsT,
] {
verifier := newVerifier(proofVerifier, telemetrySink)
verifier := newVerifier(proofVerifier, telemetrySink, chainSpec)
return &Processor[
AvailabilityStoreT,
ConsensusSidecarsT,
]{
logger: logger,
chainSpec: chainSpec,
verifier: verifier,
blockBodyOffsetFn: blockBodyOffsetFn,
metrics: newProcessorMetrics(telemetrySink),
logger: logger,
chainSpec: chainSpec,
verifier: verifier,
metrics: newProcessorMetrics(telemetrySink),
}
}

Expand All @@ -101,23 +96,15 @@ func (sp *Processor[
return nil
}

kzgOffset, err := sp.blockBodyOffsetFn(
blkHeader.GetSlot(), sp.chainSpec,
)
if err != nil {
return err
}

// Verify the blobs and ensure they match the local state.
return sp.verifier.verifySidecars(
sidecars,
kzgOffset,
blkHeader,
verifierFn,
)
}

// slot := processes the blobs and ensures they match the local state.
// ProcessSidecars processes the blobs and ensures they match the local state.
func (sp *Processor[
AvailabilityStoreT, _,
]) ProcessSidecars(
Expand Down
6 changes: 5 additions & 1 deletion da/blob/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,17 @@ type Sidecars[SidecarT any] interface {
Get(index int) SidecarT
GetSidecars() []SidecarT
ValidateBlockRoots() error
VerifyInclusionProofs(kzgOffset uint64) error
VerifyInclusionProofs(
kzgOffset uint64,
inclusionProofDepth uint8,
) error
}

// ChainSpec represents a chain spec.
type ChainSpec interface {
MaxBlobCommitmentsPerBlock() uint64
DomainTypeProposer() common.DomainType
ActiveForkVersionForSlot(slot math.Slot) uint32
}

// TelemetrySink is an interface for sending metrics to a telemetry backend.
Expand Down
52 changes: 36 additions & 16 deletions da/blob/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"fmt"
"time"

"github.com/berachain/beacon-kit/chain-spec/chain"
ctypes "github.com/berachain/beacon-kit/consensus-types/types"
"github.com/berachain/beacon-kit/da/kzg"
datypes "github.com/berachain/beacon-kit/da/types"
Expand All @@ -40,24 +41,27 @@ type verifier struct {
proofVerifier kzg.BlobProofVerifier
// metrics collects and reports metrics related to the verification process.
metrics *verifierMetrics
// chainSpec contains the chain specification
chainSpec chain.ChainSpec
}

// newVerifier creates a new Verifier with the given proof verifier.
func newVerifier(
proofVerifier kzg.BlobProofVerifier,
telemetrySink TelemetrySink,
chainSpec chain.ChainSpec,
) *verifier {
return &verifier{
proofVerifier: proofVerifier,
metrics: newVerifierMetrics(telemetrySink),
chainSpec: chainSpec,
}
}

// verifySidecars verifies the blobs for both inclusion as well
// as the KZG proofs.
func (bv *verifier) verifySidecars(
sidecars datypes.BlobSidecars,
kzgOffset uint64,
blkHeader *ctypes.BeaconBlockHeader,
verifierFn func(
blkHeader *ctypes.BeaconBlockHeader,
Expand All @@ -71,19 +75,22 @@ func (bv *verifier) verifySidecars(

g, _ := errgroup.WithContext(context.Background())

// check that sidecars block headers match with header of the
// corresponding block
// Verifying that sidecars block headers match with header of the
// corresponding block concurrently.
for i, s := range sidecars.GetSidecars() {
if !s.GetSignedBeaconBlockHeader().GetHeader().Equals(blkHeader) {
return fmt.Errorf("unequal block header: idx: %d", i)
}
g.Go(func() error {
var sigHeader = s.GetSignedBeaconBlockHeader()
err := verifierFn(

// Check BlobSidecar.Header equality with BeaconBlockHeader
if !sigHeader.GetHeader().Equals(blkHeader) {
return fmt.Errorf("unequal block header: idx: %d", i)
}

// Verify BeaconBlockHeader with signature
if err := verifierFn(
blkHeader,
sigHeader.GetSignature(),
)
if err != nil {
); err != nil {
return err
}
return nil
Expand All @@ -92,11 +99,7 @@ func (bv *verifier) verifySidecars(

// Verify the inclusion proofs on the blobs concurrently.
g.Go(func() error {
// TODO: KZGOffset needs to be configurable and not
// passed in.
return bv.verifyInclusionProofs(
sidecars, kzgOffset,
)
return bv.verifyInclusionProofs(sidecars, blkHeader.GetSlot())
})

// Verify the KZG proofs on the blobs concurrently.
Expand All @@ -110,13 +113,30 @@ func (bv *verifier) verifySidecars(

func (bv *verifier) verifyInclusionProofs(
scs datypes.BlobSidecars,
kzgOffset uint64,
slot math.Slot,
) error {
startTime := time.Now()
defer bv.metrics.measureVerifyInclusionProofsDuration(
startTime, math.U64(scs.Len()),
)
return scs.VerifyInclusionProofs(kzgOffset)

// Grab the KZG offset for the fork version.
kzgOffset, err := ctypes.BlockBodyKZGOffset(
slot, bv.chainSpec,
)
if err != nil {
return err
}

// Grab the inclusion proof depth for the fork version.
inclusionProofDepth, err := ctypes.KZGCommitmentInclusionProofDepth(
slot, bv.chainSpec,
)
if err != nil {
return err
}

return scs.VerifyInclusionProofs(kzgOffset, inclusionProofDepth)
}

// verifyKZGProofs verifies the sidecars.
Expand Down
6 changes: 2 additions & 4 deletions da/types/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,13 @@ func BuildBlobSidecar(
// blob in the beacon body.
func (b *BlobSidecar) HasValidInclusionProof(
kzgOffset uint64,
inclusionProofDepth uint8,
) bool {
header := b.GetSignedBeaconBlockHeader().GetHeader()
return header != nil && merkle.IsValidMerkleBranch(
b.KzgCommitment.HashTreeRoot(),
b.InclusionProof,
//#nosec:G701 // safe.
uint8(
len(b.InclusionProof),
), // TODO: use KZG_INCLUSION_PROOF_DEPTH calculation.
inclusionProofDepth,
kzgOffset+b.Index,
header.BodyRoot,
)
Expand Down
4 changes: 3 additions & 1 deletion da/types/sidecar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func TestSidecarMarshalling(t *testing.T) {
}

func TestHasValidInclusionProof(t *testing.T) {
// Equates to KZG_COMMITMENT_INCLUSION_PROOF_DEPTH
const inclusionProofDepth = 17
tests := []struct {
name string
sidecar func(t *testing.T) *types.BlobSidecar
Expand Down Expand Up @@ -137,7 +139,7 @@ func TestHasValidInclusionProof(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sidecar := tt.sidecar(t)
result := sidecar.HasValidInclusionProof(tt.kzgOffset)
result := sidecar.HasValidInclusionProof(tt.kzgOffset, inclusionProofDepth)
require.Equal(t, tt.expectedResult, result,
"Result should match expected value")
})
Expand Down
Loading

0 comments on commit 15a2f20

Please sign in to comment.