erigon-pulse/cl/persistence/beacon_indicies/indicies.go
2023-12-24 03:54:50 +01:00

281 lines
8.4 KiB
Go

package beacon_indicies
import (
"context"
"fmt"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/persistence/base_encoding"
_ "modernc.org/sqlite"
)
func WriteHighestFinalized(tx kv.RwTx, slot uint64) error {
return tx.Put(kv.HighestFinalized, kv.HighestFinalizedKey, base_encoding.Encode64ToBytes4(slot))
}
func ReadHighestFinalized(tx kv.Tx) (uint64, error) {
val, err := tx.GetOne(kv.HighestFinalized, kv.HighestFinalizedKey)
if err != nil {
return 0, err
}
if len(val) == 0 {
return 0, nil
}
return base_encoding.Decode64FromBytes4(val), nil
}
// WriteBlockRootSlot writes the slot associated with a block root.
func WriteHeaderSlot(tx kv.RwTx, blockRoot libcommon.Hash, slot uint64) error {
return tx.Put(kv.BlockRootToSlot, blockRoot[:], base_encoding.Encode64ToBytes4(slot))
}
func ReadBlockSlotByBlockRoot(tx kv.Tx, blockRoot libcommon.Hash) (*uint64, error) {
slotBytes, err := tx.GetOne(kv.BlockRootToSlot, blockRoot[:])
if err != nil {
return nil, err
}
if len(slotBytes) == 0 {
return nil, nil
}
slot := new(uint64)
*slot = base_encoding.Decode64FromBytes4(slotBytes)
return slot, nil
}
// WriteBlockRootSlot writes the slot associated with a block root.
func WriteStateRoot(tx kv.RwTx, blockRoot libcommon.Hash, stateRoot libcommon.Hash) error {
if err := tx.Put(kv.BlockRootToStateRoot, blockRoot[:], stateRoot[:]); err != nil {
return err
}
return tx.Put(kv.StateRootToBlockRoot, stateRoot[:], blockRoot[:])
}
func ReadStateRootByBlockRoot(ctx context.Context, tx kv.Tx, blockRoot libcommon.Hash) (libcommon.Hash, error) {
var stateRoot libcommon.Hash
sRoot, err := tx.GetOne(kv.BlockRootToStateRoot, blockRoot[:])
if err != nil {
return libcommon.Hash{}, err
}
copy(stateRoot[:], sRoot)
return stateRoot, nil
}
func ReadBlockRootByStateRoot(tx kv.Tx, stateRoot libcommon.Hash) (libcommon.Hash, error) {
var blockRoot libcommon.Hash
bRoot, err := tx.GetOne(kv.StateRootToBlockRoot, stateRoot[:])
if err != nil {
return libcommon.Hash{}, err
}
copy(blockRoot[:], bRoot)
return blockRoot, nil
}
func ReadCanonicalBlockRoot(tx kv.Tx, slot uint64) (libcommon.Hash, error) {
var blockRoot libcommon.Hash
bRoot, err := tx.GetOne(kv.CanonicalBlockRoots, base_encoding.Encode64ToBytes4(slot))
if err != nil {
return libcommon.Hash{}, err
}
copy(blockRoot[:], bRoot)
return blockRoot, nil
}
func WriteLastBeaconSnapshot(tx kv.RwTx, slot uint64) error {
return tx.Put(kv.LastBeaconSnapshot, []byte(kv.LastBeaconSnapshotKey), base_encoding.Encode64ToBytes4(slot))
}
func ReadLastBeaconSnapshot(tx kv.Tx) (uint64, error) {
val, err := tx.GetOne(kv.LastBeaconSnapshot, []byte(kv.LastBeaconSnapshotKey))
if err != nil {
return 0, err
}
if len(val) == 0 {
return 0, nil
}
return base_encoding.Decode64FromBytes4(val), nil
}
func MarkRootCanonical(ctx context.Context, tx kv.RwTx, slot uint64, blockRoot libcommon.Hash) error {
return tx.Put(kv.CanonicalBlockRoots, base_encoding.Encode64ToBytes4(slot), blockRoot[:])
}
func WriteExecutionBlockNumber(tx kv.RwTx, blockRoot libcommon.Hash, blockNumber uint64) error {
return tx.Put(kv.BlockRootToBlockNumber, blockRoot[:], base_encoding.Encode64ToBytes4(blockNumber))
}
func WriteExecutionBlockHash(tx kv.RwTx, blockRoot, blockHash libcommon.Hash) error {
return tx.Put(kv.BlockRootToBlockHash, blockRoot[:], blockHash[:])
}
func ReadExecutionBlockNumber(tx kv.Tx, blockRoot libcommon.Hash) (*uint64, error) {
val, err := tx.GetOne(kv.BlockRootToBlockNumber, blockRoot[:])
if err != nil {
return nil, err
}
if len(val) == 0 {
return nil, nil
}
ret := new(uint64)
*ret = base_encoding.Decode64FromBytes4(val)
return ret, nil
}
func ReadExecutionBlockHash(tx kv.Tx, blockRoot libcommon.Hash) (libcommon.Hash, error) {
val, err := tx.GetOne(kv.BlockRootToBlockHash, blockRoot[:])
if err != nil {
return libcommon.Hash{}, err
}
if len(val) == 0 {
return libcommon.Hash{}, nil
}
return libcommon.BytesToHash(val), nil
}
func WriteBeaconBlockHeader(ctx context.Context, tx kv.RwTx, signedHeader *cltypes.SignedBeaconBlockHeader) error {
headersBytes, err := signedHeader.EncodeSSZ(nil)
if err != nil {
return err
}
blockRoot, err := signedHeader.Header.HashSSZ()
if err != nil {
return err
}
return tx.Put(kv.BeaconBlockHeaders, blockRoot[:], headersBytes)
}
func WriteBeaconBlockHeaderAndIndicies(ctx context.Context, tx kv.RwTx, signedHeader *cltypes.SignedBeaconBlockHeader, forceCanonical bool) error {
blockRoot, err := signedHeader.Header.HashSSZ()
if err != nil {
return err
}
if err := WriteBeaconBlockHeader(ctx, tx, signedHeader); err != nil {
return err
}
if err := WriteHeaderSlot(tx, blockRoot, signedHeader.Header.Slot); err != nil {
return err
}
if err := WriteStateRoot(tx, blockRoot, signedHeader.Header.Root); err != nil {
return err
}
if err := WriteParentBlockRoot(ctx, tx, blockRoot, signedHeader.Header.ParentRoot); err != nil {
return err
}
if forceCanonical {
if err := MarkRootCanonical(ctx, tx, signedHeader.Header.Slot, blockRoot); err != nil {
return err
}
}
return nil
}
func ReadParentBlockRoot(ctx context.Context, tx kv.Tx, blockRoot libcommon.Hash) (libcommon.Hash, error) {
var parentRoot libcommon.Hash
pRoot, err := tx.GetOne(kv.BlockRootToParentRoot, blockRoot[:])
if err != nil {
return libcommon.Hash{}, err
}
copy(parentRoot[:], pRoot)
return parentRoot, nil
}
func WriteParentBlockRoot(ctx context.Context, tx kv.RwTx, blockRoot, parentRoot libcommon.Hash) error {
return tx.Put(kv.BlockRootToParentRoot, blockRoot[:], parentRoot[:])
}
func TruncateCanonicalChain(ctx context.Context, tx kv.RwTx, slot uint64) error {
return tx.ForEach(kv.CanonicalBlockRoots, base_encoding.Encode64ToBytes4(slot), func(k, _ []byte) error {
return tx.Delete(kv.CanonicalBlockRoots, k)
})
}
func PruneSignedHeaders(tx kv.RwTx, from uint64) error {
cursor, err := tx.RwCursor(kv.BeaconBlockHeaders)
if err != nil {
return err
}
for k, _, err := cursor.Seek(base_encoding.Encode64ToBytes4(from)); err == nil && k != nil; k, _, err = cursor.Prev() {
if err != nil {
return err
}
if err := cursor.DeleteCurrent(); err != nil {
return err
}
}
return nil
}
func RangeBlockRoots(ctx context.Context, tx kv.Tx, fromSlot, toSlot uint64, fn func(slot uint64, beaconBlockRoot libcommon.Hash) bool) error {
cursor, err := tx.Cursor(kv.CanonicalBlockRoots)
if err != nil {
return err
}
for k, v, err := cursor.Seek(base_encoding.Encode64ToBytes4(fromSlot)); err == nil && k != nil && base_encoding.Decode64FromBytes4(k) <= toSlot; k, v, err = cursor.Next() {
if !fn(base_encoding.Decode64FromBytes4(k), libcommon.BytesToHash(v)) {
break
}
}
return err
}
func PruneBlockRoots(ctx context.Context, tx kv.RwTx, fromSlot, toSlot uint64) error {
cursor, err := tx.RwCursor(kv.CanonicalBlockRoots)
if err != nil {
return err
}
for k, _, err := cursor.Seek(base_encoding.Encode64ToBytes4(fromSlot)); err == nil && k != nil && base_encoding.Decode64FromBytes4(k) <= toSlot; k, _, err = cursor.Next() {
if err := cursor.DeleteCurrent(); err != nil {
return err
}
}
return err
}
func ReadBeaconBlockRootsInSlotRange(ctx context.Context, tx kv.Tx, fromSlot, count uint64) ([]libcommon.Hash, []uint64, error) {
blockRoots := make([]libcommon.Hash, 0, count)
slots := make([]uint64, 0, count)
cursor, err := tx.Cursor(kv.CanonicalBlockRoots)
if err != nil {
return nil, nil, err
}
currentCount := uint64(0)
for k, v, err := cursor.Seek(base_encoding.Encode64ToBytes4(fromSlot)); err == nil && k != nil && currentCount != count; k, v, err = cursor.Next() {
currentCount++
blockRoots = append(blockRoots, libcommon.BytesToHash(v))
slots = append(slots, base_encoding.Decode64FromBytes4(k))
}
return blockRoots, slots, err
}
func ReadSignedHeaderByBlockRoot(ctx context.Context, tx kv.Tx, blockRoot libcommon.Hash) (*cltypes.SignedBeaconBlockHeader, bool, error) {
h := &cltypes.SignedBeaconBlockHeader{Header: &cltypes.BeaconBlockHeader{}}
headerBytes, err := tx.GetOne(kv.BeaconBlockHeaders, blockRoot[:])
if err != nil {
return nil, false, err
}
if len(headerBytes) == 0 {
return nil, false, nil
}
if err := h.DecodeSSZ(headerBytes, 0); err != nil {
return nil, false, fmt.Errorf("failed to decode BeaconHeader: %v", err)
}
canonical, err := ReadCanonicalBlockRoot(tx, h.Header.Slot)
if err != nil {
return nil, false, err
}
return h, canonical == blockRoot, nil
}