Skip to content

Add GET /lean/v0/fork_choice JSON endpoint to leanSpec#418

Merged
tcoratger merged 3 commits intoleanEthereum:mainfrom
lambdaclass:forkchoice-endpoint
Feb 25, 2026
Merged

Add GET /lean/v0/fork_choice JSON endpoint to leanSpec#418
tcoratger merged 3 commits intoleanEthereum:mainfrom
lambdaclass:forkchoice-endpoint

Conversation

@pablodeymo
Copy link
Contributor

@pablodeymo pablodeymo commented Feb 25, 2026

🗒️ Description

Add GET /lean/v0/fork_choice JSON endpoint to leanSpec, matching the endpoint already available in ethlambda's Rust implementation.

The endpoint returns a snapshot of the fork choice tree:

  • nodes: all blocks at or above the finalized slot, with their root, slot, parent_root, proposer_index, and attestation weight
  • head: current canonical head root
  • justified: latest justified checkpoint (slot + root)
  • finalized: latest finalized checkpoint (slot + root)
  • safe_target: safe target root
  • validator_count: number of validators in the head state

Changes

New compute_block_weights method on Store (store.py): extracts the weight computation loop from _compute_lmd_ghost_head into a public method. Walks backward from each validator's latest head vote, accumulating weight per block above the finalized slot.

New endpoint handler (endpoints/fork_choice.py): follows the same pattern as checkpoints.py. Returns 503 when the store is not initialized.

Route registration (routes.py, endpoints/__init__.py): wires up /lean/v0/fork_choice.

⚠️ Note: This implementation duplicates the logic of weight computation. This should be done in only one place.

Tests:

  • test_server.py: 503 test for the new endpoint (port 15058)
  • test_compute_block_weights.py: genesis-only (empty weights), linear chain (upward accumulation), and multiple attestations (weight stacking)

🔗 Related Issues or PRs

N/A

✅ Checklist

  • Ran tox checks to avoid unnecessary CI fails:
    uvx tox
  • Considered adding appropriate tests for the changes.
  • Considered updating the online docs in the ./docs/ directory.

…e endpoint already available in ethlambdas Rust implementation.
Copy link
Contributor

@ch4r10t33r ch4r10t33r left a comment

Choose a reason for hiding this comment

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

Looks good to me.

Copy link
Collaborator

@tcoratger tcoratger left a comment

Choose a reason for hiding this comment

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

Just left a minor comment for testing, otherwise, looks good to me.

Comment on lines 107 to 125
class TestForkChoiceEndpoint:
"""Tests for the /lean/v0/fork_choice endpoint error handling."""

async def test_returns_503_when_store_not_initialized(self) -> None:
"""Endpoint returns 503 Service Unavailable when store is not set."""
config = ApiServerConfig(port=15058)
server = ApiServer(config=config)

await server.start()

try:
async with httpx.AsyncClient() as client:
response = await client.get("http://127.0.0.1:15058/lean/v0/fork_choice")

assert response.status_code == 503

finally:
server.stop()
await asyncio.sleep(0.1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can't we have a test with a 200 OK code as well to test the validity?

Addresses review feedback requesting a test that validates the endpoint
returns correct fork choice data when the store is initialized.
from_validator_indices expects ValidatorIndices (SSZModel with .data),
not a plain list. This caused an AttributeError in CI.
@tcoratger tcoratger merged commit 154c203 into leanEthereum:main Feb 25, 2026
11 checks passed
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.

3 participants