Skip to content

feat: finality calculator#6785

Merged
hanabi1224 merged 5 commits intomainfrom
hm/finality-calculator
Mar 25, 2026
Merged

feat: finality calculator#6785
hanabi1224 merged 5 commits intomainfrom
hm/finality-calculator

Conversation

@hanabi1224
Copy link
Copy Markdown
Contributor

@hanabi1224 hanabi1224 commented Mar 24, 2026

Summary of changes

Changes introduced in this pull request:

Reference issue to close (if applicable)

Closes #6767

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Outside contributions

  • I have read and agree to the CONTRIBUTING document.
  • I have read and agree to the AI Policy document. I understand that failure to comply with the guidelines will lead to rejection of the pull request.

Summary by CodeRabbit

  • New Features

    • Added an EC finality probability calculator with Skellam distribution support to evaluate reorg risk and find safe finality depths.
  • Tests

    • Added comprehensive unit and integration tests validating finality math against deterministic reference data and numeric tolerances.
  • Chores

    • Updated project manifest with new dependencies and expanded the project dictionary with two new terms.

@hanabi1224 hanabi1224 marked this pull request as ready for review March 24, 2026 15:25
@hanabi1224 hanabi1224 requested a review from a team as a code owner March 24, 2026 15:25
@hanabi1224 hanabi1224 requested review from LesnyRumcajs and sudo-shashank and removed request for a team March 24, 2026 15:25
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 24, 2026

Walkthrough

Adds the FRC-0089 EC finality calculator: new calculator module (Poisson + Skellam math), Skellam PMF helper, comprehensive tests, Cargo dependency additions, and integration into the chain module. (≤50 words)

Changes

Cohort / File(s) Summary
Configuration & Dependencies
\.config/forest.dic, Cargo.toml
Updated dictionary (PMF, Skellam) and added dependencies libm = "0.2", puruspe = "0.4", plus dev-dep all_asserts = "2".
EC Finality Calculator Core
src/chain/ec_finality/calculator/mod.rs, src/chain/ec_finality/calculator/skellam.rs
New FRC-0089 implementation: public constants, calc_validator_prob and find_threshold_depth, Poisson helpers, Skellam PMF (Bessel-based), truncation/renormalization, and error/context handling.
Calculator Tests
src/chain/ec_finality/calculator/tests.rs
Comprehensive tests validating outputs against Python reference vectors, edge cases, and helper functions.
Module Integration
src/chain/ec_finality/mod.rs, src/chain/mod.rs
Adds ec_finality module and wires calculator submodule into the chain module tree.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant Calc as "calc_validator_prob"
    participant Poisson as "Poisson Helpers"
    participant Skellam as "Skellam PMF"
    participant Normalize as "Truncate & Normalize"
    participant Aggregate as "Cumulative Aggregation"

    Client->>Calc: call(chain, finality, blocks_per_epoch, byzantine_fraction, current_epoch, target_epoch)
    activate Calc

    Calc->>Poisson: compute L (adversarial lead) and B (settlement window) distributions
    Poisson-->>Calc: L, B arrays

    Calc->>Skellam: compute M (future advantage) via Skellam PMF
    Skellam-->>Calc: M array

    Calc->>Normalize: truncate & renormalize L, B, M distributions
    Normalize-->>Calc: normalized distributions

    Calc->>Aggregate: nested cumulative sums / convolution-like aggregation
    Aggregate-->>Calc: upper-bound reorg probability (clamped to ≤1.0)

    Calc-->>Client: Result<f64> (probability)
    deactivate Calc
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Suggested reviewers

  • akaladarshi
  • LesnyRumcajs
  • sudo-shashank
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: finality calculator' accurately summarizes the main change—implementation of an EC finality calculator as specified in FRC-0089.
Linked Issues check ✅ Passed The PR implements the EC finality calculator per FRC-0089 [#6767], adding core functions, constants, tests, and documentation matching specification requirements.
Out of Scope Changes check ✅ Passed All changes are scoped to the EC finality calculator implementation; dependency updates (libm, puruspe) and dictionary additions are necessary supporting changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hm/finality-calculator
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch hm/finality-calculator

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/chain/ec_finality/calculator/mod.rs`:
- Around line 223-269: The bisection using (mut low, mut high) with
calc_validator_prob is unsound because calc_validator_prob(depth) is not
strictly monotone; replace the binary search in this function with a forward
linear scan from low = BISECT_LOW (clamped by current_epoch) up to high =
BISECT_HIGH.min(current_epoch), inclusive, calling calc_validator_prob for each
depth (using current_epoch - depth) and return the first depth where prob <
guarantee, otherwise return -1; also remove the early return on low >= high and
ensure the single-depth case (low == high) is checked rather than rejected.
- Around line 62-64: The code truncates blocks_per_epoch by using an integer
cast when computing max_k_b, shrinking support for non-integer block rates;
update the computation to perform the arithmetic in f64 and use ceil() before
casting to usize (e.g., compute ((current_epoch - target_epoch) as f64 *
blocks_per_epoch).ceil() as usize) and apply the same ceil-based fix at the
other identical location where blocks_per_epoch is cast to an integer; keep the
variable names (max_k_b, current_epoch, target_epoch, blocks_per_epoch) to
locate and replace the truncating cast.

In `@src/chain/ec_finality/calculator/skellam.rs`:
- Around line 20-25: The guard in skellam_pmf incorrectly treats mu1==0 or
mu2==0 as invalid; instead handle degenerate Poisson branches explicitly in
skellam_pmf (and the similar logic around lines 95-100) so only negative or
non-finite mus return NaN. Concretely: keep the NaN checks for mu1 or mu2 being
negative or non-finite, but add branches: if mu1==0.0 && mu2==0.0 return 1.0 if
k==0.0 else 0.0; if mu1==0.0 compute the Poisson PMF for N2 with n = -k (integer
check) and return that probability; if mu2==0.0 compute the Poisson PMF for N1
with n = k (integer check) and return that probability. Use or add a helper
poisson_pmf(n: u64, mu: f64) to avoid duplicating formulas and ensure
integer-ness of k before mapping to n.

In `@src/chain/ec_finality/mod.rs`:
- Line 4: The calculator submodule (calculator) is declared but its API isn't
exposed; update this module to publicly re-export the calculator API (e.g.,
expose the module and/or its public symbols from ec_finality by adding a pub use
or pub mod re-export for calculator and selectively pub use the
functions/constants you need such as the calculator types/constants and
functions referenced) and also export the ec_finality module from the parent
chain module (add a public re-export of ec_finality or its key symbols in the
parent module so external code can reach calculator via
ec_finality::calculator); ensure you reference the existing module name
calculator and the enclosing module ec_finality when adding the re-exports.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2b369bdb-6006-4463-9220-15b20ac58dc3

📥 Commits

Reviewing files that changed from the base of the PR and between 7868455 and c8313ee.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • .config/forest.dic
  • Cargo.toml
  • src/chain/ec_finality/calculator/mod.rs
  • src/chain/ec_finality/calculator/skellam.rs
  • src/chain/ec_finality/calculator/tests.rs
  • src/chain/ec_finality/mod.rs
  • src/chain/mod.rs

Comment thread src/chain/ec_finality/calculator/mod.rs
Comment thread src/chain/ec_finality/calculator/mod.rs
Comment thread src/chain/ec_finality/calculator/skellam.rs
Comment thread src/chain/ec_finality/mod.rs
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 93.10345% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.68%. Comparing base (7868455) to head (ba0c4cd).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/chain/ec_finality/calculator/mod.rs 92.15% 4 Missing and 12 partials ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/chain/ec_finality/calculator/skellam.rs 100.00% <100.00%> (ø)
src/chain/mod.rs 75.00% <ø> (ø)
src/chain/ec_finality/calculator/mod.rs 92.15% <92.15%> (ø)

... and 4 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7868455...ba0c4cd. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/chain/ec_finality/calculator/mod.rs`:
- Line 60: Rename the constant NELIGIBLE_THRESHOLD to NEGLIGIBLE_THRESHOLD in
the declaration and update every usage in this module to the new name (replace
all occurrences of NELIGIBLE_THRESHOLD with NEGLIGIBLE_THRESHOLD) so the
identifier spelling is correct and references compile; ensure any unit tests or
internal matches that reference the old name are updated as well.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f3556281-c34d-4dd8-b25f-9e60b6bd5189

📥 Commits

Reviewing files that changed from the base of the PR and between c8313ee and 38c545b.

📒 Files selected for processing (1)
  • src/chain/ec_finality/calculator/mod.rs

Comment thread src/chain/ec_finality/calculator/mod.rs Outdated
@LesnyRumcajs
Copy link
Copy Markdown
Member

@hanabi1224 I think it should be relatively easy to cover the remaining LoC with tests; those are some edge cases, but easily constructible.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/chain/ec_finality/calculator/tests.rs (1)

223-227: Add zero-length chain case to complete short-input coverage.

The short-chain parameterization currently starts at length 1. Adding length 0 would guard against accidental empty-slice regressions in find_threshold_depth.

Proposed test tweak
 #[rstest]
+#[case(0)]
 #[case(4)]
 #[case(3)]
 #[case(2)]
 #[case(1)]
 fn test_find_threshold_depth_too_short_chain(#[case] chain_len: usize) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/chain/ec_finality/calculator/tests.rs` around lines 223 - 227, Add a
zero-length case to the parameterized short-chain test by adding #[case(0)] to
the test_find_threshold_depth_too_short_chain parameterization so the test
invokes find_threshold_depth with chain_len == 0; update any test setup inside
test_find_threshold_depth_too_short_chain that constructs the slice/vector for
the chain (used by find_threshold_depth) to correctly create an empty slice when
chain_len is 0 so the test asserts the expected behavior for empty input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/chain/ec_finality/calculator/tests.rs`:
- Around line 223-227: Add a zero-length case to the parameterized short-chain
test by adding #[case(0)] to the test_find_threshold_depth_too_short_chain
parameterization so the test invokes find_threshold_depth with chain_len == 0;
update any test setup inside test_find_threshold_depth_too_short_chain that
constructs the slice/vector for the chain (used by find_threshold_depth) to
correctly create an empty slice when chain_len is 0 so the test asserts the
expected behavior for empty input.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1def13c3-df20-416d-990b-96afa74494ce

📥 Commits

Reviewing files that changed from the base of the PR and between 0eafeee and ba0c4cd.

📒 Files selected for processing (2)
  • src/chain/ec_finality/calculator/skellam.rs
  • src/chain/ec_finality/calculator/tests.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/chain/ec_finality/calculator/skellam.rs

Copy link
Copy Markdown
Member

@LesnyRumcajs LesnyRumcajs left a comment

Choose a reason for hiding this comment

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

I believe in this math and do not believe in God. In both cases, I might be wrong.

@hanabi1224
Copy link
Copy Markdown
Contributor Author

hanabi1224 commented Mar 25, 2026

I think it should be relatively easy to cover the remaining LoC with tests; those are some edge cases, but easily constructible.

@LesnyRumcajs all edge cases are now covered. 4 left missing lines are workaround for slice indexing clippy warnings, which cannot be tested as they are infallible

@hanabi1224 hanabi1224 enabled auto-merge March 25, 2026 08:38
@hanabi1224 hanabi1224 added this pull request to the merge queue Mar 25, 2026
Merged via the queue into main with commit a05a3c3 Mar 25, 2026
36 checks passed
@hanabi1224 hanabi1224 deleted the hm/finality-calculator branch March 25, 2026 09:15
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.

feat: implement FRC-0089 EC finality calculator

2 participants