Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Cache lifetime-constant Beacon Node API responses

オープン
#481 コメント 1 件 リアクション 0 件 担当者 1 名 GitHub で見る

@varex83 がすでに取り組んでいます。

2026年9月3日 から。

評価

この issue はまだ評価されていません。

説明

enhancement

Summary

Several Beacon Node API responses are constant for the lifetime of the client (genesis data, the chain spec, slots-per-epoch / slot duration, the deposit contract, …) yet Pluto re-fetches them over HTTP on every call. We should cache these once and reuse them, while being conservative: only cache what is genuinely immutable, and when in doubt make the extra call rather than risk serving stale data.

This came out of the core/scheduler review (PR #466). SchedulerActor::get_duty_definition issues a live fetch_slots_config() round-trip on every query just to derive slots_per_epoch:

slots_per_epoch never changes, so this is a per-call beacon round-trip on a hot path that blocks the actor. A general cache for lifetime-constant responses fixes this class of problem rather than just the one call site.

Where caching should live

Almost all the constant-data helpers funnel through two private base fetchers in extensions.rs, which makes them the natural memoization points:

Memoizing just these two makes every downstream helper (fetch_genesis_time, fetch_slots_config, fetch_fork_config, fetch_domain*, …) cheap.

Note that EthBeaconNodeApiClient itself is an OpenAPI-generated struct, so a cache field can't simply be added to it without changing the generator:

A caching layer (or a small wrapper type) is therefore preferable. There is already precedent for this pattern in the crate — the epoch-aware ValidatorCache:

Reference: what Charon caches

Charon delegates this caching to go-eth2-client. Its eth2wrap code generator marks each endpoint with a Latency flag; Latency: false means "this endpoint is cached in go-eth2-client" (the generator literally emits that comment):

The endpoints Charon/go-eth2-client cache (Latency: false) are: BeaconBlockRoot, DepositContract, Domain, Genesis, NodePeerCount, NodeVersion, SlotDuration, SlotsPerEpoch, Spec. Notably ForkSchedule and Fork are NOT cached by Charon (Latency: true).

Category 1 — cache these (lifetime-constant; Charon caches them too)

Data Pluto method Backing endpoint
Genesis (time, validators root, genesis fork version) fetch_genesis_data → fetch_genesis_time, fetch_genesis_validators_root, fetch_genesis_fork_version get_genesis
Chain spec fetch_spec_data / fetch_spec get_spec
Slot duration & slots-per-epoch fetch_slots_config derived from spec
Signing domains fetch_domain_type, fetch_genesis_domain, fetch_domain derived from spec + genesis
Deposit contract (address, chain id) — (not yet wrapped) get_deposit_contract
Beacon node version — (not yet wrapped) get_node_version

Caching fetch_spec_data and fetch_genesis_data covers the whole first four rows at once.

Category 2 — semantically constant-ish, but do NOT cache (err on the side of caution)

Data Pluto method Why not
Fork schedule fetch_fork_config → get_fork_schedule Future forks can be (re)scheduled. Charon explicitly does not cache this (Latency: true). In Pluto it is derived from the spec, so it rides along with the spec cache only as far as the spec itself; treat new forks as a reason to re-read.
State fork get_state_fork Per-state / per-fork-epoch, not lifetime-constant. Charon does not cache it.
Peer count get_peer_count go-eth2-client marks it Latency: false, but it is semantically dynamic — do not cache in Pluto.
Block root get_block_root Cached by go-eth2-client keyed by block_id; a single value cache is wrong here. Out of scope.

Everything else (duties, validator state, syncing status, head/finality, pools, block production/submission, rewards, …) is dynamic and must not be cached.

Proposed scope

  1. Introduce a memoization layer for the two base fetchers (fetch_spec_data, fetch_genesis_data) so all constant-data helpers become effectively free after the first call.
  2. Use it to make slots_per_epoch available synchronously to the scheduler, removing the per-call fetch_slots_config() round-trip at scheduler.rs#L341.
  3. Optionally extend the same mechanism to get_deposit_contract and get_node_version if/when they get high-level wrappers.
  4. Leave Category 2 endpoints uncached.
主要言語
Rust
スター
8
フォーク
5
平均マージ
4日 18時間
マージ済み PR(30日)
4

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

NethermindEth/pluto のほかの issue

NethermindEth/pluto の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。