From ac58ef8c9913bfdf8268bd8c8818d96d3e8142fd Mon Sep 17 00:00:00 2001 From: Sasha Zezulinsky <188990923+sasha-bitfly@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:22:16 +0000 Subject: [PATCH] add(dashboard): calculate total missed el rewards using postgres db --- backend/pkg/api/data_access/vdb_summary.go | 118 ++++++++++++--------- 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/backend/pkg/api/data_access/vdb_summary.go b/backend/pkg/api/data_access/vdb_summary.go index a8b7cd47f..308284ebb 100644 --- a/backend/pkg/api/data_access/vdb_summary.go +++ b/backend/pkg/api/data_access/vdb_summary.go @@ -521,56 +521,70 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex return nil, err } - getMissedELRewards := func(validatorId uint32, epochStart, epochEnd uint64) (float64, error) { + getMissedELRewards := func(epochStart, epochEnd uint64) (float64, error) { // Initialize the result variable - var missedElRewards float64 - - // Execute the query - err := d.readerDb.GetContext(ctx, &missedElRewards, - `SELECT - COALESCE(SUM(v), 0) AS total_median_rewards - FROM ( - SELECT - a.slot, - PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY b.value)::numeric(76,0) AS v - FROM ( - SELECT - b.slot AS slot - FROM - blocks b - WHERE - b.proposer = $1 - AND b.status != '1' - AND b.epoch BETWEEN $2 AND $3 - ) a - LEFT JOIN - execution_rewards_finalized b - ON - (b.slot BETWEEN a.slot - 16 AND a.slot + 16) - GROUP BY - a.slot - ) res;`, validatorId, epochStart, epochEnd) - - // Handle query execution error + var totalMissedRewardsEl float64 + + // SQL query + query := ` + WITH targets AS ( + SELECT + b.slot AS slot + FROM + blocks b + JOIN + users_val_dashboards_validators uvdv + ON + b.proposer = uvdv.validator_index + WHERE + uvdv.dashboard_id = $1 + AND b.status != '1' + AND epoch >= $2 + AND epoch <= $3 + ), + res AS ( + SELECT + a.slot, + percentile_cont(0.5) WITHIN GROUP (ORDER BY b.value)::numeric(76,0) AS v + FROM + targets a + LEFT JOIN + execution_rewards_finalized b + ON + b.slot >= a.slot - 16 + AND b.slot < a.slot + 16 + GROUP BY + a.slot + ) + SELECT + COALESCE(SUM(v), 0) + FROM + res; + ` + + // Execute the query with the provided parameters + err := d.readerDb.GetContext(ctx, &totalMissedRewardsEl, query, dashboardId.Id, epochStart, epochEnd) if err != nil { return 0, fmt.Errorf("failed to execute query: %w", err) } // Return the computed total median rewards - return missedElRewards, nil + return totalMissedRewardsEl, nil } - getLastScheduledBlockAndSyncDate := func() (time.Time, time.Time, error) { + getLastScheduledBlockAndSyncDate := func() (time.Time, time.Time, uint64, uint64, error) { // we need to go to the all time table for last scheduled block/sync committee epoch clickhouseTotalTable, _, err := d.getTablesForPeriod(enums.AllTime) if err != nil { - return time.Time{}, time.Time{}, err + return time.Time{}, time.Time{}, 0, 0, err } ds := goqu.Dialect("postgres"). Select( goqu.L("MAX(last_scheduled_block_epoch) as last_scheduled_block_epoch"), - goqu.L("MAX(last_scheduled_sync_epoch) as last_scheduled_sync_epoch")). + goqu.L("MAX(last_scheduled_sync_epoch) as last_scheduled_sync_epoch"), + goqu.L("MIN(epoch_start) as min_epoch_start"), + goqu.L("MAX(epoch_end) as max_epoch_end")). From(goqu.L(fmt.Sprintf(`%s AS r FINAL`, clickhouseTotalTable))) if dashboardId.Validators == nil { @@ -585,23 +599,29 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex query, args, err := ds.Prepared(true).ToSQL() if err != nil { - return time.Time{}, time.Time{}, err + return time.Time{}, time.Time{}, 0, 0, err } var row struct { - LastScheduledBlockEpoch *int64 `db:"last_scheduled_block_epoch"` - LastSyncEpoch *int64 `db:"last_scheduled_sync_epoch"` + LastScheduledBlockEpoch *int64 `db:"last_scheduled_block_epoch"` + LastSyncEpoch *int64 `db:"last_scheduled_sync_epoch"` + MinEpochStart *uint64 `db:"min_epoch_start"` + MaxEpochEnd *uint64 `db:"max_epoch_end"` } err = d.clickhouseReader.GetContext(ctx, &row, query, args...) if err != nil { - return time.Time{}, time.Time{}, err + return time.Time{}, time.Time{}, 0, 0, err } if row.LastScheduledBlockEpoch == nil || row.LastSyncEpoch == nil { - return time.Time{}, time.Time{}, nil + return time.Time{}, time.Time{}, 0, 0, nil } - return utils.EpochToTime(uint64(*row.LastScheduledBlockEpoch)), utils.EpochToTime(uint64(*row.LastSyncEpoch)), nil + return utils.EpochToTime(uint64(*row.LastScheduledBlockEpoch)), + utils.EpochToTime(uint64(*row.LastSyncEpoch)), + *row.MinEpochStart, + *row.MaxEpochEnd, + nil } ds := goqu.Dialect("postgres"). @@ -691,10 +711,11 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex return nil }) + var minEpochStart, maxEpochEnd uint64 var lastBlockTs, lastSyncTs time.Time errGroup.Go(func() error { var err error - lastBlockTs, lastSyncTs, err = getLastScheduledBlockAndSyncDate() + lastBlockTs, lastSyncTs, minEpochStart, maxEpochEnd, err = getLastScheduledBlockAndSyncDate() return err }) @@ -720,7 +741,6 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex totalBlocksScheduled := uint32(0) totalBlocksProposed := uint32(0) - totalMissedRewardsEl := float64(0) totalMissedRewardsCl := int64(0) totalMissedRewardsAttestations := int64(0) totalMissedRewardsSync := int64(0) @@ -740,12 +760,6 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex ret.AttestationsTarget.Success += uint64(row.AttestationsTargetExecuted) ret.AttestationsTarget.Failed += uint64(row.AttestationsScheduled) - uint64(row.AttestationsTargetExecuted) - missedRewards, err := getMissedELRewards(row.ValidatorIndex, row.EpochStart, row.EpochEnd) - if err != nil { - return nil, err - } - - totalMissedRewardsEl += missedRewards totalMissedRewardsCl += row.BlocksCLMissedReward totalMissedRewardsAttestations += row.AttestationsIdealReward - row.AttestationsRewardRewardsOnly totalMissedRewardsSync += row.SyncLocalizedMaxRewards - row.SyncRewardRewardsOnly @@ -799,10 +813,16 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex totalInclusionDelayDivisor += row.AttestationsObserved } } + + totalMissedRewardsEl, err := getMissedELRewards(minEpochStart, maxEpochEnd) + if err != nil { + return nil, err + } + ret.MissedRewards.Attestations = utils.GWeiToWei(big.NewInt(totalMissedRewardsAttestations)) ret.MissedRewards.Sync = utils.GWeiToWei(big.NewInt(totalMissedRewardsSync)) ret.MissedRewards.ProposerRewards.Cl = utils.GWeiToWei(big.NewInt(totalMissedRewardsCl)) - //ret.MissedRewards.ProposerRewards.El = utils.GWeiToEther(big.NewInt(totalMissedRewardsEl)) + ret.MissedRewards.ProposerRewards.El = decimal.NewFromFloat(totalMissedRewardsEl) ret.Rewards.El, ret.Apr.El, ret.Rewards.Cl, ret.Apr.Cl, err = d.getElClAPR(ctx, dashboardId, groupId, hours) if err != nil {