Conversation
|
Warning Gemini is experiencing higher than usual traffic and was unable to create the review. Please try again in a few hours by commenting |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the Membership trait and its implementations to use synchronous methods for membership lookups, replacing async_lock::RwLock with parking_lot::RwLock to improve performance and simplify the codebase. The EpochCommittees structure was also reorganized to support these changes. A typo in a panic message was identified and should be corrected.
| panic!( | ||
| "The decided block header's `next_stake_table_hash` does not match the hash \ | ||
| of the stake table we have. This is an unrecoverable error likely due to \ | ||
| issues with the your L1 RPC provider. Decided:\n\n{:?}Actual:\n\n{:?}", |
|
Claude finished @twittner's task in 5m 8s —— View job Code Review: PR #4263 — Use internal locking for epoch memberships
SummaryThis is a significant refactor (~2650 added / ~2590 removed across 84 files) that converts the Architecture & DesignLocking model is well-considered. The doc-comment on
The Code QualityThe refactor is mechanically clean across the 84 files. The task-impl changes consistently replace Concurrency & SafetyTOCTOU windows are documented and intentional. Methods like
TestingThe new concurrency tests in
All tests use Issues FoundTwo minor issues with inline suggestions posted:
One performance suggestion posted inline:
VerdictThis is a well-executed refactor that simplifies the codebase significantly. The locking model is sound, the TOCTOU windows are documented and intentional, and the test coverage for the new concurrency model is strong. The two typo fixes are trivial. Looks good to merge after those are addressed. |
| fn set_first_epoch(&self, epoch: EpochNumber, initial_drb_result: DrbResult) { | ||
| let rand_comm = self | ||
| .randomized_committee(EpochNumber::genesis(), initial_drb_result) | ||
| .expect("committee exist at genesis"); |
There was a problem hiding this comment.
Minor observation: randomized_committee() takes a read lock on inner (line 574), which is released before the write lock on line 1123. This is correct with parking_lot::RwLock, but worth being aware of: between the read and write locks, the genesis committee could theoretically be removed by another writer, causing the .expect() here to panic.
In practice this is safe because state[EpochNumber::genesis()] is populated at construction and never removed. But if that invariant ever changed, this would be a latent issue. The test set_first_epoch_is_atomic validates the current behavior well.
| fn add_drb_result(&self, epoch: EpochNumber, drb: DrbResult) { | ||
| tracing::info!("Adding DRB result {drb:?} to epoch {epoch}"); | ||
| if let Some(committee) = self.randomized_committee(epoch, drb) { | ||
| self.inner | ||
| .write() | ||
| .randomized_committees | ||
| .insert(epoch, committee); | ||
| } | ||
| } |
There was a problem hiding this comment.
Documented TOCTOU window: randomized_committee() acquires and releases a read lock, then add_drb_result acquires a write lock. Between those two, the state entry for epoch could change. The effect is benign (overwrite with slightly stale leader set) and the doc-comment on EpochCommittees explicitly calls out this per-call-snapshot behavior. The concurrent tests cover this well.
No action needed — just confirming this was reviewed and is intentional.
No description provided.