Skip to content

Conversation

@gonzalezzfelipe
Copy link
Contributor

@gonzalezzfelipe gonzalezzfelipe commented Dec 22, 2025

Summary by CodeRabbit

New Features

  • Added support for tracking and managing pool delegator retirement events, with proper preservation of retired pool information in account states for fallback scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Walkthrough

This PR introduces pool delegator retirement tracking by adding a new PoolDelegatorRetire delta entity, extending AccountState with a retired_pool field, and integrating boundary processing logic to emit retirement deltas when delegated pools enter the retiring state.

Changes

Cohort / File(s) Summary
New PoolDelegatorRetire Delta
crates/cardano/src/ewrap/drops.rs
Introduces PoolDelegatorRetire struct implementing EntityDelta for AccountState. Stores delegator, epoch, and previous pool delegation. Implements constructor new(), key(), and apply() to schedule pool as NotDelegated and record undo state. Integrates into boundary visitor to queue retirement deltas for delegators when their pools enter retiring state.
AccountState Model Extension
crates/cardano/src/model.rs
Adds retired_pool: Option<PoolHash> field to AccountState with CBOR tag. Imports PoolDelegatorRetire from ewrap::drops. Adds PoolDelegatorRetire(PoolDelegatorRetire) variant to CardanoDelta enum. Registers variant in delta_from! macro and wires handling into key(), apply(), and undo() methods. Initializes retired_pool: None in AccountState::new().
Genesis Initialization
crates/cardano/src/genesis/staking.rs
Updates parse_delegation to initialize retired_pool: None in AccountState struct literal.
Account Delegation State Tracking
crates/cardano/src/roll/accounts.rs
Adds prev_retired_pool: Option<PoolHash> field to StakeDelegation. Imports PoolHash. Updates apply() to preserve current retired_pool into prev_retired_pool before clearing. Updates undo() to restore retired_pool from prev_retired_pool.
Account Model Builder Fallback
crates/minibf/src/routes/accounts.rs
In AccountModelBuilder.into_model, pool_id computation now chains fallback to retired_pool when delegated_pool_at(current_epoch) is None before mapping to bech32 format.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • scarmuega

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'fix(cardano): Handle pool re-registrations' is directly related to the core functionality added. However, the actual changes implement pool delegator retirement tracking and state management, not pool re-registrations. The title suggests fixing re-registration logic, but the code handles retiring delegators from pools. Consider clarifying the title to reflect the actual changes, such as 'fix(cardano): Track retiring pool delegators' or 'fix(cardano): Handle pool delegator retirement tracking' to accurately describe the implementation of delegator retirement state management.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/handle-pool-reregistrations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@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

🧹 Nitpick comments (1)
crates/cardano/src/ewrap/drops.rs (1)

88-91: Potential panic if invariant is violated.

The unreachable! macro will panic if prev_pool is not Some(PoolDelegation::Pool(_)). While this should be guaranteed by the check in visit_account (line 161-162), defensive coding might be preferable to avoid panics in edge cases.

Consider using a warning log instead:

🔎 Proposed defensive handling
-        let Some(PoolDelegation::Pool(pool)) = self.prev_pool else {
-            unreachable!("account delegated to pool")
-        };
-        entity.retired_pool = Some(pool);
+        if let Some(PoolDelegation::Pool(pool)) = self.prev_pool {
+            entity.retired_pool = Some(pool);
+        } else {
+            warn!(delegator=%self.delegator, "expected pool delegation but found {:?}", self.prev_pool);
+        }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a342df and 1923263.

📒 Files selected for processing (5)
  • crates/cardano/src/ewrap/drops.rs
  • crates/cardano/src/genesis/staking.rs
  • crates/cardano/src/model.rs
  • crates/cardano/src/roll/accounts.rs
  • crates/minibf/src/routes/accounts.rs
🧰 Additional context used
🧬 Code graph analysis (2)
crates/cardano/src/roll/accounts.rs (1)
crates/cardano/src/model.rs (1)
  • undo (1974-2009)
crates/cardano/src/ewrap/drops.rs (1)
crates/cardano/src/roll/accounts.rs (24)
  • new (28-34)
  • new (119-129)
  • new (177-185)
  • new (233-247)
  • new (293-304)
  • new (381-388)
  • apply (53-64)
  • apply (86-96)
  • apply (140-155)
  • apply (196-210)
  • apply (258-268)
  • apply (315-337)
  • apply (359-363)
  • apply (399-412)
  • apply (437-448)
  • undo (66-68)
  • undo (98-102)
  • undo (157-162)
  • undo (212-217)
  • undo (270-275)
  • undo (339-342)
  • undo (365-369)
  • undo (414-419)
  • undo (450-452)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Check Build
🔇 Additional comments (7)
crates/minibf/src/routes/accounts.rs (1)

96-101: LGTM! Appropriate fallback for retired pool delegation.

The fallback to retired_pool when delegated_pool_at(current_epoch) returns None correctly preserves pool information for accounts whose delegated pool has retired. This ensures API consumers can still identify the pool the account was delegated to.

crates/cardano/src/roll/accounts.rs (1)

165-218: LGTM! Proper undo/redo semantics for retired pool state.

The StakeDelegation delta correctly:

  1. Saves retired_pool before applying (line 203)
  2. Clears retired_pool when applying a new delegation (line 209) - this is correct because a new delegation supersedes the retired state
  3. Restores retired_pool on undo (line 216)

This ensures that chain rollbacks properly restore the retired pool tracking state.

crates/cardano/src/genesis/staking.rs (1)

101-111: LGTM! Correct initialization for genesis accounts.

Initializing retired_pool: None for genesis delegations is correct since these accounts are bootstrapped with active pools, not retired ones.

crates/cardano/src/ewrap/drops.rs (1)

161-165: LGTM! Boundary processing correctly detects retiring pools.

The logic properly checks if the account's delegated pool is in the retiring_pools set and emits a PoolDelegatorRetire delta accordingly.

crates/cardano/src/model.rs (3)

536-539: LGTM! Appropriate field addition with correct CBOR tagging.

The retired_pool field is properly tagged with #[n(7)] following the existing sequential CBOR encoding pattern, and the Option<PoolHash> type correctly represents the optional retired pool state.


543-555: LGTM! Correct initialization in constructor.

The AccountState::new properly initializes retired_pool: None, consistent with the genesis initialization in staking.rs.


1823-1823: LGTM! Complete delta integration.

The PoolDelegatorRetire delta is fully wired into the CardanoDelta enum with:

  • Enum variant (line 1823)
  • delta_from! macro (line 1891)
  • key() dispatch (line 1928)
  • apply() dispatch (line 1966)
  • undo() dispatch (line 2003)

Also applies to: 1891-1891, 1928-1928, 1966-1966, 2003-2003

Comment on lines +94 to +97
fn undo(&self, _entity: &mut Option<AccountState>) {
// todo!()
// Placeholder undo logic. Ensure this does not panic.
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Placeholder undo logic may cause issues during chain rollbacks.

The undo method is not implemented, which could lead to incorrect state after rollbacks. Unlike some other deltas where undo is less critical, PoolDelegatorRetire::apply modifies both entity.pool (via schedule) and entity.retired_pool. If a rollback occurs, these changes won't be reversed.

🔎 Proposed undo implementation
     fn undo(&self, _entity: &mut Option<AccountState>) {
-        // todo!()
-        // Placeholder undo logic. Ensure this does not panic.
+        let Some(entity) = _entity.as_mut() else {
+            warn!(delegator=%self.delegator, "missing account during undo");
+            return;
+        };
+
+        // Restore previous pool delegation
+        entity.pool.reset(self.prev_pool.clone());
+        // Clear the retired_pool since we're undoing the retirement
+        entity.retired_pool = None;
     }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In crates/cardano/src/ewrap/drops.rs around lines 94 to 97, implement undo to
reverse the changes made by PoolDelegatorRetire::apply: remove the scheduled
retirement entry from entity.pool.schedule that matches this delta (epoch and
pool id) and restore entity.retired_pool to its previous state (clear it or set
it back if it equals the pool id and epoch scheduled by this delta). Ensure you
safely handle None entity, only mutate when the pool and retired_pool match the
values set by apply, and avoid panics.

pub credential: StakeCredential,

#[n(7)]
pub retired_pool: Option<PoolHash>,
Copy link
Member

Choose a reason for hiding this comment

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

let's put a cbor default attribute here so that previous snapshots still work regardless of the existence of the new value.

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