Skip to content

Commit

Permalink
refactor(api): validator addition
Browse files Browse the repository at this point in the history
  • Loading branch information
remoterami committed Feb 5, 2025
1 parent a17f8f8 commit b52da1c
Show file tree
Hide file tree
Showing 14 changed files with 642 additions and 155 deletions.
8 changes: 6 additions & 2 deletions backend/pkg/api/data_access/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ func (d *DummyService) GetValidatorsFromSlices(ctx context.Context, indices []ui
return getDummyData[[]t.VDBValidator](ctx)
}

func (d *DummyService) GetValidatorsEffectiveBalanceTotal(ctx context.Context, indices []uint64) (uint64, error) {
return getDummyData[uint64](ctx)
}

func (d *DummyService) GetUserDashboards(ctx context.Context, userId uint64) (*t.UserDashboardsData, error) {
return getDummyStruct[t.UserDashboardsData](ctx)
}
Expand Down Expand Up @@ -266,7 +270,7 @@ func (d *DummyService) GetValidatorDashboardGroupExists(ctx context.Context, das
return true, nil
}

func (d *DummyService) AddValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error) {
func (d *DummyService) AddValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator, limit uint64) ([]t.VDBPostValidatorsData, error) {
return getDummyData[[]t.VDBPostValidatorsData](ctx)
}

Expand Down Expand Up @@ -542,7 +546,7 @@ func (d *DummyService) GetValidatorDashboardGroupCount(ctx context.Context, dash
return getDummyData[uint64](ctx)
}

func (d *DummyService) GetValidatorDashboardValidatorsCount(ctx context.Context, dashboardId t.VDBIdPrimary) (uint64, error) {
func (d *DummyService) GetValidatorDashboardEffectiveBalanceTotal(ctx context.Context, dashboardId t.VDBId) (uint64, error) {
return getDummyData[uint64](ctx)
}

Expand Down
84 changes: 84 additions & 0 deletions backend/pkg/api/data_access/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package dataaccess

import (
"context"
"database/sql"
"fmt"

"github.com/doug-martin/goqu/v9"
"github.com/doug-martin/goqu/v9/exp"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gobitfly/beaconchain/pkg/api/types"
t "github.com/gobitfly/beaconchain/pkg/api/types"
"github.com/gobitfly/beaconchain/pkg/commons/db"
"github.com/gobitfly/beaconchain/pkg/commons/utils"
constypes "github.com/gobitfly/beaconchain/pkg/consapi/types"
)

// retrieve (primary) ens name and optional name (=label) maintained by beaconcha.in, if present
Expand Down Expand Up @@ -131,3 +135,83 @@ func applySortAndPagination(defaultColumns []types.SortColumn, primary types.Sor

return queryOrder, queryWhere, nil
}

// returns the effective balances of the provided validators
// executed from the vdb premium limits pov, i.e. exited validators account for the EB at exit time
func (d *DataAccessService) GetValidatorsEffectiveBalances(ctx context.Context, validators []t.VDBValidator, onlyActive bool) (map[t.VDBValidator]uint64, error) {
validatorMapping, err := d.services.GetCurrentValidatorMapping()
if err != nil {
return nil, err
}

// active
effectiveBalances := make(map[t.VDBValidator]uint64)
var validatorExitEpochs []exp.Expression
for _, validator := range validators {
if len(validatorMapping.ValidatorMetadata) <= int(validator) {
return nil, fmt.Errorf("validator index %d not found in validator mapping", validator)
}
status := constypes.ValidatorDbStatus(validatorMapping.ValidatorMetadata[validator].Status)
if !onlyActive &&
(status == constypes.DbSlashed || status == constypes.DbExited) &&
validatorMapping.ValidatorMetadata[validator].EffectiveBalance == 0 {
// exited & balance withdrawn, need to query latest EB before exit
if !validatorMapping.ValidatorMetadata[validator].ExitEpoch.Valid {
return nil, fmt.Errorf("validator %d has no exit epoch", validator)
}
// goqu can't pass tuples directly
epochTs := utils.EpochToTime(uint64(validatorMapping.ValidatorMetadata[validator].ExitEpoch.Int64)).Unix()
validatorExitEpochs = append(validatorExitEpochs, goqu.L("(fromUnixTimestamp(?), ?)", epochTs, validator))
} else {
effectiveBalances[validator] = validatorMapping.ValidatorMetadata[validator].EffectiveBalance
}
}

// exited
if len(validatorExitEpochs) > 0 {
ds := goqu.Dialect("postgres").
Select(
// goqu.SUM(goqu.I("balance_effective_end")).As("balance_effective_end"),
goqu.I("validator_index"),
goqu.I("balance_effective_end"),
).
From("validator_dashboard_data_epoch").
Where(
goqu.L("(epoch_timestamp, validator_index)").In(validatorExitEpochs),
)
query, args, err := ds.Prepared(true).ToSQL()
if err != nil {
return nil, err
}

ebsBeforeExit := []struct {
ValidatorIndex uint64 `db:"validator_index"`
EffectiveBalance uint64 `db:"balance_effective_end"`
}{}
err = d.clickhouseReader.SelectContext(ctx, &ebsBeforeExit, query, args...)
if err != nil && err != sql.ErrNoRows {
return nil, err
}
for _, eb := range ebsBeforeExit {
effectiveBalances[eb.ValidatorIndex] = eb.EffectiveBalance
}
}
return effectiveBalances, nil
}

func (d *DataAccessService) GetValidatorsEffectiveBalanceTotal(ctx context.Context, validators []t.VDBValidator) (uint64, error) {
validatorEbs, err := d.GetValidatorsEffectiveBalances(ctx, validators, false)
if err != nil {
return 0, err
}

var totalEb uint64
for _, validator := range validators {
if eb, ok := validatorEbs[validator]; !ok {
return 0, fmt.Errorf("effective balance for validator %d not found", validator)
} else {
totalEb += eb
}
}
return totalEb, nil
}
4 changes: 2 additions & 2 deletions backend/pkg/api/data_access/vdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ type ValidatorDashboardRepository interface {
GetValidatorDashboardGroupCount(ctx context.Context, dashboardId t.VDBIdPrimary) (uint64, error)
GetValidatorDashboardGroupExists(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64) (bool, error)

AddValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, validators []t.VDBValidator, limit uint64) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidatorsByDepositAddress(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, address string, limit uint64) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidatorsByWithdrawalCredential(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, credential string, limit uint64) ([]t.VDBPostValidatorsData, error)
AddValidatorDashboardValidatorsByGraffiti(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, graffiti string, limit uint64) ([]t.VDBPostValidatorsData, error)

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

CreateValidatorDashboardPublicId(ctx context.Context, dashboardId t.VDBIdPrimary, name string, shareGroups bool) (*t.VDBPublicId, error)
GetValidatorDashboardPublicId(ctx context.Context, publicDashboardId t.VDBIdPublic) (*t.VDBPublicId, error)
Expand Down
Loading

0 comments on commit b52da1c

Please sign in to comment.