mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-05 10:32:19 +00:00
47a6ac16da
adds a two indexes to the validators cache creates beaconhttp package with many utilities for beacon http endpoint (future support for ssz is baked in) started on some validator endpoints
159 lines
4.8 KiB
Go
159 lines
4.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
|
"github.com/ledgerwatch/erigon/cl/beacon/beaconhttp"
|
|
"github.com/ledgerwatch/erigon/cl/cltypes"
|
|
"github.com/ledgerwatch/erigon/cl/persistence/beacon_indicies"
|
|
)
|
|
|
|
type headerResponse struct {
|
|
Root libcommon.Hash `json:"root"`
|
|
Canonical bool `json:"canonical"`
|
|
Header *cltypes.SignedBeaconBlockHeader `json:"header"`
|
|
}
|
|
|
|
type getHeadersRequest struct {
|
|
Slot *uint64 `json:"slot,omitempty"`
|
|
ParentRoot *libcommon.Hash `json:"root,omitempty"`
|
|
}
|
|
|
|
func (a *ApiHandler) rootFromBlockId(ctx context.Context, tx kv.Tx, blockId *segmentID) (root libcommon.Hash, err error) {
|
|
switch {
|
|
case blockId.head():
|
|
root, _, err = a.forkchoiceStore.GetHead()
|
|
if err != nil {
|
|
return libcommon.Hash{}, err
|
|
}
|
|
case blockId.finalized():
|
|
root = a.forkchoiceStore.FinalizedCheckpoint().BlockRoot()
|
|
case blockId.justified():
|
|
root = a.forkchoiceStore.JustifiedCheckpoint().BlockRoot()
|
|
case blockId.genesis():
|
|
root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, 0)
|
|
if err != nil {
|
|
return libcommon.Hash{}, err
|
|
}
|
|
if root == (libcommon.Hash{}) {
|
|
return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusNotFound, "genesis block not found")
|
|
}
|
|
case blockId.getSlot() != nil:
|
|
root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, *blockId.getSlot())
|
|
if err != nil {
|
|
return libcommon.Hash{}, err
|
|
}
|
|
if root == (libcommon.Hash{}) {
|
|
return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("block not found %d", *blockId.getSlot()))
|
|
}
|
|
case blockId.getRoot() != nil:
|
|
// first check if it exists
|
|
root = *blockId.getRoot()
|
|
default:
|
|
return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusInternalServerError, "cannot parse block id")
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a *ApiHandler) getBlock(r *http.Request) (*beaconResponse, error) {
|
|
ctx := r.Context()
|
|
tx, err := a.indiciesDB.BeginRo(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
blockId, err := blockIdFromRequest(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
root, err := a.rootFromBlockId(ctx, tx, blockId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
blk, err := a.blockReader.ReadBlockByRoot(ctx, tx, root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if blk == nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("block not found %x", root))
|
|
}
|
|
// Check if the block is canonical
|
|
var canonicalRoot libcommon.Hash
|
|
canonicalRoot, err = beacon_indicies.ReadCanonicalBlockRoot(tx, blk.Block.Slot)
|
|
if err != nil {
|
|
return nil, beaconhttp.WrapEndpointError(err)
|
|
}
|
|
return newBeaconResponse(blk).
|
|
withFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()).
|
|
withVersion(blk.Version()), nil
|
|
}
|
|
|
|
func (a *ApiHandler) getBlockAttestations(r *http.Request) (*beaconResponse, error) {
|
|
ctx := r.Context()
|
|
tx, err := a.indiciesDB.BeginRo(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback()
|
|
blockId, err := blockIdFromRequest(r)
|
|
if err != nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error())
|
|
}
|
|
root, err := a.rootFromBlockId(ctx, tx, blockId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blk, err := a.blockReader.ReadBlockByRoot(ctx, tx, root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if blk == nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("block not found %x", root))
|
|
}
|
|
// Check if the block is canonical
|
|
canonicalRoot, err := beacon_indicies.ReadCanonicalBlockRoot(tx, blk.Block.Slot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newBeaconResponse(blk.Block.Body.Attestations).withFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()).
|
|
withVersion(blk.Version()), nil
|
|
}
|
|
|
|
func (a *ApiHandler) getBlockRoot(r *http.Request) (*beaconResponse, error) {
|
|
ctx := r.Context()
|
|
tx, err := a.indiciesDB.BeginRo(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback()
|
|
blockId, err := blockIdFromRequest(r)
|
|
if err != nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error())
|
|
}
|
|
root, err := a.rootFromBlockId(ctx, tx, blockId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// check if the root exist
|
|
slot, err := beacon_indicies.ReadBlockSlotByBlockRoot(tx, root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if slot == nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("block not found %x", root))
|
|
}
|
|
// Check if the block is canonical
|
|
var canonicalRoot libcommon.Hash
|
|
canonicalRoot, err = beacon_indicies.ReadCanonicalBlockRoot(tx, *slot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newBeaconResponse(struct{ Root libcommon.Hash }{Root: root}).withFinalized(canonicalRoot == root && *slot <= a.forkchoiceStore.FinalizedSlot()), nil
|
|
}
|