From 947298745ddaf2302ef20639806865f8ab8a4ce9 Mon Sep 17 00:00:00 2001 From: 0xrajath Date: Tue, 7 Jan 2025 14:54:14 -0500 Subject: [PATCH] default operator split snapshots --- pkg/rewards/defaultOperatorSplitSnapshots.go | 89 ++++++++++++++++++++ pkg/rewards/rewards.go | 11 ++- 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 pkg/rewards/defaultOperatorSplitSnapshots.go diff --git a/pkg/rewards/defaultOperatorSplitSnapshots.go b/pkg/rewards/defaultOperatorSplitSnapshots.go new file mode 100644 index 00000000..05b533c7 --- /dev/null +++ b/pkg/rewards/defaultOperatorSplitSnapshots.go @@ -0,0 +1,89 @@ +package rewards + +import "github.com/Layr-Labs/sidecar/pkg/rewardsUtils" + +const defaultOperatorSplitSnapshotQuery = ` +WITH default_operator_splits_with_block_info as ( + select + dos.new_default_operator_split_bips as split, + dos.block_number, + dos.log_index, + b.block_time::timestamp(6) as block_time + from default_operator_splits as dos + join blocks as b on (b.number = dos.block_number) + where b.block_time < TIMESTAMP '{{.cutoffDate}}' +), +-- Rank the records for each combination of (block date) by block time and log index +ranked_default_operator_split_records as ( + SELECT + *, + ROW_NUMBER() OVER (PARTITION BY cast(block_time AS DATE) ORDER BY block_time DESC, log_index DESC) AS rn + FROM default_operator_splits_with_block_info +), +-- Get the latest record for each day & round up to the snapshot day +snapshotted_records as ( + SELECT + split, + block_time, + date_trunc('day', block_time) + INTERVAL '1' day AS snapshot_time + from ranked_default_operator_split_records + where rn = 1 +), +-- Get the range for each operator, avs pairing +default_operator_split_windows as ( + SELECT + split, + snapshot_time as start_time, + CASE + -- If the range does not have the end, use the current timestamp truncated to 0 UTC + WHEN LEAD(snapshot_time) OVER (ORDER BY snapshot_time) is null THEN date_trunc('day', TIMESTAMP '{{.cutoffDate}}') + ELSE LEAD(snapshot_time) OVER (ORDER BY snapshot_time) + END AS end_time + FROM snapshotted_records +), +-- Clean up any records where start_time >= end_time +cleaned_records as ( + SELECT * FROM default_operator_split_windows + WHERE start_time < end_time +), +-- Generate a snapshot for each day in the range +final_results as ( + SELECT + split, + d AS snapshot + FROM + cleaned_records + CROSS JOIN + generate_series(DATE(start_time), DATE(end_time) - interval '1' day, interval '1' day) AS d +) +select * from final_results +` + +func (r *RewardsCalculator) GenerateAndInsertDefaultOperatorSplitSnapshots(snapshotDate string) error { + tableName := "default_operator_split_snapshots" + + query, err := rewardsUtils.RenderQueryTemplate(defaultOperatorSplitSnapshotQuery, map[string]interface{}{ + "cutoffDate": snapshotDate, + }) + if err != nil { + r.logger.Sugar().Errorw("Failed to render query template", "error", err) + return err + } + + err = r.generateAndInsertFromQuery(tableName, query, nil) + if err != nil { + r.logger.Sugar().Errorw("Failed to generate default_operator_split_snapshots", "error", err) + return err + } + return nil +} + +func (r *RewardsCalculator) ListDefaultOperatorSplitSnapshots() ([]*DefaultOperatorSplitSnapshots, error) { + var snapshots []*DefaultOperatorSplitSnapshots + res := r.grm.Model(&DefaultOperatorSplitSnapshots{}).Find(&snapshots) + if res.Error != nil { + r.logger.Sugar().Errorw("Failed to list default operator split snapshots", "error", res.Error) + return nil, res.Error + } + return snapshots, nil +} diff --git a/pkg/rewards/rewards.go b/pkg/rewards/rewards.go index 70fda127..485963d0 100644 --- a/pkg/rewards/rewards.go +++ b/pkg/rewards/rewards.go @@ -8,6 +8,9 @@ import ( "sync/atomic" + "slices" + "strings" + "github.com/Layr-Labs/eigenlayer-rewards-proofs/pkg/distribution" "github.com/Layr-Labs/sidecar/internal/config" "github.com/Layr-Labs/sidecar/pkg/rewards/stakerOperators" @@ -18,8 +21,6 @@ import ( "go.uber.org/zap" "gorm.io/gorm" "gorm.io/gorm/clause" - "slices" - "strings" ) type RewardsCalculator struct { @@ -625,6 +626,12 @@ func (rc *RewardsCalculator) generateSnapshotData(snapshotDate string) error { } rc.logger.Sugar().Debugw("Generated operator pi snapshots") + if err = rc.GenerateAndInsertDefaultOperatorSplitSnapshots(snapshotDate); err != nil { + rc.logger.Sugar().Errorw("Failed to generate default operator split snapshots", "error", err) + return err + } + rc.logger.Sugar().Debugw("Generated default operator split snapshots") + return nil }