Added blocks API and attestations API (#8279)

This commit is contained in:
Giulio rebuffo 2023-09-24 01:44:26 +02:00 committed by GitHub
parent 4bec348e62
commit a95914df26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 148 additions and 31 deletions

View File

@ -4,12 +4,14 @@ import (
"context"
"database/sql"
"fmt"
"io"
"net/http"
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/beacon_indicies"
"github.com/ledgerwatch/erigon/cmd/sentinel/sentinel/communication/ssz_snappy"
)
type headerResponse struct {
@ -57,8 +59,119 @@ func (a *ApiHandler) rootFromBlockId(ctx context.Context, tx *sql.Tx, blockId *s
return
}
func (a *ApiHandler) getBlock(w http.ResponseWriter, r *http.Request) {
func (a *ApiHandler) getBlock(r *http.Request) (data any, finalized *bool, version *clparams.StateVersion, httpStatus int, err error) {
var (
tx *sql.Tx
blockId *segmentID
root libcommon.Hash
blkHeader *cltypes.SignedBeaconBlockHeader
blockReader io.ReadCloser
isCanonical bool
)
ctx := r.Context()
tx, err = a.indiciesDB.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
if err != nil {
httpStatus = http.StatusInternalServerError
return
}
defer tx.Rollback()
blockId, err = blockIdFromRequest(r)
if err != nil {
fmt.Println("A")
httpStatus = http.StatusBadRequest
return
}
root, httpStatus, err = a.rootFromBlockId(ctx, tx, blockId)
if err != nil {
return
}
blkHeader, isCanonical, err = beacon_indicies.ReadSignedHeaderByBlockRoot(ctx, tx, root)
if err != nil {
return
}
if blkHeader == nil {
httpStatus = http.StatusNotFound
err = fmt.Errorf("block not found %x", root)
return
}
blockReader, err = a.blockSource.BlockReader(ctx, blkHeader.Header.Slot, root)
if err != nil {
return
}
defer blockReader.Close()
blk := cltypes.NewSignedBeaconBlock(a.beaconChainCfg)
version = new(clparams.StateVersion)
*version = a.beaconChainCfg.GetCurrentStateVersion(blkHeader.Header.Slot / a.beaconChainCfg.SlotsPerEpoch)
if err = ssz_snappy.DecodeAndReadNoForkDigest(blockReader, blk, *version); err != nil {
return
}
data = blk
finalized = new(bool)
httpStatus = http.StatusAccepted
*finalized = isCanonical && blkHeader.Header.Slot <= a.forkchoiceStore.FinalizedSlot()
return
}
func (a *ApiHandler) getBlockAttestations(r *http.Request) (data any, finalized *bool, version *clparams.StateVersion, httpStatus int, err error) {
var (
tx *sql.Tx
blockId *segmentID
root libcommon.Hash
blkHeader *cltypes.SignedBeaconBlockHeader
blockReader io.ReadCloser
isCanonical bool
)
ctx := r.Context()
tx, err = a.indiciesDB.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
if err != nil {
httpStatus = http.StatusInternalServerError
return
}
defer tx.Rollback()
blockId, err = blockIdFromRequest(r)
if err != nil {
fmt.Println("A")
httpStatus = http.StatusBadRequest
return
}
root, httpStatus, err = a.rootFromBlockId(ctx, tx, blockId)
if err != nil {
return
}
blkHeader, isCanonical, err = beacon_indicies.ReadSignedHeaderByBlockRoot(ctx, tx, root)
if err != nil {
return
}
if blkHeader == nil {
httpStatus = http.StatusNotFound
err = fmt.Errorf("block not found %x", root)
return
}
blockReader, err = a.blockSource.BlockReader(ctx, blkHeader.Header.Slot, root)
if err != nil {
return
}
defer blockReader.Close()
blk := cltypes.NewSignedBeaconBlock(a.beaconChainCfg)
version = new(clparams.StateVersion)
*version = a.beaconChainCfg.GetCurrentStateVersion(blkHeader.Header.Slot / a.beaconChainCfg.SlotsPerEpoch)
if err = ssz_snappy.DecodeAndReadNoForkDigest(blockReader, blk, *version); err != nil {
return
}
data = blk.Block.Body.Attestations
finalized = new(bool)
httpStatus = http.StatusAccepted
*finalized = isCanonical && blkHeader.Header.Slot <= a.forkchoiceStore.FinalizedSlot()
return
}
func (a *ApiHandler) getBlockRoot(r *http.Request) (data any, finalized *bool, version *clparams.StateVersion, httpStatus int, err error) {

View File

@ -15,14 +15,14 @@ type ApiHandler struct {
o sync.Once
mux chi.Router
blockSource persistence.BlockSource
blockSource persistence.RawBeaconBlockChain
indiciesDB *sql.DB
genesisCfg *clparams.GenesisConfig
beaconChainCfg *clparams.BeaconChainConfig
forkchoiceStore forkchoice.ForkChoiceStorage
}
func NewApiHandler(genesisConfig *clparams.GenesisConfig, beaconChainConfig *clparams.BeaconChainConfig, source persistence.BlockSource, indiciesDB *sql.DB, forkchoiceStore forkchoice.ForkChoiceStorage) *ApiHandler {
func NewApiHandler(genesisConfig *clparams.GenesisConfig, beaconChainConfig *clparams.BeaconChainConfig, source persistence.RawBeaconBlockChain, indiciesDB *sql.DB, forkchoiceStore forkchoice.ForkChoiceStorage) *ApiHandler {
return &ApiHandler{o: sync.Once{}, genesisCfg: genesisConfig, beaconChainCfg: beaconChainConfig, indiciesDB: indiciesDB, blockSource: source, forkchoiceStore: forkchoiceStore}
}
@ -46,8 +46,8 @@ func (a *ApiHandler) init() {
})
r.Route("/blocks", func(r chi.Router) {
r.Post("/", nil)
r.Get("/{block_id}", a.getBlock)
r.Get("/{block_id}/attestations", beaconHandlerWrapper(a.getBlockRoot))
r.Get("/{block_id}", beaconHandlerWrapper(a.getBlock))
r.Get("/{block_id}/attestations", beaconHandlerWrapper(a.getBlockAttestations))
r.Get("/{block_id}/root", beaconHandlerWrapper(a.getBlockRoot))
})
r.Get("/genesis", beaconHandlerWrapper(a.getGenesis))

View File

@ -50,9 +50,9 @@ func NewAttestionFromParameters(
func (a Attestation) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
AggregationBits hexutility.Bytes
Signature libcommon.Bytes96
Data AttestationData
AggregationBits hexutility.Bytes `json:"aggregation_bits"`
Signature libcommon.Bytes96 `json:"signature"`
Data AttestationData `json:"data"`
}{
AggregationBits: a.aggregationBitsBuffer,
Signature: a.Signature(),
@ -62,9 +62,9 @@ func (a Attestation) MarshalJSON() ([]byte, error) {
func (a *Attestation) UnmarshalJSON(buf []byte) error {
var tmp struct {
AggregationBits hexutility.Bytes
Signature libcommon.Bytes96
Data AttestationData
AggregationBits hexutility.Bytes `json:"aggregation_bits"`
Signature libcommon.Bytes96 `json:"signature"`
Data AttestationData `json:"data"`
}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err

View File

@ -40,11 +40,11 @@ func NewAttestionDataFromParameters(
func (a AttestationData) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Slot uint64
Index uint64
BeaconBlockRoot libcommon.Hash
Source Checkpoint
Target Checkpoint
Slot uint64 `json:"slot"`
Index uint64 `json:"index"`
BeaconBlockRoot libcommon.Hash `json:"beacon_block_root"`
Source Checkpoint `json:"source"`
Target Checkpoint `json:"target"`
}{
Slot: a.Slot(),
BeaconBlockRoot: a.BeaconBlockRoot(),
@ -56,11 +56,11 @@ func (a AttestationData) MarshalJSON() ([]byte, error) {
func (a AttestationData) UnmarshalJSON(buf []byte) error {
var tmp struct {
Slot uint64
Index uint64
BeaconBlockRoot libcommon.Hash
Source Checkpoint
Target Checkpoint
Slot uint64 `json:"slot"`
Index uint64 `json:"index"`
BeaconBlockRoot libcommon.Hash `json:"beacon_block_root"`
Source Checkpoint `json:"source"`
Target Checkpoint `json:"target"`
}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err

View File

@ -35,15 +35,15 @@ func NewCheckpoint() Checkpoint {
func (c Checkpoint) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Epoch uint64
Root libcommon.Hash
Epoch uint64 `json:"epoch"`
Root libcommon.Hash `json:"root"`
}{Epoch: c.Epoch(), Root: c.BlockRoot()})
}
func (c Checkpoint) UnmarshalJSON(buf []byte) error {
var tmp struct {
Epoch uint64
Root libcommon.Hash
Epoch uint64 `json:"epoch"`
Root libcommon.Hash `json:"root"`
}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err

View File

@ -315,7 +315,7 @@ func ConsensusClStages(ctx context.Context,
}
currentEpoch++
}
return nil
return tx.Commit()
},
},
CatchUpBlocks: {

View File

@ -36,6 +36,7 @@ func OpenCaplinDatabase(ctx context.Context,
) (persistence.BeaconChainDatabase, *sql.DB, error) {
dataDirIndexer := path.Join(dbPath, "beacon_indicies")
os.Remove(dataDirIndexer)
os.MkdirAll(dbPath, 0700)
db, err := sql.Open("sqlite", dataDirIndexer)
if err != nil {
@ -69,7 +70,7 @@ func OpenCaplinDatabase(ctx context.Context,
func RunCaplinPhase1(ctx context.Context, sentinel sentinel.SentinelClient, engine execution_client.ExecutionEngine,
beaconConfig *clparams.BeaconChainConfig, genesisConfig *clparams.GenesisConfig, state *state.CachingBeaconState,
caplinFreezer freezer.Freezer, db *sql.DB, beaconDB persistence.BeaconChainDatabase, tmpdir string, cfg beacon.RouterConfiguration) error {
caplinFreezer freezer.Freezer, db *sql.DB, rawDB persistence.RawBeaconBlockChain, beaconDB persistence.BeaconChainDatabase, tmpdir string, cfg beacon.RouterConfiguration) error {
ctx, cn := context.WithCancel(ctx)
defer cn()
@ -113,7 +114,7 @@ func RunCaplinPhase1(ctx context.Context, sentinel sentinel.SentinelClient, engi
}
if cfg.Active {
apiHandler := handler.NewApiHandler(genesisConfig, beaconConfig, beaconDB, db, forkChoice)
apiHandler := handler.NewApiHandler(genesisConfig, beaconConfig, rawDB, db, forkChoice)
go beacon.ListenAndServe(apiHandler, &cfg)
log.Info("Beacon API started", "addr", cfg.Address)
}

View File

@ -17,6 +17,7 @@ import (
"context"
"fmt"
"os"
"path"
"github.com/ledgerwatch/erigon/cl/beacon"
"github.com/ledgerwatch/erigon/cl/freezer"
@ -124,11 +125,13 @@ func runCaplinNode(cliCtx *cli.Context) error {
}
}
beaconDB, sqlDB, err := caplin1.OpenCaplinDatabase(ctx, db_config.DatabaseConfiguration{}, cfg.BeaconCfg, persistence.AferoRawBeaconBlockChainFromOsPath(cfg.BeaconCfg, cfg.Dirs.Tmp), cfg.Dirs.Tmp, executionEngine)
caplinDBPath := path.Join(cfg.DataDir, "caplin")
rawdb := persistence.AferoRawBeaconBlockChainFromOsPath(cfg.BeaconCfg, caplinDBPath)
beaconDB, sqlDB, err := caplin1.OpenCaplinDatabase(ctx, db_config.DefaultDatabaseConfiguration, cfg.BeaconCfg, rawdb, caplinDBPath, executionEngine)
if err != nil {
return err
}
return caplin1.RunCaplinPhase1(ctx, sentinel, executionEngine, cfg.BeaconCfg, cfg.GenesisCfg, state, caplinFreezer, sqlDB, beaconDB, cfg.Dirs.Tmp, beacon.RouterConfiguration{
return caplin1.RunCaplinPhase1(ctx, sentinel, executionEngine, cfg.BeaconCfg, cfg.GenesisCfg, state, caplinFreezer, sqlDB, rawdb, beaconDB, cfg.Dirs.Tmp, beacon.RouterConfiguration{
Protocol: cfg.BeaconProtocol,
Address: cfg.BeaconAddr,
ReadTimeTimeout: cfg.BeaconApiReadTimeout,

View File

@ -790,7 +790,7 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
if err != nil {
return nil, err
}
go caplin1.RunCaplinPhase1(ctx, client, engine, beaconCfg, genesisCfg, state, nil, sqlDb, beaconDB, dirs.Tmp, beacon.RouterConfiguration{Active: false})
go caplin1.RunCaplinPhase1(ctx, client, engine, beaconCfg, genesisCfg, state, nil, sqlDb, rawBeaconBlockChainDb, beaconDB, dirs.Tmp, beacon.RouterConfiguration{Active: false})
}
return backend, nil