diff --git a/cl/beacon/handler/blocks.go b/cl/beacon/handler/blocks.go index 5ee67b535..e34ae3821 100644 --- a/cl/beacon/handler/blocks.go +++ b/cl/beacon/handler/blocks.go @@ -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) { diff --git a/cl/beacon/handler/handler.go b/cl/beacon/handler/handler.go index 6757d0773..5b213bf23 100644 --- a/cl/beacon/handler/handler.go +++ b/cl/beacon/handler/handler.go @@ -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)) diff --git a/cl/cltypes/solid/attestation.go b/cl/cltypes/solid/attestation.go index 12ca81b07..dd50eb3cb 100644 --- a/cl/cltypes/solid/attestation.go +++ b/cl/cltypes/solid/attestation.go @@ -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 diff --git a/cl/cltypes/solid/attestation_data.go b/cl/cltypes/solid/attestation_data.go index 82cbebec8..501f26049 100644 --- a/cl/cltypes/solid/attestation_data.go +++ b/cl/cltypes/solid/attestation_data.go @@ -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 diff --git a/cl/cltypes/solid/checkpoint.go b/cl/cltypes/solid/checkpoint.go index 66b1c96ad..598686bdd 100644 --- a/cl/cltypes/solid/checkpoint.go +++ b/cl/cltypes/solid/checkpoint.go @@ -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 diff --git a/cl/phase1/stages/clstages.go b/cl/phase1/stages/clstages.go index d3fd9c7a0..6c2035d2d 100644 --- a/cl/phase1/stages/clstages.go +++ b/cl/phase1/stages/clstages.go @@ -315,7 +315,7 @@ func ConsensusClStages(ctx context.Context, } currentEpoch++ } - return nil + return tx.Commit() }, }, CatchUpBlocks: { diff --git a/cmd/caplin-phase1/caplin1/run.go b/cmd/caplin-phase1/caplin1/run.go index fb20ee94a..c491505fa 100644 --- a/cmd/caplin-phase1/caplin1/run.go +++ b/cmd/caplin-phase1/caplin1/run.go @@ -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) } diff --git a/cmd/caplin-phase1/main.go b/cmd/caplin-phase1/main.go index fc8ee184d..8010f2696 100644 --- a/cmd/caplin-phase1/main.go +++ b/cmd/caplin-phase1/main.go @@ -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, diff --git a/eth/backend.go b/eth/backend.go index 23f44c331..6c859602d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -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