Skip to content

Commit

Permalink
HTTP validator API: beacon and account endpoints (#13191)
Browse files Browse the repository at this point in the history
* fixing squashing changes, migrates beacon , account, and auth endpoints on validator client

* adding accounts endpoints

* fixing tests and query endpoints

* adding auth endpoint and fixing unit tests

* removing unused files and updating node file to skip gRPC

* ineffectual assignment fix

* rolling back a change to fix e2e

* fixing issues with ui

* updating with webui version 2.0.5

* updating package name flag in readme

* removing restore assets functions

* adding nomemcopy flag to see if vulenerability scan passes

* making data non compressed to avoid copy vulnerability

* Update beacon-chain/rpc/eth/shared/structs_validator.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* updating site_data, and skipping static analysis on file

* adding back deprecation comment notice

* updating workflows to ignore generated

* addressing radek comments

* missed a conversion

---------

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
  • Loading branch information
james-prysm and rauljordan committed Dec 1, 2023
1 parent 461af4b commit 394bd17
Show file tree
Hide file tree
Showing 38 changed files with 2,052 additions and 4,623 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
run: | # https://github.com/securego/gosec/issues/469
export PATH=$PATH:$(go env GOPATH)/bin
go install github.com/securego/gosec/v2/cmd/gosec@v2.15.0
gosec -exclude=G307 -exclude-dir=crypto/bls/herumi ./...
gosec -exclude-generated -exclude=G307 -exclude-dir=crypto/bls/herumi ./...
lint:
name: Lint
Expand Down
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
101 changes: 101 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,104 @@ 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 {
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,
}
}

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
}
156 changes: 156 additions & 0 deletions beacon-chain/rpc/eth/shared/structs_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package shared

import (
"github.com/ethereum/go-ethereum/common/hexutil"
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 {
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,
}
}

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) {
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) {
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
}
3 changes: 2 additions & 1 deletion nogo_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@
},
"exclude_files": {
".*_test\\.go": "Tests are ok",
"io/file/fileutil.go": "Package which defines the proper rules"
"io/file/fileutil.go": "Package which defines the proper rules",
"validator/web/site_data.go": "Generated web ui assets"
}
},
"uintcast": {
Expand Down
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

0 comments on commit 394bd17

Please sign in to comment.