Skip to content

Baker KPIs#20

Closed
0xVoronov wants to merge 11 commits intomasterfrom
feature/backer-kpis
Closed

Baker KPIs#20
0xVoronov wants to merge 11 commits intomasterfrom
feature/backer-kpis

Conversation

@0xVoronov
Copy link
Copy Markdown
Collaborator

Extends GET /v1/rewards/bakers/{address}/stats with optional cycle / cyclesLimit query parameters and a new kpis object in the response. Enables validator dashboards to show per-cycle and lifetime metrics (rewards, efficiency, shares) without extra round-trips.

Response

  • cycle (int?, optional) — Present when the request was for a single cycle (?cycle=N).
  • cyclesUsed (int) — Number of cycles included in aggregation (1 for single-cycle, otherwise ≤ cyclesLimit).
  • kpis (object?, optional) — Reward-derived KPIs and efficiency summary. Null when the baker has no cycle data.

kpis fields:

  • Rewards: totalIncome, extraRewards, lostRewards, slashedRewards, totalSlashed, blocksBaked, blocksProposed, totalBlockRewards, totalEndorsementRewards, endorsementsMade, endorsementsMissed, expectedDistribution.
  • Efficiency: technicalReliability, monetaryPerformance, fairEfficiency, luckRatio, totalExpectedRewards, totalActualRewards, missedRights.
  • Summary: totalRewards, totalBlockFees, totalRevelationRewards, missedBlocks, missedEndorsements, performanceRate, avgRewardsPerCycle, totalRewardsDelegated, totalRewardsStakedShared, totalRewardsOwnStake, totalEdgeFees, delegatorSharePercent, coStakerSharePercent, validatorSharePercent.

@0xVoronov 0xVoronov self-assigned this Feb 20, 2026
@0xVoronov
Copy link
Copy Markdown
Collaborator Author

0xVoronov commented Feb 20, 2026

Local benchmarks

Before changes

Test 1

STATISTICS
Total requests: 4500 (bakers=30, rounds=150)
Success (2xx): 4500
Failed: 0
Wall-clock time: 4.03s
Response time (ms): min=1.9 max=117.1 avg=7.9
Median (p50): 6.5ms
p95: 16.0ms
p99: 25.7ms

Test 2

STATISTICS
Total requests: 4500 (bakers=30, rounds=150)
Success (2xx): 4500
Failed: 0
Wall-clock time: 4.02s
Response time (ms): min=1.7 max=81.8 avg=7.8
Median (p50): 6.7ms
p95: 16.1ms
p99: 27.0ms


After changes

Without Response Cache implementation

STATISTICS
Total requests: 4500 (bakers=30, rounds=150)
Success (2xx): 4500
Failed: 0
Wall-clock time: 8.17s
Response time (ms): min=3.1 max=129.4 avg=16.1
Median (p50): 14.2ms
p95: 27.1ms
p99: 79.2ms

With Response Cache implementation

STATISTICS
Total requests: 4500 (bakers=30, rounds=150)
Success (2xx): 4500
Failed: 0
Wall-clock time: 4.77s
Response time (ms): min=0.9 max=90.0 avg=9.1
Median (p50): 8.5ms
p95: 17.1ms
p99: 45.7ms

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Feb 23, 2026

Deploying mvkt-atlasnet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5d6c1d5
Status: ✅  Deploy successful!
Preview URL: https://7719ae9f.mvkt-atlasnet.pages.dev
Branch Preview URL: https://feature-backer-kpis.mvkt-atlasnet.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Feb 23, 2026

Deploying mvkt-mainnet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5d6c1d5
Status: ✅  Deploy successful!
Preview URL: https://1d854eb7.mvkt.pages.dev
Branch Preview URL: https://feature-backer-kpis.mvkt.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Feb 23, 2026

Deploying mvkt-basenet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5d6c1d5
Status: ✅  Deploy successful!
Preview URL: https://883aad19.mvkt-basenet.pages.dev
Branch Preview URL: https://feature-backer-kpis.mvkt-basenet.pages.dev

View logs

@0xVoronov
Copy link
Copy Markdown
Collaborator Author

Passed! - Failed: 0, Passed: 75, Skipped: 0, Total: 75, Duration: 2 s @TristanAllaire

};
}

async Task<BakerStatsTotals> GetBakerStatsTotals(int bakerId, int? cycle, int cyclesLimit)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the SQL query, I also considered using a materialized view, something like a snapshot of cycle data for a particular validator. However, that introduces some overhead because the data must remain strictly consistent when a cycle changes. Also, we don’t only query all cycles; sometimes we query a specific cycle, and storing snapshots for everything would be too much data. I don’t think it’s necessary right now.

SUM("BlockRewardsStakedShared" + "EndorsementRewardsStakedShared") AS "TotalRewardsStakedShared",
SUM("BlockRewardsStakedOwn" + "EndorsementRewardsStakedOwn") AS "TotalRewardsOwnStake",
SUM("BlockRewardsStakedEdge" + "EndorsementRewardsStakedEdge") AS "TotalEdgeFees"
""";
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also concluded that it’s faster to aggregate the data at the SQL level rather than pulling it into the method and calculating it with loops:

  1. We already filter efficiently in the query using WHERE "BakerId" = @bakerId ORDER BY "Cycle" DESC.
  2. This reduces load on both CPU and GC on the application side.

public DalPublishCommitmentCommit(ProtocolHandler protocol) : base(protocol) { }

public async Task Apply(Block block, JsonElement op, JsonElement content)
public new async Task Apply(Block block, JsonElement op, JsonElement content)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please detail both changes? Are they needed?

{
public BlockCommit(ProtocolHandler protocol) : base(protocol) { }

public async Task ApplyRewards(JsonElement rawBlock)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain this change? Is it needed?

}

async Task<List<MvktQuote>?> GetQuotes(DateTime from, DateTime to)
async Task<List<MvktQuote>> GetQuotes(DateTime from, DateTime to)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain this change? Is it needed?

Logger = logger;
}

public async Task Init()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the changes in this file? Are they needed?

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Mar 4, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@0xVoronov
Copy link
Copy Markdown
Collaborator Author

This logic will be moved to the mvkt-bff service. @TristanAllaire

@0xVoronov 0xVoronov closed this Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants