erigon-pulse/turbo/snapshotsync/freezeblocks/beacon_block_reader.go

132 lines
3.3 KiB
Go
Raw Normal View History

package freezeblocks
import (
"bytes"
"fmt"
"sync"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format"
"github.com/pierrec/lz4"
)
var buffersPool = sync.Pool{
New: func() interface{} { return &bytes.Buffer{} },
}
var lz4ReaderPool = sync.Pool{
New: func() interface{} {
return lz4.NewReader(nil)
},
}
type BeaconSnapshotReader interface {
// ReadBlock reads the block at the given slot.
// If the block is not present, it returns nil.
ReadBlock(slot uint64) (*cltypes.SignedBeaconBlock, error)
ReadHeader(slot uint64) (*cltypes.SignedBeaconBlockHeader, uint64, libcommon.Hash, error)
FrozenSlots() uint64
}
type beaconSnapshotReader struct {
sn *CaplinSnapshots
eth1Getter snapshot_format.ExecutionBlockReaderByNumber
cfg *clparams.BeaconChainConfig
}
func NewBeaconSnapshotReader(snapshots *CaplinSnapshots, eth1Getter snapshot_format.ExecutionBlockReaderByNumber, cfg *clparams.BeaconChainConfig) BeaconSnapshotReader {
return &beaconSnapshotReader{sn: snapshots, eth1Getter: eth1Getter, cfg: cfg}
}
func (r *beaconSnapshotReader) FrozenSlots() uint64 {
return r.sn.BlocksAvailable()
}
func (r *beaconSnapshotReader) ReadBlock(slot uint64) (*cltypes.SignedBeaconBlock, error) {
view := r.sn.View()
defer view.Close()
var buf []byte
seg, ok := view.BeaconBlocksSegment(slot)
if !ok {
return nil, nil
}
if seg.idxSlot == nil {
return nil, nil
}
if slot < seg.idxSlot.BaseDataID() {
return nil, fmt.Errorf("slot %d is before the base data id %d", slot, seg.idxSlot.BaseDataID())
}
blockOffset := seg.idxSlot.OrdinalLookup(slot - seg.idxSlot.BaseDataID())
gg := seg.seg.MakeGetter()
gg.Reset(blockOffset)
if !gg.HasNext() {
return nil, nil
}
buf = buf[:0]
buf, _ = gg.Next(buf)
if len(buf) == 0 {
return nil, nil
}
// Decompress this thing
buffer := buffersPool.Get().(*bytes.Buffer)
defer buffersPool.Put(buffer)
buffer.Reset()
buffer.Write(buf)
lzReader := lz4ReaderPool.Get().(*lz4.Reader)
defer lz4ReaderPool.Put(lzReader)
lzReader.Reset(buffer)
// Use pooled buffers and readers to avoid allocations.
return snapshot_format.ReadBlockFromSnapshot(lzReader, r.eth1Getter, r.cfg)
}
func (r *beaconSnapshotReader) ReadHeader(slot uint64) (*cltypes.SignedBeaconBlockHeader, uint64, libcommon.Hash, error) {
view := r.sn.View()
defer view.Close()
var buf []byte
seg, ok := view.BeaconBlocksSegment(slot)
if !ok {
return nil, 0, libcommon.Hash{}, nil
}
if seg.idxSlot == nil {
return nil, 0, libcommon.Hash{}, nil
}
blockOffset := seg.idxSlot.OrdinalLookup(slot - seg.idxSlot.BaseDataID())
gg := seg.seg.MakeGetter()
gg.Reset(blockOffset)
if !gg.HasNext() {
return nil, 0, libcommon.Hash{}, nil
}
buf, _ = gg.Next(buf)
if len(buf) == 0 {
return nil, 0, libcommon.Hash{}, nil
}
// Decompress this thing
buffer := buffersPool.Get().(*bytes.Buffer)
defer buffersPool.Put(buffer)
buffer.Reset()
buffer.Write(buf)
lzReader := lz4ReaderPool.Get().(*lz4.Reader)
defer lz4ReaderPool.Put(lzReader)
lzReader.Reset(buffer)
// Use pooled buffers and readers to avoid allocations.
return snapshot_format.ReadBlockHeaderFromSnapshotWithExecutionData(lzReader, r.cfg)
}