Skip to content

refactor(cloner): make post-delegation clone mode exclusive - #1504

Open
snawaz wants to merge 1 commit into
masterfrom
snawaz/clone-mod
Open

refactor(cloner): make post-delegation clone mode exclusive#1504
snawaz wants to merge 1 commit into
masterfrom
snawaz/clone-mod

Conversation

@snawaz

@snawaz snawaz commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

This PR replaces product-state with sum-type (enum) to make the exclusivity semantic obvious. See enum ClonePostDelegationMode that replaces the two-fields with one field.

snawaz commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces ClonePostDelegationMode with None, ExecuteActions, and RescueUndelegate variants, replacing separate delegation-action and undelegation fields on clone requests. Request construction, dependency collection, account cloning, projected ATA handling, subscription updates, and rescue scheduling now use the new mode. Unit and integration tests update fixtures and assertions for the new representation.

Suggested reviewers: dodecahedr0x, gabrielepicco, bzawisto

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch snawaz/clone-mod

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.

@snawaz
snawaz force-pushed the snawaz/clone-mod branch from e0b3bf3 to cae90c6 Compare July 29, 2026 21:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
magicblock-chainlink/src/cloner/mod.rs (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated "plain mode" check derived from two negated predicates instead of a direct accessor.

ClonePostDelegationMode exposes has_actions() and is_rescue_undelegate() but no direct check for the None variant, so both consumer sites reconstruct "is plain/None mode" as !has_actions() && !is_rescue_undelegate(). This duplicates the same 3-term boolean twice verbatim and implicitly relies on the invariant that ExecuteActions never wraps empty actions (only guaranteed by the From<DelegationActions> constructor, not by the type itself, since the variant is public).

  • magicblock-chainlink/src/cloner/mod.rs#L61-80: add pub fn is_none(&self) -> bool { matches!(self, Self::None) } to ClonePostDelegationMode for a direct, invariant-independent check.
  • magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs#L863-865: replace !request.post_delegation_mode.has_actions() && ... && !request.post_delegation_mode.is_rescue_undelegate() with request.post_delegation_mode.is_none() && request.delegated_to_other.is_none().
  • magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs#L1057-1061: apply the same simplification to owned_request.
♻️ Proposed fix
 impl ClonePostDelegationMode {
+    pub fn is_none(&self) -> bool {
+        matches!(self, Self::None)
+    }
+
     pub fn execute_actions(&self) -> Option<&DelegationActions> {
-        let active_delegation_satisfies_request =
-            !request.post_delegation_mode.has_actions()
-                && request.delegated_to_other.is_none()
-                && !request.post_delegation_mode.is_rescue_undelegate();
+        let active_delegation_satisfies_request = request
+            .post_delegation_mode
+            .is_none()
+            && request.delegated_to_other.is_none();
-                    let active_delegation_satisfies_request =
-                        !owned_request.post_delegation_mode.has_actions()
-                            && owned_request.delegated_to_other.is_none()
-                            && !owned_request
-                                .post_delegation_mode
-                                .is_rescue_undelegate();
+                    let active_delegation_satisfies_request = owned_request
+                        .post_delegation_mode
+                        .is_none()
+                        && owned_request.delegated_to_other.is_none();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@magicblock-chainlink/src/cloner/mod.rs` at line 1, Add an `is_none()`
accessor to `ClonePostDelegationMode` using a direct `None` variant match, then
update both plain-mode checks in the fetch-cloner request and owned-request
paths to use `post_delegation_mode.is_none()` alongside
`delegated_to_other.is_none()`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@magicblock-chainlink/src/cloner/mod.rs`:
- Line 1: Add an `is_none()` accessor to `ClonePostDelegationMode` using a
direct `None` variant match, then update both plain-mode checks in the
fetch-cloner request and owned-request paths to use
`post_delegation_mode.is_none()` alongside `delegated_to_other.is_none()`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 76b6b7d0-1316-4ec5-9db7-d9fae0c956b2

📥 Commits

Reviewing files that changed from the base of the PR and between 26e5844 and e0b3bf3.

📒 Files selected for processing (9)
  • magicblock-account-cloner/src/lib.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs
  • magicblock-chainlink/src/cloner/mod.rs
  • magicblock-chainlink/src/testing/cloner_stub.rs
  • test-integration/test-chainlink/src/ixtest_context.rs
  • test-integration/test-chainlink/tests/ix_aml_undelegation.rs

@snawaz
snawaz force-pushed the snawaz/clone-mod branch 3 times, most recently from 8c0cf5e to 98e5168 Compare July 29, 2026 22:27
@snawaz
snawaz force-pushed the snawaz/clone-mod branch from 98e5168 to 325057f Compare July 30, 2026 17:21
@snawaz
snawaz requested a review from Dodecahedr0x July 30, 2026 17:21
@snawaz
snawaz marked this pull request as ready for review July 30, 2026 17:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs (1)

890-909: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract duplicated active_delegation_satisfies_request predicate.

The exact same three-condition check (!post_delegation_mode.has_actions() && delegated_to_other.is_none() && !post_delegation_mode.is_rescue_undelegate()) is computed independently in local_account_satisfies_clone_request and clone_account_with_ownership. Both migrations were done correctly, but keeping the logic in one place avoids a future edit silently diverging between the pre-check and the post-failure reconciliation path.

♻️ Suggested consolidation
+impl AccountCloneRequest {
+    /// True when an actively delegated local copy already satisfies this
+    /// clone request (no pending actions, not delegated elsewhere, no
+    /// rescue-undelegate pending).
+    fn active_delegation_satisfies_request(&self) -> bool {
+        !self.post_delegation_mode.has_actions()
+            && self.delegated_to_other.is_none()
+            && !self.post_delegation_mode.is_rescue_undelegate()
+    }
+}

Then in local_account_satisfies_clone_request:

-        let active_delegation_satisfies_request =
-            !request.post_delegation_mode.has_actions()
-                && request.delegated_to_other.is_none()
-                && !request.post_delegation_mode.is_rescue_undelegate();
+        let active_delegation_satisfies_request =
+            request.active_delegation_satisfies_request();

And in clone_account_with_ownership:

-                    let active_delegation_satisfies_request =
-                        !owned_request.post_delegation_mode.has_actions()
-                            && owned_request.delegated_to_other.is_none()
-                            && !owned_request
-                                .post_delegation_mode
-                                .is_rescue_undelegate();
+                    let active_delegation_satisfies_request =
+                        owned_request.active_delegation_satisfies_request();

Also applies to: 1088-1093

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs` around lines 890 -
909, Extract the duplicated three-condition active-delegation predicate into a
shared helper near the existing clone-request logic, then update both
local_account_satisfies_clone_request and clone_account_with_ownership to call
it. Preserve the current boolean behavior in both pre-check and post-failure
reconciliation paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs`:
- Around line 890-909: Extract the duplicated three-condition active-delegation
predicate into a shared helper near the existing clone-request logic, then
update both local_account_satisfies_clone_request and
clone_account_with_ownership to call it. Preserve the current boolean behavior
in both pre-check and post-failure reconciliation paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ab43e07f-a018-417f-98e9-08eb8a7742f2

📥 Commits

Reviewing files that changed from the base of the PR and between e0b3bf3 and 325057f.

📒 Files selected for processing (9)
  • magicblock-account-cloner/src/lib.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs
  • magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs
  • magicblock-chainlink/src/cloner/mod.rs
  • magicblock-chainlink/src/testing/cloner_stub.rs
  • test-integration/test-chainlink/src/ixtest_context.rs
  • test-integration/test-chainlink/tests/ix_aml_undelegation.rs

vec![],
)]);
request.post_delegation_mode =
ClonePostDelegationMode::from(DelegationActions::from(vec![

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: there could be a impl From<Vec<Instruction>> for ClonePostDelegationMode

ixs.push(Self::schedule_undelegation_ix(request.pubkey));
} else if !actions.is_empty() {
ixs.push(Self::post_delegation_action_ix(request.pubkey, actions));
match &request.post_delegation_mode {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: this and the change above could be merged in a single match

fn small_undelegation_clone_schedules_in_same_tx_without_actions() {
let pubkey = Pubkey::new_unique();
let mut request = request(pubkey, vec![1, 2, 3], vec![action()]);
request.needs_undelegation = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These should also be applied to large accounts

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.

2 participants