mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-14 18:08:15 -05:00
* poc changes for safe validator shutdown * simplifying health routine and adding safe shutdown after max restarts reached * fixing health tests * fixing tests * changelog * gofmt * fixing runner * improve how runner times out * improvements to ux on logs * linting * adding in max healthcheck flag * changelog * Update james-prysm_safe-validator-shutdown.md Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/runner.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/service.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/runner.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/runner.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * addressing some feedback from radek * addressing some more feedback * fixing name based on feedback * fixing mistake on max health checks * conflict accidently checked in * go 1.23 no longer needs you to stop for the ticker * Update flags.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * wip no unit test for recursive healthy host find * rework healthcheck * gaz * fixing bugs and improving logs with new monitor * removing health tracker, fixing runner tests, and adding placeholder for monitor tests * fixing event stream check * linting * adding in health monitor tests * gaz * improving test * removing some log.fatals * forgot to remove comment * missed fatal removal * doppleganger should exit the node safely now * Update validator/client/health_monitor.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * radek review * Update validator/client/validator.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/validator.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/health_monitor.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/health_monitor.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/health_monitor.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/client/validator.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * radek feedback * read up on more suggestions and making fixes to channel * suggested updates after more reading * reverting some of this because it froze the validator after healthcheck failed * fully reverting * some improvements I found during testing * Update cmd/validator/flags/flags.go Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com> * preston's feedback * clarifications on changelog * converted to using an event feed instead of my own channel publishing implementation, adding relevant logs * preston log suggestion --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
package beacon_api
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
|
|
"github.com/OffchainLabs/prysm/v6/api/server/structs"
|
|
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
|
|
"github.com/OffchainLabs/prysm/v6/validator/client/iface"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/golang/protobuf/ptypes/empty"
|
|
"github.com/pkg/errors"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
)
|
|
|
|
var (
|
|
_ = iface.NodeClient(&beaconApiNodeClient{})
|
|
)
|
|
|
|
type beaconApiNodeClient struct {
|
|
fallbackClient iface.NodeClient
|
|
jsonRestHandler RestHandler
|
|
genesisProvider GenesisProvider
|
|
}
|
|
|
|
func (c *beaconApiNodeClient) SyncStatus(ctx context.Context, _ *empty.Empty) (*ethpb.SyncStatus, error) {
|
|
syncingResponse := structs.SyncStatusResponse{}
|
|
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/syncing", &syncingResponse); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if syncingResponse.Data == nil {
|
|
return nil, errors.New("syncing data is nil")
|
|
}
|
|
|
|
return ðpb.SyncStatus{
|
|
Syncing: syncingResponse.Data.IsSyncing,
|
|
}, nil
|
|
}
|
|
|
|
func (c *beaconApiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesis, error) {
|
|
genesisJson, err := c.genesisProvider.Genesis(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get genesis")
|
|
}
|
|
|
|
genesisValidatorRoot, err := hexutil.Decode(genesisJson.GenesisValidatorsRoot)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to decode genesis validator root `%s`", genesisJson.GenesisValidatorsRoot)
|
|
}
|
|
|
|
genesisTime, err := strconv.ParseInt(genesisJson.GenesisTime, 10, 64)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to parse genesis time `%s`", genesisJson.GenesisTime)
|
|
}
|
|
|
|
depositContractJson := structs.GetDepositContractResponse{}
|
|
if err = c.jsonRestHandler.Get(ctx, "/eth/v1/config/deposit_contract", &depositContractJson); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if depositContractJson.Data == nil {
|
|
return nil, errors.New("deposit contract data is nil")
|
|
}
|
|
|
|
depositContactAddress, err := hexutil.Decode(depositContractJson.Data.Address)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to decode deposit contract address `%s`", depositContractJson.Data.Address)
|
|
}
|
|
|
|
return ðpb.Genesis{
|
|
GenesisTime: ×tamppb.Timestamp{
|
|
Seconds: genesisTime,
|
|
},
|
|
DepositContractAddress: depositContactAddress,
|
|
GenesisValidatorsRoot: genesisValidatorRoot,
|
|
}, nil
|
|
}
|
|
|
|
func (c *beaconApiNodeClient) Version(ctx context.Context, _ *empty.Empty) (*ethpb.Version, error) {
|
|
var versionResponse structs.GetVersionResponse
|
|
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/version", &versionResponse); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if versionResponse.Data == nil || versionResponse.Data.Version == "" {
|
|
return nil, errors.New("empty version response")
|
|
}
|
|
|
|
return ðpb.Version{
|
|
Version: versionResponse.Data.Version,
|
|
}, nil
|
|
}
|
|
|
|
func (c *beaconApiNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error) {
|
|
if c.fallbackClient != nil {
|
|
return c.fallbackClient.Peers(ctx, in)
|
|
}
|
|
|
|
// TODO: Implement me
|
|
return nil, errors.New("beaconApiNodeClient.Peers is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
|
}
|
|
|
|
func (c *beaconApiNodeClient) IsHealthy(ctx context.Context) bool {
|
|
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/health", nil); err != nil {
|
|
log.WithError(err).Error("failed to get health of node")
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func NewNodeClientWithFallback(jsonRestHandler RestHandler, fallbackClient iface.NodeClient) iface.NodeClient {
|
|
b := &beaconApiNodeClient{
|
|
jsonRestHandler: jsonRestHandler,
|
|
fallbackClient: fallbackClient,
|
|
genesisProvider: &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
|
|
}
|
|
return b
|
|
}
|