Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP validator API: beacon and account endpoints #13191

Merged
merged 28 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
34c6f62
fixing squashing changes, migrates beacon , account, and auth endpoin…
james-prysm Nov 16, 2023
952c7ca
adding accounts endpoints
james-prysm Nov 16, 2023
2df0796
fixing tests and query endpoints
james-prysm Nov 16, 2023
c56f2df
adding auth endpoint and fixing unit tests
james-prysm Nov 16, 2023
630b9ff
Merge branch 'develop' into http-validator-beacon
james-prysm Nov 16, 2023
8a2b658
removing unused files and updating node file to skip gRPC
james-prysm Nov 16, 2023
5a37eea
ineffectual assignment fix
james-prysm Nov 17, 2023
62e9fde
rolling back a change to fix e2e
james-prysm Nov 17, 2023
194dcf5
fixing issues with ui
james-prysm Nov 17, 2023
439ae3a
Merge branch 'develop' into http-validator-beacon
james-prysm Nov 17, 2023
0fdc8dd
Merge branch 'develop' into http-validator-beacon
james-prysm Nov 28, 2023
374e230
Merge branch 'develop' into http-validator-beacon
james-prysm Nov 29, 2023
74c6312
updating with webui version 2.0.5
james-prysm Nov 30, 2023
945903a
updating package name flag in readme
james-prysm Nov 30, 2023
04f1927
removing restore assets functions
james-prysm Nov 30, 2023
561ff56
Merge branch 'develop' into http-validator-beacon
james-prysm Nov 30, 2023
f43d48a
adding nomemcopy flag to see if vulenerability scan passes
james-prysm Nov 30, 2023
95a47ff
making data non compressed to avoid copy vulnerability
james-prysm Nov 30, 2023
39ec677
Merge branch 'develop' into http-validator-beacon
james-prysm Dec 1, 2023
552ea8d
Update beacon-chain/rpc/eth/shared/structs_validator.go
james-prysm Dec 1, 2023
0767600
updating site_data, and skipping static analysis on file
james-prysm Dec 1, 2023
c3630ba
adding back deprecation comment notice
james-prysm Dec 1, 2023
e5b3218
updating workflows to ignore generated
james-prysm Dec 1, 2023
c7f1651
Merge branch 'develop' into http-validator-beacon
james-prysm Dec 1, 2023
338829f
addressing radek comments
james-prysm Dec 1, 2023
a13bf3b
missed a conversion
james-prysm Dec 1, 2023
3566090
Merge branch 'develop' into http-validator-beacon
james-prysm Dec 1, 2023
12628c5
Merge branch 'develop' into http-validator-beacon
james-prysm Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion api/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ load("@prysm//tools/go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["headers.go"],
srcs = [
"constants.go",
"headers.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/api",
visibility = ["//visibility:public"],
)
3 changes: 3 additions & 0 deletions api/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package api

const WebUrlPrefix = "/v2/validator/"
1 change: 1 addition & 0 deletions beacon-chain/rpc/eth/shared/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ go_library(
"structs.go",
"structs_blocks.go",
"structs_blocks_conversions.go",
"structs_validator.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared",
visibility = ["//visibility:public"],
Expand Down
104 changes: 104 additions & 0 deletions beacon-chain/rpc/eth/shared/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,3 +701,107 @@ type SyncDetails struct {
type SyncDetailsContainer struct {
Data *SyncDetails `json:"data"`
}

// ChainHead is the response for api endpoint /beacon/chainhead
type ChainHead struct {
HeadSlot string `json:"head_slot"`
HeadEpoch string `json:"head_epoch"`
HeadBlockRoot string `json:"head_block_root"`
FinalizedSlot string `json:"finalized_slot"`
FinalizedEpoch string `json:"finalized_epoch"`
FinalizedBlockRoot string `json:"finalized_block_root"`
JustifiedSlot string `json:"justified_slot"`
JustifiedEpoch string `json:"justified_epoch"`
JustifiedBlockRoot string `json:"justified_block_root"`
PreviousJustifiedSlot string `json:"previous_justified_slot"`
PreviousJustifiedEpoch string `json:"previous_justified_epoch"`
PreviousJustifiedBlockRoot string `json:"previous_justified_block_root"`
OptimisticStatus bool `json:"optimistic_status"`
}

func ChainHeadResponseFromConsensus(e *eth.ChainHead) (*ChainHead, error) {
if e == nil {
return nil, errors.New("ChainHead is empty")
}
return &ChainHead{
HeadSlot: fmt.Sprintf("%d", e.HeadSlot),
HeadEpoch: fmt.Sprintf("%d", e.HeadEpoch),
HeadBlockRoot: hexutil.Encode(e.HeadBlockRoot),
FinalizedSlot: fmt.Sprintf("%d", e.FinalizedSlot),
FinalizedEpoch: fmt.Sprintf("%d", e.FinalizedEpoch),
FinalizedBlockRoot: hexutil.Encode(e.FinalizedBlockRoot),
JustifiedSlot: fmt.Sprintf("%d", e.JustifiedSlot),
JustifiedEpoch: fmt.Sprintf("%d", e.JustifiedEpoch),
JustifiedBlockRoot: hexutil.Encode(e.JustifiedBlockRoot),
PreviousJustifiedSlot: fmt.Sprintf("%d", e.PreviousJustifiedSlot),
PreviousJustifiedEpoch: fmt.Sprintf("%d", e.PreviousJustifiedEpoch),
PreviousJustifiedBlockRoot: hexutil.Encode(e.PreviousJustifiedBlockRoot),
OptimisticStatus: e.OptimisticStatus,
}, nil
}

func (m *ChainHead) ToConsensus() (*eth.ChainHead, error) {
headSlot, err := strconv.ParseUint(m.HeadSlot, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "HeadSlot")
}
headEpoch, err := strconv.ParseUint(m.HeadEpoch, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "HeadEpoch")
}
headBlockRoot, err := DecodeHexWithLength(m.HeadBlockRoot, fieldparams.RootLength)
if err != nil {
return nil, NewDecodeError(err, "HeadBlockRoot")
}
finalizedSlot, err := strconv.ParseUint(m.FinalizedSlot, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "FinalizedSlot")
}
finalizedEpoch, err := strconv.ParseUint(m.FinalizedEpoch, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "FinalizedEpoch")
}
finalizedBlockRoot, err := DecodeHexWithLength(m.FinalizedBlockRoot, fieldparams.RootLength)
if err != nil {
return nil, NewDecodeError(err, "FinalizedBlockRoot")
}
justifiedSlot, err := strconv.ParseUint(m.JustifiedSlot, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "JustifiedSlot")
}
justifiedEpoch, err := strconv.ParseUint(m.JustifiedEpoch, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "JustifiedEpoch")
}
justifiedBlockRoot, err := DecodeHexWithLength(m.JustifiedBlockRoot, fieldparams.RootLength)
if err != nil {
return nil, NewDecodeError(err, "JustifiedBlockRoot")
}
previousjustifiedSlot, err := strconv.ParseUint(m.PreviousJustifiedSlot, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "PreviousJustifiedSlot")
}
previousjustifiedEpoch, err := strconv.ParseUint(m.PreviousJustifiedEpoch, 10, 64)
if err != nil {
return nil, NewDecodeError(err, "PreviousJustifiedEpoch")
}
previousjustifiedBlockRoot, err := DecodeHexWithLength(m.PreviousJustifiedBlockRoot, fieldparams.RootLength)
if err != nil {
return nil, NewDecodeError(err, "PreviousJustifiedBlockRoot")
}
return &eth.ChainHead{
HeadSlot: primitives.Slot(headSlot),
HeadEpoch: primitives.Epoch(headEpoch),
HeadBlockRoot: headBlockRoot,
FinalizedSlot: primitives.Slot(finalizedSlot),
FinalizedEpoch: primitives.Epoch(finalizedEpoch),
FinalizedBlockRoot: finalizedBlockRoot,
JustifiedSlot: primitives.Slot(justifiedSlot),
JustifiedEpoch: primitives.Epoch(justifiedEpoch),
JustifiedBlockRoot: justifiedBlockRoot,
PreviousJustifiedSlot: primitives.Slot(previousjustifiedSlot),
PreviousJustifiedEpoch: primitives.Epoch(previousjustifiedEpoch),
PreviousJustifiedBlockRoot: previousjustifiedBlockRoot,
OptimisticStatus: m.OptimisticStatus,
}, nil
}
166 changes: 166 additions & 0 deletions beacon-chain/rpc/eth/shared/structs_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package shared

import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)

type ValidatorPerformanceResponse struct {
CurrentEffectiveBalances []uint64 `json:"current_effective_balances"`
InclusionSlots []uint64 `json:"inclusion_slots"`
InclusionDistances []uint64 `json:"inclusion_distances"`
CorrectlyVotedSource []bool `json:"correctly_voted_source"`
CorrectlyVotedTarget []bool `json:"correctly_voted_target"`
CorrectlyVotedHead []bool `json:"correctly_voted_head"`
BalancesBeforeEpochTransition []uint64 `json:"balances_before_epoch_transition"`
BalancesAfterEpochTransition []uint64 `json:"balances_after_epoch_transition"`
MissingValidators []string `json:"missing_validators"`
AverageActiveValidatorBalance float32 `json:"average_active_validator_balance"`
PublicKeys []string `json:"public_keys"`
InactivityScores []uint64 `json:"inactivity_scores"`
}

func ValidatorPerformanceResponseFromConsensus(e *eth.ValidatorPerformanceResponse) (*ValidatorPerformanceResponse, error) {
if e == nil {
return nil, errors.New("ValidatorPerformanceResponse is empty")
}
inclusionSlots := make([]uint64, len(e.InclusionSlots))
for i, index := range e.InclusionSlots {
inclusionSlots[i] = uint64(index)
}
inclusionDistances := make([]uint64, len(e.InclusionDistances))
for i, index := range e.InclusionDistances {
inclusionDistances[i] = uint64(index)
}
missingValidators := make([]string, len(e.MissingValidators))
for i, key := range e.MissingValidators {
missingValidators[i] = hexutil.Encode(key)
}
publicKeys := make([]string, len(e.PublicKeys))
for i, key := range e.PublicKeys {
publicKeys[i] = hexutil.Encode(key)
}
if len(e.CurrentEffectiveBalances) == 0 {
e.CurrentEffectiveBalances = make([]uint64, 0)
}
if len(e.BalancesBeforeEpochTransition) == 0 {
e.BalancesBeforeEpochTransition = make([]uint64, 0)
}
if len(e.BalancesAfterEpochTransition) == 0 {
e.BalancesAfterEpochTransition = make([]uint64, 0)
}
if len(e.CorrectlyVotedSource) == 0 {
e.CorrectlyVotedSource = make([]bool, 0)
}
if len(e.CorrectlyVotedTarget) == 0 {
e.CorrectlyVotedTarget = make([]bool, 0)
}
if len(e.CorrectlyVotedHead) == 0 {
e.CorrectlyVotedHead = make([]bool, 0)
}
if len(e.InactivityScores) == 0 {
e.InactivityScores = make([]uint64, 0)
}
return &ValidatorPerformanceResponse{
CurrentEffectiveBalances: e.CurrentEffectiveBalances,
InclusionSlots: inclusionSlots,
InclusionDistances: inclusionDistances,
CorrectlyVotedSource: e.CorrectlyVotedSource,
CorrectlyVotedTarget: e.CorrectlyVotedTarget,
CorrectlyVotedHead: e.CorrectlyVotedHead,
BalancesBeforeEpochTransition: e.BalancesBeforeEpochTransition,
BalancesAfterEpochTransition: e.BalancesAfterEpochTransition,
MissingValidators: missingValidators,
AverageActiveValidatorBalance: e.AverageActiveValidatorBalance,
PublicKeys: publicKeys,
InactivityScores: e.InactivityScores,
}, nil
}

type ValidatorBalancesResponse struct {
Epoch uint64 `json:"epoch"`
Balances []*ValidatorBalance `json:"balances"`
NextPageToken string `json:"next_page_token"`
TotalSize int32 `json:"total_size,omitempty"`
}

type ValidatorBalance struct {
PublicKey string `json:"public_key"`
Index uint64 `json:"index"`
Balance uint64 `json:"balance"`
Status string `json:"status"`
}

func ValidatorBalancesResponseFromConsensus(e *eth.ValidatorBalances) (*ValidatorBalancesResponse, error) {
if e == nil {
return nil, errors.New("ValidatorBalances is empty")
}
balances := make([]*ValidatorBalance, len(e.Balances))
for i, balance := range e.Balances {
balances[i] = &ValidatorBalance{
PublicKey: hexutil.Encode(balance.PublicKey),
Index: uint64(balance.Index),
Balance: balance.Balance,
Status: balance.Status,
}
}
return &ValidatorBalancesResponse{
Epoch: uint64(e.Epoch),
Balances: balances,
NextPageToken: e.NextPageToken,
TotalSize: e.TotalSize,
}, nil
}

type ValidatorsResponse struct {
Epoch uint64 `json:"epoch"`
ValidatorList []*ValidatorContainer `json:"validator_list"`
NextPageToken string `json:"next_page_token"`
TotalSize int32 `json:"total_size"`
}

type ValidatorContainer struct {
Index uint64 `json:"index"`
Validator *Validator `json:"validator"`
}

type Validator struct {
PublicKey string `json:"public_key,omitempty"`
WithdrawalCredentials string `json:"withdrawal_credentials"`
EffectiveBalance uint64 `json:"effective_balance"`
Slashed bool `json:"slashed"`
ActivationEligibilityEpoch uint64 `json:"activation_eligibility_epoch"`
ActivationEpoch uint64 `json:"activation_epoch"`
ExitEpoch uint64 `json:"exit_epoch"`
WithdrawableEpoch uint64 `json:"withdrawable_epoch"`
}

func ValidatorsResponseFromConsensus(e *eth.Validators) (*ValidatorsResponse, error) {
if e == nil {
return nil, errors.New("VValidatorsResponse is empty")
james-prysm marked this conversation as resolved.
Show resolved Hide resolved
}
validatorList := make([]*ValidatorContainer, len(e.ValidatorList))
for i, validatorContainer := range e.ValidatorList {
val := validatorContainer.Validator
validatorList[i] = &ValidatorContainer{
Index: uint64(validatorContainer.Index),
Validator: &Validator{
PublicKey: hexutil.Encode(val.PublicKey),
WithdrawalCredentials: hexutil.Encode(val.WithdrawalCredentials),
EffectiveBalance: val.EffectiveBalance,
Slashed: val.Slashed,
ActivationEligibilityEpoch: uint64(val.ActivationEligibilityEpoch),
ActivationEpoch: uint64(val.ActivationEpoch),
ExitEpoch: uint64(val.ExitEpoch),
WithdrawableEpoch: uint64(val.WithdrawableEpoch),
},
}
}
return &ValidatorsResponse{
Epoch: uint64(e.Epoch),
ValidatorList: validatorList,
NextPageToken: e.NextPageToken,
TotalSize: e.TotalSize,
}, nil
}
1 change: 0 additions & 1 deletion proto/prysm/v1alpha1/validator-client/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ proto_library(
name = "proto",
srcs = [
"keymanager.proto",
"web_api.proto",
],
visibility = ["//visibility:public"],
deps = [
Expand Down
Loading
Loading