Skip to content

Commit

Permalink
(BIDS-3095) revamp adding validators to dashboard (#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
LuccaBitfly authored Jun 6, 2024
1 parent a38c887 commit 79d676a
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 118 deletions.
26 changes: 25 additions & 1 deletion backend/pkg/api/data_access/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,31 @@ func (d *DummyService) GetValidatorDashboardGroupExists(dashboardId t.VDBIdPrima
return true, nil
}

func (d *DummyService) AddValidatorDashboardValidators(dashboardId t.VDBIdPrimary, groupId int64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error) {
func (d *DummyService) GetValidatorDashboardExistingValidatorCount(dashboardId t.VDBIdPrimary, validators []t.VDBValidator) (uint64, error) {
r := uint64(0)
err := commonFakeData(&r)
return r, err
}

func (d *DummyService) AddValidatorDashboardValidators(dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error) {
r := []t.VDBPostValidatorsData{}
err := commonFakeData(&r)
return r, err
}

func (d *DummyService) AddValidatorDashboardValidatorsByDepositAddress(dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error) {
r := []t.VDBPostValidatorsData{}
err := commonFakeData(&r)
return r, err
}

func (d *DummyService) AddValidatorDashboardValidatorsByWithdrawalAddress(dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error) {
r := []t.VDBPostValidatorsData{}
err := commonFakeData(&r)
return r, err
}

func (d *DummyService) AddValidatorDashboardValidatorsByGraffiti(dashboardId t.VDBIdPrimary, groupId uint64, graffiti string, limit uint64) ([]t.VDBPostValidatorsData, error) {
r := []t.VDBPostValidatorsData{}
err := commonFakeData(&r)
return r, err
Expand Down
4 changes: 4 additions & 0 deletions backend/pkg/api/data_access/networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@ func (d *DataAccessService) GetAllNetworks() ([]types.NetworkInfo, error) {
ChainId: 100,
Name: "gnosis",
},
{
ChainId: 17000,
Name: "holesky",
},
}, nil
}
19 changes: 8 additions & 11 deletions backend/pkg/api/data_access/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,13 @@ func (d *DataAccessService) GetSearchValidatorByPublicKey(ctx context.Context, c
func (d *DataAccessService) GetSearchValidatorsByDepositAddress(ctx context.Context, chainId uint64, address []byte) (*t.SearchValidatorsByDepositAddress, error) {
// TODO: implement handling of chainid
ret := &t.SearchValidatorsByDepositAddress{
Address: address,
Validators: make([]uint64, 0),
Address: address,
}
err := db.ReaderDb.Select(&ret.Validators, "select validatorindex from validators where pubkey in (select publickey from eth1_deposits where from_address = $1) order by validatorindex LIMIT 10;", address)
err := db.ReaderDb.Get(&ret.Count, "select count(validatorindex) from validators where pubkey in (select publickey from eth1_deposits where from_address = $1);", address)
if err != nil {
return nil, err
}
if len(ret.Validators) == 0 {
if ret.Count == 0 {
return nil, ErrNotFound
}
return ret, nil
Expand All @@ -81,13 +80,12 @@ func (d *DataAccessService) GetSearchValidatorsByWithdrawalCredential(ctx contex
// TODO: implement handling of chainid
ret := &t.SearchValidatorsByWithdrwalCredential{
WithdrawalCredential: credential,
Validators: make([]uint64, 0),
}
err := db.ReaderDb.Select(&ret.Validators, "select validatorindex from validators where withdrawalcredentials = $1 order by validatorindex LIMIT 10;", credential)
err := db.ReaderDb.Get(&ret.Count, "select count(validatorindex) from validators where withdrawalcredentials = $1;", credential)
if err != nil {
return nil, err
}
if len(ret.Validators) == 0 {
if ret.Count == 0 {
return nil, ErrNotFound
}
return ret, nil
Expand All @@ -102,14 +100,13 @@ func (d *DataAccessService) GetSearchValidatorsByWithdrawalEnsName(ctx context.C
func (d *DataAccessService) GetSearchValidatorsByGraffiti(ctx context.Context, chainId uint64, graffiti string) (*t.SearchValidatorsByGraffiti, error) {
// TODO: implement handling of chainid
ret := &t.SearchValidatorsByGraffiti{
Graffiti: graffiti,
Validators: make([]uint64, 0),
Graffiti: graffiti,
}
err := db.ReaderDb.Select(&ret.Validators, "select distinct proposer from blocks where graffiti_text = $1 limit 10;", graffiti) // added a limit here to keep the query fast
err := db.ReaderDb.Get(&ret.Count, "select count(distinct proposer) from blocks where graffiti_text = $1;", graffiti)
if err != nil {
return nil, err
}
if len(ret.Validators) == 0 {
if ret.Count == 0 {
return nil, ErrNotFound
}
return ret, nil
Expand Down
7 changes: 6 additions & 1 deletion backend/pkg/api/data_access/vdb_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ type ValidatorDashboardRepository interface {
RemoveValidatorDashboardGroup(dashboardId t.VDBIdPrimary, groupId uint64) error

GetValidatorDashboardGroupExists(dashboardId t.VDBIdPrimary, groupId uint64) (bool, error)
AddValidatorDashboardValidators(dashboardId t.VDBIdPrimary, groupId int64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error)
GetValidatorDashboardExistingValidatorCount(dashboardId t.VDBIdPrimary, validators []t.VDBValidator) (uint64, error)
AddValidatorDashboardValidators(dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidatorsByDepositAddress(dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidatorsByWithdrawalAddress(dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidatorsByGraffiti(dashboardId t.VDBIdPrimary, groupId uint64, graffiti string, limit uint64) ([]t.VDBPostValidatorsData, error)

RemoveValidatorDashboardValidators(dashboardId t.VDBIdPrimary, validators []t.VDBValidator) error
GetValidatorDashboardValidators(dashboardId t.VDBId, groupId int64, cursor string, colSort t.Sort[enums.VDBManageValidatorsColumn], search string, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error)

Expand Down
38 changes: 37 additions & 1 deletion backend/pkg/api/data_access/vdb_management.go
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,22 @@ func (d *DataAccessService) GetValidatorDashboardGroupExists(dashboardId t.VDBId
return groupExists, err
}

func (d *DataAccessService) AddValidatorDashboardValidators(dashboardId t.VDBIdPrimary, groupId int64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error) {
// return how many of the passed validators are already in the dashboard
func (d *DataAccessService) GetValidatorDashboardExistingValidatorCount(dashboardId t.VDBIdPrimary, validators []t.VDBValidator) (uint64, error) {
if len(validators) == 0 {
return 0, nil
}

var count uint64
err := d.alloyReader.Get(&count, `
SELECT COUNT(*)
FROM users_val_dashboards_validators
WHERE dashboard_id = $1 AND validator_index = ANY($2)
`, dashboardId, pq.Array(validators))
return count, err
}

func (d *DataAccessService) AddValidatorDashboardValidators(dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error) {
if len(validators) == 0 {
// No validators to add
return nil, nil
Expand Down Expand Up @@ -820,6 +835,27 @@ func (d *DataAccessService) AddValidatorDashboardValidators(dashboardId t.VDBIdP
return result, nil
}

func (d *DataAccessService) AddValidatorDashboardValidatorsByDepositAddress(dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error) {
// TODO
// for all validators already in the dashboard that are associated with the deposit address, update the group
// then add no more than `limit` validators associated with the deposit address to the dashboard
return d.dummy.AddValidatorDashboardValidatorsByDepositAddress(dashboardId, groupId, address, limit)
}

func (d *DataAccessService) AddValidatorDashboardValidatorsByWithdrawalAddress(dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error) {
// TODO
// for all validators already in the dashboard that are associated with the withdrawal address, update the group
// then add no more than `limit` validators associated with the withdrawal address to the dashboard
return d.dummy.AddValidatorDashboardValidatorsByWithdrawalAddress(dashboardId, groupId, address, limit)
}

func (d *DataAccessService) AddValidatorDashboardValidatorsByGraffiti(dashboardId t.VDBIdPrimary, groupId uint64, graffiti string, limit uint64) ([]t.VDBPostValidatorsData, error) {
// TODO
// for all validators already in the dashboard that are associated with the graffiti (by produced block), update the group
// then add no more than `limit` validators associated with the graffiti to the dashboard
return d.dummy.AddValidatorDashboardValidatorsByGraffiti(dashboardId, groupId, graffiti, limit)
}

func (d *DataAccessService) RemoveValidatorDashboardValidators(dashboardId t.VDBIdPrimary, validators []t.VDBValidator) error {
if len(validators) == 0 {
// Remove all validators for the dashboard
Expand Down
4 changes: 2 additions & 2 deletions backend/pkg/api/handlers/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,9 @@ func returnNotFound(w http.ResponseWriter, err error) {
returnError(w, http.StatusNotFound, err)
}

/* func returnConflict(w http.ResponseWriter, err error) {
func returnConflict(w http.ResponseWriter, err error) {
returnError(w, http.StatusConflict, err)
} */
}

func returnInternalServerError(w http.ResponseWriter, err error) {
log.Error(err, "internal server error", 2, nil)
Expand Down
93 changes: 75 additions & 18 deletions backend/pkg/api/handlers/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package handlers

import (
"errors"
"fmt"
"net/http"
"reflect"

"github.com/gobitfly/beaconchain/pkg/api/enums"
types "github.com/gobitfly/beaconchain/pkg/api/types"
Expand Down Expand Up @@ -388,24 +390,34 @@ func (h *HandlerService) InternalPostValidatorDashboardValidators(w http.Respons
var v validationError
dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"])
req := struct {
Validators []string `json:"validators"`
GroupId string `json:"group_id,omitempty"`
GroupId uint64 `json:"group_id,omitempty"`
Validators []string `json:"validators,omitempty"`
DepositAddress string `json:"deposit_address,omitempty"`
WithdrawalAddress string `json:"withdrawal_address,omitempty"`
Graffiti string `json:"graffiti,omitempty"`
}{}
if err := v.checkBody(&req, r); err != nil {
handleErr(w, err)
return
}
indices, pubkeys := v.checkValidatorArray(req.Validators, forbidEmpty)
groupId := v.checkGroupId(req.GroupId, allowEmpty)
// check if exactly one of validators, deposit_address, withdrawal_address, graffiti is set
fields := []interface{}{req.Validators, req.DepositAddress, req.WithdrawalAddress, req.Graffiti}
var count int
for _, set := range fields {
if !reflect.ValueOf(set).IsZero() {
count++
}
}
if count != 1 {
v.add("request body", "exactly one of `validators`, `deposit_address`, `withdrawal_address`, `graffiti` must be set. please check the API documentation for more information")
}
if v.hasErrors() {
handleErr(w, v)
return
}
// empty group id becomes default group
if groupId == types.AllGroups {
groupId = types.DefaultGroupId
}
groupExists, err := h.dai.GetValidatorDashboardGroupExists(dashboardId, uint64(groupId))

groupId := req.GroupId
groupExists, err := h.dai.GetValidatorDashboardGroupExists(dashboardId, groupId)
if err != nil {
handleErr(w, err)
return
Expand All @@ -414,18 +426,63 @@ func (h *HandlerService) InternalPostValidatorDashboardValidators(w http.Respons
returnNotFound(w, errors.New("group not found"))
return
}
validators, err := h.dai.GetValidatorsFromSlices(indices, pubkeys)
if err != nil {
handleErr(w, err)
return
// TODO get real limit once stripe is implemented
limit := ^uint64(0) // user mustn't add more validators than the limit
var data []types.VDBPostValidatorsData
var dataErr error
switch {
case req.Validators != nil:
indices, pubkeys := v.checkValidatorArray(req.Validators, forbidEmpty)
if v.hasErrors() {
handleErr(w, v)
return
}
validators, err := h.dai.GetValidatorsFromSlices(indices, pubkeys)
if err != nil {
handleErr(w, err)
return
}
// check if adding more validators than allowed
existingValidatorCount, err := h.dai.GetValidatorDashboardExistingValidatorCount(dashboardId, validators)
if err != nil {
handleErr(w, err)
return
}
if uint64(len(validators)) > existingValidatorCount+limit {
returnConflict(w, fmt.Errorf("adding more validators than allowed, limit is %v new validators", limit))
return
}
data, dataErr = h.dai.AddValidatorDashboardValidators(dashboardId, groupId, validators)

case req.DepositAddress != "":
depositAddress := v.checkRegex(reEthereumAddress, req.DepositAddress, "deposit_address")
if v.hasErrors() {
handleErr(w, v)
return
}
data, dataErr = h.dai.AddValidatorDashboardValidatorsByDepositAddress(dashboardId, groupId, depositAddress, limit)

case req.WithdrawalAddress != "":
withdrawalAddress := v.checkRegex(reEthereumAddress, req.WithdrawalAddress, "withdrawal_address")
if v.hasErrors() {
handleErr(w, v)
return
}
data, dataErr = h.dai.AddValidatorDashboardValidatorsByWithdrawalAddress(dashboardId, groupId, withdrawalAddress, limit)

case req.Graffiti != "":
graffiti := v.checkRegex(reNonEmpty, req.Graffiti, "graffiti")
if v.hasErrors() {
handleErr(w, v)
return
}
data, dataErr = h.dai.AddValidatorDashboardValidatorsByGraffiti(dashboardId, groupId, graffiti, limit)
}
// TODO check validator limit reached
data, err := h.dai.AddValidatorDashboardValidators(dashboardId, groupId, validators)
if err != nil {
handleErr(w, err)

if dataErr != nil {
handleErr(w, dataErr)
return
}

response := types.ApiResponse{
Data: data,
}
Expand Down
Loading

0 comments on commit 79d676a

Please sign in to comment.