Skip to content

Conversation

@taco-paco
Copy link
Contributor

@taco-paco taco-paco commented Nov 18, 2025

#636

Summary by CodeRabbit

  • Bug Fixes

    • Undelegation failures are now treated as a distinct, non‑fatal error path with targeted cleanup and retry behavior.
    • Error mapping refined to preserve instruction-specific outcomes (commit/action/undelegate) and improve granular logging.
  • Tests

    • Added integration tests for undelegation error parsing and recovery.
    • Test helpers now accept optional labels and produce realistic account payloads to simulate undelegation scenarios.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

📝 Walkthrough

Walkthrough

Added an UndelegationError variant to executor error enums and mapped undelegate instruction failures into it; implemented handle_undelegation_error to truncate a TransactionStrategy at the first Undelegate task and return a cleanup strategy; wired undelegation-aware recovery into single- and two-stage executors (returning cleanup Continue in finalize/patch paths, logging/breaking where appropriate); updated try_from_transaction_error to dispatch on (TaskType, InstructionError) and wrap indexed instruction errors; extended the flexi-counter test program and test utilities to simulate undelegation failures and added tests exercising parsing and recovery.

Changes

Cohort / File(s) Summary
Error variants & mapping
magicblock-committor-service/src/intent_executor/error.rs
Added UndelegationError(#[source] TransactionError, Option<Signature>) to IntentExecutorError and TransactionStrategyExecutionError. Extended try_from_transaction_error to map Undelegate-task InstructionError to UndelegationError, reintroduced an indexed-instruction helper, and refactored dispatch to match on (TaskType, InstructionError) for granular mapping.
Executor core & recovery
magicblock-committor-service/src/intent_executor/mod.rs, .../single_stage_executor.rs, .../two_stage_executor.rs
Added handle_undelegation_error(&self, strategy: &mut TransactionStrategy) -> TransactionStrategy to locate the first Undelegate task and truncate tasks from that point; integrated UndelegationError handling: single-stage and finalize paths return cleanup strategy (Continue), two-stage commit logs and Break in commit path; treated UndelegationError alongside certain non-fatal persist/error flows.
Test program: flexi-counter
test-integration/programs/flexi-counter/src/state.rs, .../processor.rs
Added FAIL_UNDELEGATION_LABEL and FAIL_UNDELEGATION_CODE; processor returns ProgramError::Custom(FAIL_UNDELEGATION_CODE) when a counter's label equals the failure label to simulate undelegation failure.
Test utilities: label propagation
test-integration/test-committor-service/tests/utils/instructions.rs, .../transactions.rs
Added optional label: Option<String> parameter to init_account_and_delegate_ixs and init_and_delegate_account_on_chain, propagated label through initialization helper (defaults when None).
Integration tests updates
test-integration/test-committor-service/tests/test_intent_executor.rs, .../test_ix_commit_local.rs
Updated test helpers and call sites to accept optional label (passing None or Some); added tests for undelegation error parsing and recovery; stabilized some tests with short sleeps; updated account initialization to use serialized FlexiCounter payloads.

Sequence Diagram(s)

sequenceDiagram
    participant Exec as IntentExecutor
    participant Strat as TransactionStrategy
    participant Map as ErrorMapper
    participant Recover as handle_undelegation_error

    Exec->>Strat: execute/send transaction
    Strat-->>Exec: TransactionError (InstructionError @ index)
    Exec->>Map: try_from_transaction_error(tx_err, index)
    Map-->>Exec: TransactionStrategyExecutionError::UndelegationError(tx_err, signature)

    alt Single-stage finalization
        Exec->>Recover: handle_undelegation_error(strategy)
        Recover-->>Exec: Cleanup strategy (tasks before Undelegate)
        Exec->>Exec: Continue with cleanup strategy
    else Two-stage commit path
        Exec-->>Exec: Log unexpected undelegation error and Break
    else Two-stage finalize path
        Exec->>Recover: handle_undelegation_error(strategy)
        Recover-->>Exec: Cleanup strategy
        Exec->>Exec: Continue finalize with cleanup strategy
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Focus: correctness of index→TaskType mapping in try_from_transaction_error, correctness of handle_undelegation_error truncation and preservation of TransactionStrategy metadata, consistency of treating UndelegationError like other non-fatal persist/error outcomes, and test changes (label propagation, failure simulation, sleeps).

Possibly related PRs

Suggested reviewers

  • thlorenz
  • Dodecahedr0x
  • GabrielePicco

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Strip failed undelegations' directly and clearly describes the main objective of the pull request, which adds comprehensive handling for undelegation errors across the codebase by removing failed undelegation tasks from transaction strategies.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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.

@github-actions
Copy link

github-actions bot commented Nov 18, 2025

Manual Deploy Available

You can trigger a manual deploy of this PR branch to testnet:

Deploy to Testnet 🚀

Alternative: Comment /deploy on this PR to trigger deployment directly.

⚠️ Note: Manual deploy requires authorization. Only authorized users can trigger deployments.

Comment updated automatically when the PR is synchronized.

Copy link
Contributor

@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: 5

Caution

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

⚠️ Outside diff range comments (1)
magicblock-committor-service/src/intent_executor/error.rs (1)

110-118: Consider adding a dedicated metrics label for undelegation failures

IntentExecutorError::UndelegationError(_, _) currently falls under the catch‑all "failed" label, while Actions, CPI limit, and CommitID have dedicated labels. For observability and alerting, it may be useful to distinguish undelegation failures as well, e.g.:

    fn value(&self) -> &str {
        match self {
            IntentExecutorError::ActionsError(_, _) => "actions_failed",
            IntentExecutorError::CpiLimitError(_, _) => "cpi_limit_failed",
            IntentExecutorError::CommitIDError(_, _) => "commit_nonce_failed",
+           IntentExecutorError::UndelegationError(_, _) => "undelegation_failed",
            _ => "failed",
        }
    }

This keeps metrics granular as new error classes are introduced.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ded9c50 and 1a094ec.

📒 Files selected for processing (10)
  • magicblock-committor-service/src/intent_executor/error.rs (4 hunks)
  • magicblock-committor-service/src/intent_executor/mod.rs (3 hunks)
  • magicblock-committor-service/src/intent_executor/single_stage_executor.rs (1 hunks)
  • magicblock-committor-service/src/intent_executor/two_stage_executor.rs (2 hunks)
  • test-integration/programs/flexi-counter/src/processor.rs (2 hunks)
  • test-integration/programs/flexi-counter/src/state.rs (1 hunks)
  • test-integration/test-committor-service/tests/test_intent_executor.rs (12 hunks)
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs (2 hunks)
  • test-integration/test-committor-service/tests/utils/instructions.rs (1 hunks)
  • test-integration/test-committor-service/tests/utils/transactions.rs (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • test-integration/test-committor-service/tests/utils/transactions.rs
  • test-integration/programs/flexi-counter/src/state.rs
  • test-integration/test-committor-service/tests/utils/instructions.rs
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
  • test-integration/programs/flexi-counter/src/processor.rs
  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-11-18T08:47:39.681Z
Learnt from: Dodecahedr0x
Repo: magicblock-labs/magicblock-validator PR: 639
File: magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs:158-165
Timestamp: 2025-11-18T08:47:39.681Z
Learning: In magicblock-chainlink tests involving compressed accounts, `set_remote_slot()` sets the slot of the `AccountSharedData`, while `compressed_account_shared_with_owner_and_slot()` sets the slot of the delegation record. These are two different fields and both calls are necessary.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-11-07T13:09:52.253Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.

Applied to files:

  • magicblock-committor-service/src/intent_executor/single_stage_executor.rs
  • test-integration/test-committor-service/tests/test_intent_executor.rs
🧬 Code graph analysis (5)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
test-integration/test-committor-service/tests/utils/instructions.rs (1)
  • init_account_and_delegate_ixs (20-51)
magicblock-committor-service/src/intent_executor/error.rs (2)
magicblock-rpc-client/src/lib.rs (2)
  • error (193-195)
  • signature (82-90)
magicblock-committor-service/src/tasks/args_task.rs (1)
  • task_type (146-153)
test-integration/test-committor-service/tests/test_ix_commit_local.rs (1)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
test-integration/programs/flexi-counter/src/processor.rs (3)
programs/magicblock/src/mutate_accounts/account_mod_data.rs (1)
  • data (137-144)
programs/magicblock/src/magic_context.rs (1)
  • deserialize (18-26)
programs/magicblock/src/task_context.rs (1)
  • deserialize (82-90)
test-integration/test-committor-service/tests/test_intent_executor.rs (2)
test-integration/programs/flexi-counter/src/state.rs (2)
  • pda (34-37)
  • new (16-22)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
⏰ 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: run_make_ci_lint
🔇 Additional comments (15)
magicblock-committor-service/src/intent_executor/single_stage_executor.rs (2)

178-184: LGTM! Consistent error handling pattern.

The new UndelegationError handling follows the same pattern as ActionsError and CommitIDError, correctly patching the strategy for retry and returning cleanup data.


12-13: LGTM! Test constants for undelegation failure simulation.

The constants are appropriately scoped for test purposes and will enable undelegation error path testing.

test-integration/test-committor-service/tests/utils/instructions.rs (1)

20-30: LGTM! Clean parameter addition with safe default.

The optional label parameter is properly handled with a sensible default value.

magicblock-committor-service/src/intent_executor/two_stage_executor.rs (2)

180-184: LGTM! Correct handling of unexpected undelegation in commit phase.

Undelegation should not occur during the commit phase, so treating UndelegationError as unexpected and breaking the flow is architecturally correct.


222-228: LGTM! Proper recoverable error handling in finalize phase.

The UndelegationError handling in the finalize phase correctly patches the strategy and prepares cleanup data for retry, consistent with how ActionsError is handled.

test-integration/test-committor-service/tests/utils/transactions.rs (1)

127-146: LGTM! Clean parameter propagation.

The optional label parameter is properly threaded through the test utility.

test-integration/test-committor-service/tests/test_ix_commit_local.rs (2)

115-116: LGTM! Test updated for new API.

Passing None for the label parameter is correct for this test case.


397-402: LGTM! Test updated for new API.

Passing None for the label parameter is correct for this test case.

magicblock-committor-service/src/intent_executor/mod.rs (3)

450-475: LGTM! Correct implementation of undelegation error recovery.

The method correctly:

  • Locates the first Undelegate task
  • Removes it and all subsequent tasks via drain(position..)
  • Recomputes lookup table keys
  • Returns an empty strategy if no Undelegate task exists

552-553: LGTM! Correct error status mapping.

Treating UndelegationError like CpiLimitError by mapping to None (no status update) is correct since it's a recoverable error that will be retried after patching the strategy.


791-792: LGTM! Good safety note on cache invalidation.

The comment correctly documents that cache reset occurs even when undelegation is removed from the strategy, ensuring safety for subsequent commits.

magicblock-committor-service/src/intent_executor/error.rs (1)

43-44: Undelegation error variants are wired consistently across executor layers

Adding UndelegationError(#[source] TransactionError, Option<Signature>) to both IntentExecutorError and TransactionStrategyExecutionError, and mapping it through from_strategy_execution_error, keeps the shape and provenance of undelegation failures consistent with existing ActionsError / CommitIDError paths. No changes needed here.

Also applies to: 99-102, 126-127

test-integration/test-committor-service/tests/test_intent_executor.rs (2)

38-40: Flexi-counter imports match new undelegation test behavior

Bringing in FlexiCounterInstruction and FAIL_UNDELEGATION_LABEL here lines up with their later usage in failing_undelegate_action and the new undelegation tests. The import structure remains clear and localized; no change needed.


121-121: Optional label is plumbed cleanly through setup_counter and init_and_delegate_account_on_chain

The refactor to:

  • Extend setup_counter to accept label: Option<String> and forward it to init_and_delegate_account_on_chain, and
  • Update all call sites to pass None or Some(FAIL_UNDELEGATION_LABEL.to_string()) explicitly,

is consistent and keeps the intent of each test clear (labeled vs. unlabeled counters). This gives you precise control over when undelegation is supposed to fail without impacting existing scenarios. No changes needed.

Also applies to: 222-222, 283-283, 340-341, 433-433, 483-483, 540-540, 627-627, 822-825, 828-829

test-integration/programs/flexi-counter/src/state.rs (1)

12-13: LGTM for undelegation failure constants

The label and code are clearly named, typed appropriately, and fit well with the flexi-counter test program’s role in simulating undelegation failures. No issues from this file’s perspective.

Comment on lines +448 to +449
/// Handles actions error, stripping away actions
/// Returns [`TransactionStrategy`] to be cleaned up
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix copy-paste error in documentation.

The comment says "Handles actions error, stripping away actions" but this method handles undelegation errors.

Apply this diff:

-    /// Handles actions error, stripping away actions
+    /// Handles undelegation error, stripping away undelegation and subsequent tasks
     /// Returns [`TransactionStrategy`] to be cleaned up
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Handles actions error, stripping away actions
/// Returns [`TransactionStrategy`] to be cleaned up
/// Handles undelegation error, stripping away undelegation and subsequent tasks
/// Returns [`TransactionStrategy`] to be cleaned up
🤖 Prompt for AI Agents
In magicblock-committor-service/src/intent_executor/mod.rs around lines 448 to
449, the doc comment incorrectly states "Handles actions error, stripping away
actions" though the function actually handles undelegation errors; update the
documentation comment to accurately describe that this method handles
undelegation errors (e.g., "Handles undelegation error, stripping away
undelegations") and ensure wording matches the function behavior and terminology
used elsewhere in the module.

Copy link
Contributor

@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

♻️ Duplicate comments (1)
test-integration/test-committor-service/tests/test_intent_executor.rs (1)

380-418: Extend undelegation error recovery test to assert commit-buffer cleanup as well

test_undelegation_error_recovery nicely validates that:

  • An intent whose undelegation is guaranteed to fail (via FAIL_UNDELEGATION_LABEL) still results in Ok from execute.
  • The executor returns ExecutionOutput::SingleStage(_), i.e., recovery happens without switching to a two-stage flow.
  • On-chain state and TableMania refcounts are checked via verify.

However, because verify is called with &HashMap::new() for commit_ids_by_pk, the verify_buffers_cleaned_up step becomes a no‑op here (there are no commit IDs to check against), so this test doesn’t currently assert that commit buffers are actually cleaned up in the undelegation‑failure recovery path.

For symmetry with test_commit_id_error_recovery and the other recovery tests, you could also capture the commit ID for this account and pass it into verify, e.g.:

-    let TestEnv {
-        fixture,
-        intent_executor,
-        task_info_fetcher: _,
-        pre_test_tablemania_state,
-    } = TestEnv::setup().await;
+    let TestEnv {
+        fixture,
+        intent_executor,
+        task_info_fetcher,
+        pre_test_tablemania_state,
+    } = TestEnv::setup().await;
@@
-    verify(
-        &fixture.table_mania,
-        fixture.rpc_client.get_inner(),
-        &HashMap::new(),
-        &pre_test_tablemania_state,
-        &[committed_account],
-    )
-    .await;
+    let commit_ids_by_pk: HashMap<_, _> = [&committed_account]
+        .iter()
+        .map(|el| {
+            (
+                el.pubkey,
+                task_info_fetcher.peek_commit_id(&el.pubkey).unwrap(),
+            )
+        })
+        .collect();
+
+    verify(
+        &fixture.table_mania,
+        fixture.rpc_client.get_inner(),
+        &commit_ids_by_pk,
+        &pre_test_tablemania_state,
+        &[committed_account],
+    )
+    .await;

This would ensure the undelegation‑error recovery path is also covered by the buffer‑cleanup assertions, not just the refcount and data checks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a094ec and 541c1a5.

📒 Files selected for processing (2)
  • magicblock-committor-service/src/intent_executor/error.rs (4 hunks)
  • test-integration/test-committor-service/tests/test_intent_executor.rs (12 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-07T13:09:52.253Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
🧬 Code graph analysis (2)
magicblock-committor-service/src/intent_executor/error.rs (4)
magicblock-rpc-client/src/lib.rs (2)
  • error (193-195)
  • signature (82-90)
magicblock-committor-service/src/tasks/buffer_task.rs (1)
  • task_type (122-126)
magicblock-committor-service/src/tasks/args_task.rs (1)
  • task_type (146-153)
magicblock-committor-service/src/tasks/mod.rs (1)
  • task_type (89-89)
test-integration/test-committor-service/tests/test_intent_executor.rs (5)
magicblock-committor-service/src/tasks/buffer_task.rs (2)
  • instruction (65-86)
  • new (37-45)
magicblock-committor-service/src/tasks/args_task.rs (2)
  • instruction (45-98)
  • new (36-41)
test-integration/programs/flexi-counter/src/state.rs (2)
  • pda (34-37)
  • new (16-22)
test-integration/test-tools/src/conversions.rs (1)
  • err (8-8)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
⏰ 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). (3)
  • GitHub Check: run_make_ci_lint
  • GitHub Check: run_make_ci_test
  • GitHub Check: Build Project
🔇 Additional comments (10)
magicblock-committor-service/src/intent_executor/error.rs (5)

43-44: LGTM! Variant structure is consistent with existing error patterns.

The UndelegationError variant follows the same payload structure as ActionsError and CommitIDError, maintaining consistency in the error hierarchy.


99-102: LGTM! Error mapping is correct.

The passthrough mapping from TransactionStrategyExecutionError::UndelegationError to IntentExecutorError::UndelegationError preserves all context and is consistent with other variant mappings.


110-119: Verify whether UndelegationError should have a dedicated metrics label.

The LabelValue implementation provides specific labels for ActionsError, CpiLimitError, and CommitIDError, but the new UndelegationError variant falls through to the catch-all case returning "failed".

If undelegation failures should be tracked separately for observability, consider adding an explicit case like IntentExecutorError::UndelegationError(_, _) => "undelegation_failed".


126-127: LGTM! Variant structure is consistent.

The UndelegationError variant in TransactionStrategyExecutionError maintains consistency with the corresponding variant in IntentExecutorError and follows established patterns.


165-204: LGTM! Error mapping logic is sound and well-structured.

The refactored error mapping correctly:

  • Handles the instruction offset to account for budget instructions
  • Guards against underflow and out-of-bounds access
  • Maps task-specific failures to appropriate error variants (CommitIDError, ActionsError, UndelegationError)
  • Falls back to returning the original error for unhandled cases

The pattern matching on (task_type, instruction_err) tuples makes the logic clear and maintainable. The comment update on line 165 addresses the past review feedback.

test-integration/test-committor-service/tests/test_intent_executor.rs (5)

37-40: Importing FlexiCounterInstruction and FAIL_UNDELEGATION_LABEL is appropriate for the new failure-path tests

Pulling in FlexiCounterInstruction and FAIL_UNDELEGATION_LABEL from the flexi-counter test program cleanly exposes the knobs you need to drive undelegation failures and base actions from the program itself, instead of hard-coding test-only constants here. This keeps the tests aligned with the on-chain test program and avoids duplication.

Based on learnings


121-121: Consistent use of setup_counter(..., None) simplifies counter initialization across tests

Refactoring the various parsing/recovery tests to go through setup_counter(COUNTER_SIZE, None) centralizes the “plain” counter setup (including delegation and owner fixup) and keeps label-handling logic in one place. This reduces duplication and makes it easy to later tweak how counters are prepared without touching every test.

Also applies to: 222-222, 283-283, 540-540, 627-627


161-208: Undelegation error parsing test mirrors existing patterns; be aware of string/position fragility

The new test_undelegation_error_parsing does a good job of:

  • Using FAIL_UNDELEGATION_LABEL to deterministically trigger an undelegation failure.
  • Verifying that the executor surfaces TransactionStrategyExecutionError::UndelegationError(_, _).
  • Asserting that the formatted error string contains the expected undelegation message.

This matches the existing commit‑ID / actions / CPI parsing tests and gives good coverage of the new error variant. Just note that pinning the full EXPECTED_ERR_MSG (including instruction index and Solana’s error text) is intentionally brittle — any change in transaction layout or upstream error formatting will require updating this literal. If that trade-off is acceptable (as with the other parsing tests), this looks solid.


340-341: Explicit None label at init_and_delegate_account_on_chain call sites keeps intent clear

Updating the init_and_delegate_account_on_chain call sites to pass None for the new label: Option<String> parameter makes it explicit that these scenarios are not using the failure label and should behave like the original “happy path” tests. This keeps the API usage uniform and avoids confusion with the new undelegation-failure scenarios.

Also applies to: 433-433, 483-483


822-829: setup_counter helper cleanly encapsulates counter auth + delegated account preparation

The new setup_counter(counter_bytes, label) helper is a nice improvement:

  • It reuses init_and_delegate_account_on_chain so all counter setup (airdrop, init, realloc, delegate) stays in one place.
  • It returns both the Keypair and the delegated Account, which fits existing test call sites that need to both operate on the account and fund/use the authority.
  • It centralizes the account.owner = program_flexi_counter::id(); fixup, avoiding scattered owner overrides.

This should make future changes to how counters are initialized (or how labels are threaded through) much easier.

Copy link
Contributor

@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

♻️ Duplicate comments (1)
test-integration/test-committor-service/tests/test_intent_executor.rs (1)

382-421: Test validates undelegation recovery; consider verifying commit buffer cleanup.

The test correctly validates that:

  • An intent with a failing undelegation still returns Ok from execute
  • Recovery produces ExecutionOutput::SingleStage
  • Final on-chain state and TableMania refcounts are verified

However, verify is called with an empty commit_ids_by_pk, making the verify_buffers_cleaned_up step a no-op. If undelegation fails after commit operations create buffers, you should capture and verify those buffers are cleaned up during recovery.

To add buffer cleanup verification:

// Before verify, capture commit IDs if they exist
let commit_ids_by_pk: HashMap<_, _> = [&committed_account]
    .iter()
    .filter_map(|el| {
        task_info_fetcher
            .peek_commit_id(&el.pubkey)
            .map(|id| (el.pubkey, id))
    })
    .collect();

tokio::time::sleep(Duration::from_secs(1)).await;
verify(
    &fixture.table_mania,
    fixture.rpc_client.get_inner(),
    &commit_ids_by_pk,  // Instead of HashMap::new()
    &pre_test_tablemania_state,
    &[committed_account],
)
.await;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 541c1a5 and 2684f8d.

📒 Files selected for processing (1)
  • test-integration/test-committor-service/tests/test_intent_executor.rs (17 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-07T13:09:52.253Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
🧬 Code graph analysis (1)
test-integration/test-committor-service/tests/test_intent_executor.rs (2)
test-integration/programs/flexi-counter/src/state.rs (2)
  • pda (34-37)
  • new (16-22)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
🔇 Additional comments (4)
test-integration/test-committor-service/tests/test_intent_executor.rs (4)

38-39: LGTM! Test constant import is appropriate.

The addition of FAIL_UNDELEGATION_LABEL from the flexi-counter test contract enables the new undelegation failure scenarios. This is a clean test-only addition.


121-121: LGTM! Call sites correctly updated for optional label parameter.

All existing calls to setup_counter have been consistently updated to pass None for the new optional label parameter, maintaining backward compatibility.

Also applies to: 222-222, 283-283, 340-341, 436-436, 488-488, 547-547, 635-635


161-208: LGTM! Undelegation error parsing test correctly validates the new error path.

The test properly:

  • Forces an undelegation failure via FAIL_UNDELEGATION_LABEL
  • Asserts the correct error variant TransactionStrategyExecutionError::UndelegationError
  • Verifies the error message content

Note that EXPECTED_ERR_MSG couples the test to Solana's error formatting and instruction ordering. This is consistent with other tests in the file and acceptable if you're comfortable updating tests when those details change.


831-842: LGTM! Clean extension of test utility function.

The addition of the optional label parameter to setup_counter is well-designed:

  • Uses Option<String> for backward compatibility
  • Properly threads the label through to init_and_delegate_account_on_chain
  • Enables test scenarios that require labeled counters

Copy link
Contributor

@bmuddha bmuddha left a comment

Choose a reason for hiding this comment

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

looks LGTM

Copy link
Contributor

@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

♻️ Duplicate comments (1)
test-integration/test-committor-service/tests/test_intent_executor.rs (1)

383-422: Test validates undelegation error recovery correctly.

The test successfully verifies that when undelegation fails (via FAIL_UNDELEGATION_LABEL), the executor recovers gracefully and produces a SingleStage output. The core behavior is properly tested.

Note: A previous review suggested capturing commit IDs (via task_info_fetcher.peek_commit_id) and passing them to verify() instead of HashMap::new() at line 417, which would enable verification of commit buffer cleanup similar to test_commit_id_error_recovery. This remains an optional enhancement for test coverage symmetry.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1968617 and b319f3d.

📒 Files selected for processing (1)
  • test-integration/test-committor-service/tests/test_intent_executor.rs (17 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-19T09:34:37.917Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: test-integration/test-chainlink/tests/ix_remote_account_provider.rs:62-63
Timestamp: 2025-11-19T09:34:37.917Z
Learning: In test-integration/test-chainlink/tests/ix_remote_account_provider.rs and similar test files, the `_fwd_rx` receiver returned by `init_remote_account_provider()` is intentionally kept alive (but unused) to prevent "receiver dropped" errors on the sender side. The pattern `let (remote_account_provider, _fwd_rx) = init_remote_account_provider().await;` should NOT be changed to `let (remote_account_provider, _) = ...` because dropping the receiver would cause send() operations to fail.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-07T13:09:52.253Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-07T14:20:31.457Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs:457-495
Timestamp: 2025-11-07T14:20:31.457Z
Learning: In magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs, the unsubscribe closure returned by PubSubConnection::account_subscribe(...) resolves to () (unit), not a Result. Downstream code should not attempt to inspect an unsubscribe result and can optionally wrap it in a timeout to guard against hangs.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
🧬 Code graph analysis (1)
test-integration/test-committor-service/tests/test_intent_executor.rs (5)
magicblock-committor-service/src/tasks/buffer_task.rs (2)
  • instruction (65-86)
  • new (37-45)
magicblock-committor-service/src/tasks/args_task.rs (2)
  • instruction (45-98)
  • new (36-41)
test-integration/programs/flexi-counter/src/state.rs (2)
  • pda (34-37)
  • new (16-22)
test-integration/test-tools/src/conversions.rs (1)
  • err (8-8)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
⏰ 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). (3)
  • GitHub Check: run_make_ci_test
  • GitHub Check: Build Project
  • GitHub Check: run_make_ci_lint
🔇 Additional comments (2)
test-integration/test-committor-service/tests/test_intent_executor.rs (2)

38-40: Import of test constant looks good.

The FAIL_UNDELEGATION_LABEL import is correctly added and used in the new undelegation error tests.


121-121: Label parameter propagation implemented correctly.

The setup_counter function signature has been properly updated to accept an optional label parameter, and all call sites have been consistently updated to pass None where the label is not needed. The new undelegation error tests correctly pass Some(FAIL_UNDELEGATION_LABEL.to_string()) to trigger the failure condition.

Also applies to: 223-223, 284-284, 341-342, 437-437, 489-489, 548-548, 636-636, 832-843

Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 438c527 and ff9d2a5.

📒 Files selected for processing (1)
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs (4 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-11-19T09:34:37.917Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: test-integration/test-chainlink/tests/ix_remote_account_provider.rs:62-63
Timestamp: 2025-11-19T09:34:37.917Z
Learning: In test-integration/test-chainlink/tests/ix_remote_account_provider.rs and similar test files, the `_fwd_rx` receiver returned by `init_remote_account_provider()` is intentionally kept alive (but unused) to prevent "receiver dropped" errors on the sender side. The pattern `let (remote_account_provider, _fwd_rx) = init_remote_account_provider().await;` should NOT be changed to `let (remote_account_provider, _) = ...` because dropping the receiver would cause send() operations to fail.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-11-18T08:47:39.702Z
Learnt from: Dodecahedr0x
Repo: magicblock-labs/magicblock-validator PR: 639
File: magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs:158-165
Timestamp: 2025-11-18T08:47:39.702Z
Learning: In magicblock-chainlink tests involving compressed accounts, `set_remote_slot()` sets the slot of the `AccountSharedData`, while `compressed_account_shared_with_owner_and_slot()` sets the slot of the delegation record. These are two different fields and both calls are necessary.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-10-21T13:06:38.900Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/http/get_program_accounts.rs:17-25
Timestamp: 2025-10-21T13:06:38.900Z
Learning: The magicblock validator does not support ledger forking, so commitment-based state queries (processed/confirmed/finalized) are not applicable. RPC methods can safely ignore commitment and minContextSlot parameters from Solana RPC config objects.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
🧬 Code graph analysis (1)
test-integration/test-committor-service/tests/test_ix_commit_local.rs (1)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
⏰ 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). (3)
  • GitHub Check: Build Project
  • GitHub Check: run_make_ci_test
  • GitHub Check: run_make_ci_lint
🔇 Additional comments (2)
test-integration/test-committor-service/tests/test_ix_commit_local.rs (2)

7-7: LGTM: Imports support the new serialized account data initialization.

The borsh::to_vec and FlexiCounter imports are correctly added to support serializing realistic account state for the tests.

Also applies to: 22-22


117-128: Account initialization correctly serializes FlexiCounter state.

The code change is correct and follows established patterns across the test suite. The function signature of init_and_delegate_account_on_chain accepts label: Option<String> as its third parameter, so passing None is valid. The FlexiCounter serialization approach (create struct, serialize with to_vec(), resize to match byte length) is consistent with usage throughout all integration tests including test_intent_executor.rs, test_schedule_intent.rs, and test_ledger_restore.rs. The test data with count=101, updates=0, label="Counter" is properly initialized and follows the standard pattern.

Comment on lines +407 to 415
let (pda, mut pda_acc) = init_and_delegate_account_on_chain(
&counter_auth,
bytes as u64,
None,
)
.await;

pda_acc.owner = program_flexi_counter::id();
pda_acc.data = vec![0u8; bytes];
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Inconsistent account data initialization between single and multiple account paths.

In the multiple account path, account data is initialized as zeroed bytes (vec![0u8; bytes]), while the single account path creates a properly serialized FlexiCounter. This inconsistency could lead to different test behaviors:

  • Single account tests (lines 120-128): Use serialized FlexiCounter with label="Counter", updates=0, count=101
  • Multiple account tests (lines 414-415): Use zeroed bytes without any FlexiCounter structure

Consider aligning both paths to use the same initialization pattern for consistency:

+            let counter = FlexiCounter {
+                label: "Counter".to_string(),
+                updates: 0,
+                count: 0,
+            };
+            let mut data = to_vec(&counter).unwrap();
+            data.resize(bytes, 0);
+            pda_acc.data = data;
             pda_acc.owner = program_flexi_counter::id();
-            pda_acc.data = vec![0u8; bytes];

If the zeroed bytes are intentional for testing different scenarios, consider adding a comment explaining the rationale.

🤖 Prompt for AI Agents
In test-integration/test-committor-service/tests/test_ix_commit_local.rs around
lines 407 to 415, the multiple-account path initializes pda_acc.data with zeroed
bytes while the single-account path uses a properly serialized FlexiCounter
(label="Counter", updates=0, count=101), causing inconsistent test setup; update
the multiple-account path to serialize and assign the same FlexiCounter
structure to pda_acc.data (or, if zeroed bytes are intentional, add a clear
comment explaining why this different initialization is required) so both paths
use consistent account data initialization.

@taco-paco taco-paco force-pushed the feat/base-layer-ix/strip-failed-undelegation branch from ff9d2a5 to 150554e Compare November 22, 2025 11:15
Copy link
Contributor

@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

♻️ Duplicate comments (5)
magicblock-committor-service/src/intent_executor/error.rs (1)

186-187: Simplify the error reconstruction.

The pattern match already binds instruction_err to InstructionError::Custom(NONCE_OUT_OF_ORDER), so reconstructing it is redundant. This mirrors the Action and Undelegate branches and avoids unnecessary reconstruction.

Apply this diff:

-                        tx_err_helper(InstructionError::Custom(
-                            NONCE_OUT_OF_ORDER,
-                        )),
+                        tx_err_helper(instruction_err),
magicblock-committor-service/src/intent_executor/mod.rs (1)

448-449: Fix copy-paste error in documentation.

The comment says "Handles actions error, stripping away actions" but this method handles undelegation errors.

Apply this diff:

-    /// Handles actions error, stripping away actions
+    /// Handles undelegation error, stripping away undelegation and subsequent tasks
     /// Returns [`TransactionStrategy`] to be cleaned up
test-integration/test-committor-service/tests/test_ix_commit_local.rs (1)

407-415: Inconsistent account data initialization between paths persists.

The multiple-account path still initializes account data with zeroed bytes (vec![0u8; bytes]) while the single-account path now uses a properly serialized FlexiCounter (lines 120-128). This inconsistency could lead to different test behaviors and reduces test realism.

Consider applying the same initialization pattern as the single-account path:

+            let counter = FlexiCounter {
+                label: "Counter".to_string(),
+                updates: 0,
+                count: 0,
+            };
+            let mut data = to_vec(&counter).unwrap();
+            data.resize(bytes, 0);
+            pda_acc.data = data;
             pda_acc.owner = program_flexi_counter::id();
-            pda_acc.data = vec![0u8; bytes];

If zeroed bytes are intentional for testing different scenarios, add a comment explaining the rationale.

test-integration/test-committor-service/tests/test_intent_executor.rs (2)

382-421: Recovery test passes empty commit IDs map, skipping buffer cleanup verification.

The test correctly validates that undelegation error recovery succeeds and produces SingleStage output. However, passing an empty HashMap to verify (line 416) causes verify_buffers_cleaned_up to skip assertions.

For symmetry with other recovery tests, consider capturing commit IDs before verification:

+    let commit_ids_by_pk: HashMap<_, _> = [&committed_account]
+        .iter()
+        .map(|el| {
+            (
+                el.pubkey,
+                task_info_fetcher.peek_commit_id(&el.pubkey).unwrap(),
+            )
+        })
+        .collect();
+
     tokio::time::sleep(Duration::from_secs(1)).await;
     verify(
         &fixture.table_mania,
         fixture.rpc_client.get_inner(),
-        &HashMap::new(),
+        &commit_ids_by_pk,
         &pre_test_tablemania_state,
         &[committed_account],
     )

This would ensure commit buffers are verified as cleaned up after undelegation recovery.


371-371: Fixed delays acceptable for integration tests, but explicit polling would be more robust.

The 1-second sleep delays allow blockchain state to stabilize before verification, which is a common pattern in blockchain integration tests. However, explicit polling for expected state would be more reliable.

Consider implementing a polling helper to wait for state stabilization rather than fixed delays:

async fn wait_for_state_stabilization(
    rpc_client: &Arc<RpcClient>,
    condition: impl Future<Output = bool>,
    max_attempts: u32,
) -> Result<(), String> {
    for _ in 0..max_attempts {
        tokio::time::sleep(Duration::from_millis(100)).await;
        if condition.await {
            return Ok(());
        }
    }
    Err("State did not stabilize".to_string())
}

This would improve test reliability by only waiting as long as necessary.

Also applies to: 412-412, 467-467, 526-526, 599-599, 712-712

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff9d2a5 and 150554e.

⛔ Files ignored due to path filters (1)
  • test-integration/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • magicblock-committor-service/src/intent_executor/error.rs (4 hunks)
  • magicblock-committor-service/src/intent_executor/mod.rs (3 hunks)
  • magicblock-committor-service/src/intent_executor/single_stage_executor.rs (1 hunks)
  • magicblock-committor-service/src/intent_executor/two_stage_executor.rs (2 hunks)
  • test-integration/programs/flexi-counter/src/processor.rs (2 hunks)
  • test-integration/programs/flexi-counter/src/state.rs (1 hunks)
  • test-integration/test-committor-service/tests/test_intent_executor.rs (17 hunks)
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs (4 hunks)
  • test-integration/test-committor-service/tests/utils/instructions.rs (1 hunks)
  • test-integration/test-committor-service/tests/utils/transactions.rs (2 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 661
File: magicblock-committor-service/src/intent_executor/single_stage_executor.rs:20-28
Timestamp: 2025-11-21T10:22:07.520Z
Learning: In magicblock-committor-service's SingleStageExecutor and TwoStageExecutor (single_stage_executor.rs and two_stage_executor.rs), the fields transaction_strategy, junk, and patched_errors are intentionally public because these executors are designed to be used independently outside of the IntentExecutor scope, and callers need access to these execution reports for cleanup and error handling.
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • test-integration/programs/flexi-counter/src/state.rs
  • test-integration/test-committor-service/tests/utils/transactions.rs
  • test-integration/test-committor-service/tests/utils/instructions.rs
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
  • test-integration/programs/flexi-counter/src/processor.rs
  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-21T10:22:07.520Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 661
File: magicblock-committor-service/src/intent_executor/single_stage_executor.rs:20-28
Timestamp: 2025-11-21T10:22:07.520Z
Learning: In magicblock-committor-service's SingleStageExecutor and TwoStageExecutor (single_stage_executor.rs and two_stage_executor.rs), the fields transaction_strategy, junk, and patched_errors are intentionally public because these executors are designed to be used independently outside of the IntentExecutor scope, and callers need access to these execution reports for cleanup and error handling.

Applied to files:

  • magicblock-committor-service/src/intent_executor/two_stage_executor.rs
  • magicblock-committor-service/src/intent_executor/single_stage_executor.rs
  • magicblock-committor-service/src/intent_executor/mod.rs
  • magicblock-committor-service/src/intent_executor/error.rs
  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-07T13:09:52.253Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: test-kit/src/lib.rs:275-0
Timestamp: 2025-11-07T13:09:52.253Z
Learning: In test-kit, the transaction scheduler in ExecutionTestEnv is not expected to shut down during tests. Therefore, using `.unwrap()` in test helper methods like `schedule_transaction` is acceptable and will not cause issues in the test environment.

Applied to files:

  • magicblock-committor-service/src/intent_executor/single_stage_executor.rs
  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-11-19T09:34:37.917Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: test-integration/test-chainlink/tests/ix_remote_account_provider.rs:62-63
Timestamp: 2025-11-19T09:34:37.917Z
Learning: In test-integration/test-chainlink/tests/ix_remote_account_provider.rs and similar test files, the `_fwd_rx` receiver returned by `init_remote_account_provider()` is intentionally kept alive (but unused) to prevent "receiver dropped" errors on the sender side. The pattern `let (remote_account_provider, _fwd_rx) = init_remote_account_provider().await;` should NOT be changed to `let (remote_account_provider, _) = ...` because dropping the receiver would cause send() operations to fail.

Applied to files:

  • test-integration/test-committor-service/tests/utils/transactions.rs
  • test-integration/test-committor-service/tests/utils/instructions.rs
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
  • test-integration/test-committor-service/tests/test_intent_executor.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579

Applied to files:

  • test-integration/test-committor-service/tests/utils/transactions.rs
  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
  • test-integration/programs/flexi-counter/src/processor.rs
📚 Learning: 2025-11-18T08:47:39.702Z
Learnt from: Dodecahedr0x
Repo: magicblock-labs/magicblock-validator PR: 639
File: magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs:158-165
Timestamp: 2025-11-18T08:47:39.702Z
Learning: In magicblock-chainlink tests involving compressed accounts, `set_remote_slot()` sets the slot of the `AccountSharedData`, while `compressed_account_shared_with_owner_and_slot()` sets the slot of the delegation record. These are two different fields and both calls are necessary.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-10-21T13:06:38.900Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/http/get_program_accounts.rs:17-25
Timestamp: 2025-10-21T13:06:38.900Z
Learning: The magicblock validator does not support ledger forking, so commitment-based state queries (processed/confirmed/finalized) are not applicable. RPC methods can safely ignore commitment and minContextSlot parameters from Solana RPC config objects.

Applied to files:

  • test-integration/test-committor-service/tests/test_ix_commit_local.rs
📚 Learning: 2025-11-07T14:20:31.457Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs:457-495
Timestamp: 2025-11-07T14:20:31.457Z
Learning: In magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs, the unsubscribe closure returned by PubSubConnection::account_subscribe(...) resolves to () (unit), not a Result. Downstream code should not attempt to inspect an unsubscribe result and can optionally wrap it in a timeout to guard against hangs.

Applied to files:

  • test-integration/test-committor-service/tests/test_intent_executor.rs
🧬 Code graph analysis (4)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
test-integration/test-committor-service/tests/utils/instructions.rs (1)
  • init_account_and_delegate_ixs (20-51)
magicblock-committor-service/src/intent_executor/error.rs (3)
magicblock-committor-service/src/tasks/buffer_task.rs (1)
  • task_type (122-126)
magicblock-committor-service/src/tasks/args_task.rs (1)
  • task_type (146-153)
magicblock-committor-service/src/tasks/mod.rs (1)
  • task_type (89-89)
test-integration/test-committor-service/tests/test_ix_commit_local.rs (1)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
test-integration/test-committor-service/tests/test_intent_executor.rs (5)
magicblock-committor-service/src/tasks/buffer_task.rs (2)
  • instruction (65-86)
  • new (37-45)
magicblock-committor-service/src/tasks/args_task.rs (2)
  • instruction (45-98)
  • new (36-41)
test-integration/programs/flexi-counter/src/state.rs (2)
  • pda (34-37)
  • new (16-22)
test-integration/test-tools/src/conversions.rs (1)
  • err (8-8)
test-integration/test-committor-service/tests/utils/transactions.rs (1)
  • init_and_delegate_account_on_chain (127-224)
🔇 Additional comments (15)
magicblock-committor-service/src/intent_executor/error.rs (1)

110-119: Verify metrics labeling for UndelegationError.

The LabelValue implementation doesn't explicitly handle UndelegationError, so it falls through to the default "failed" label. While this may be intentional, it's worth confirming that undelegation errors shouldn't have a distinct metric label (e.g., "undelegation_failed") for better observability.

test-integration/programs/flexi-counter/src/state.rs (1)

12-13: LGTM!

The undelegation failure constants are clearly named and provide a simple mechanism for testing undelegation error paths.

test-integration/test-committor-service/tests/utils/instructions.rs (1)

20-30: LGTM!

The optional label parameter provides flexibility for test scenarios while maintaining backward compatibility through the default value.

magicblock-committor-service/src/intent_executor/single_stage_executor.rs (1)

178-184: LGTM!

The UndelegationError handling follows the established pattern for recoverable errors, invoking handle_undelegation_error to produce cleanup data and continuing with a retry.

magicblock-committor-service/src/intent_executor/two_stage_executor.rs (2)

180-184: LGTM!

Correctly treats UndelegationError in the commit phase as unexpected and breaks, since undelegation should occur during finalization, not commit. The error message and handling are appropriate.


222-228: LGTM!

The UndelegationError handling in the finalize phase correctly produces cleanup data via handle_undelegation_error and continues with a retry, consistent with the recoverable error pattern.

test-integration/test-committor-service/tests/utils/transactions.rs (1)

127-146: LGTM!

The label parameter is correctly threaded through the initialization flow, enabling test scenarios to customize counter labels for undelegation failure testing.

magicblock-committor-service/src/intent_executor/mod.rs (2)

450-475: LGTM!

The implementation correctly locates the first Undelegate task, truncates the strategy from that point forward, and returns a cleanup strategy with the removed tasks. The logic handles the case where no Undelegate task exists by returning an empty strategy.


552-553: LGTM!

Correctly maps UndelegationError to None, preventing premature status updates since the error is recoverable and will be retried with cleanup.

test-integration/test-committor-service/tests/test_ix_commit_local.rs (2)

7-7: LGTM: Necessary imports for FlexiCounter serialization.

The new imports support the test changes that serialize FlexiCounter data structures using Borsh.

Also applies to: 22-22


117-128: LGTM: Single-account path now uses properly serialized FlexiCounter data.

This change improves test data realism by using a correctly serialized FlexiCounter structure instead of raw byte patterns, which better aligns with the undelegation test scenarios in this PR.

test-integration/test-committor-service/tests/test_intent_executor.rs (4)

39-39: LGTM: Import needed for undelegation failure testing.

The FAIL_UNDELEGATION_LABEL import is used in the new undelegation error tests to trigger controlled failures.


161-208: LGTM: Undelegation error parsing test is well-structured.

The test correctly:

  • Forces an undelegation failure using FAIL_UNDELEGATION_LABEL
  • Verifies the error is properly typed as UndelegationError
  • Validates the error message content

This follows the established pattern of other error parsing tests in the file.


831-842: LGTM: setup_counter signature correctly extended to support labeled counters.

The optional label parameter enables tests to create counters that trigger specific behavior (like forced undelegation failures), which aligns with the PR's testing objectives.


121-121: LGTM: Call sites consistently updated for new signature.

All invocations of setup_counter and init_and_delegate_account_on_chain have been updated to pass None for the new optional label parameter, maintaining existing test behavior while enabling new undelegation failure tests.

Also applies to: 222-222, 283-283, 340-341, 436-436, 488-488, 547-547, 635-635

Comment on lines +399 to +406
{
let data = delegated_account.data.borrow();
if let Ok(counter) = FlexiCounter::deserialize(&mut data.as_ref()) {
if counter.label == FAIL_UNDELEGATION_LABEL {
return Err(ProgramError::Custom(FAIL_UNDELEGATION_CODE));
}
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using try_from_slice for consistency.

The code uses FlexiCounter::deserialize(&mut data.as_ref())? but the rest of this file consistently uses FlexiCounter::try_from_slice() (see lines 207, 237, 265, 368). While both work, maintaining consistency improves readability.

Apply this diff:

-    {
-        let data = delegated_account.data.borrow();
-        if let Ok(counter) = FlexiCounter::deserialize(&mut data.as_ref()) {
-            if counter.label == FAIL_UNDELEGATION_LABEL {
-                return Err(ProgramError::Custom(FAIL_UNDELEGATION_CODE));
-            }
-        }
-    };
+    let counter =
+        FlexiCounter::try_from_slice(&delegated_account.data.borrow())?;
+    if counter.label == FAIL_UNDELEGATION_LABEL {
+        return Err(ProgramError::Custom(FAIL_UNDELEGATION_CODE));
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
let data = delegated_account.data.borrow();
if let Ok(counter) = FlexiCounter::deserialize(&mut data.as_ref()) {
if counter.label == FAIL_UNDELEGATION_LABEL {
return Err(ProgramError::Custom(FAIL_UNDELEGATION_CODE));
}
}
};
let counter =
FlexiCounter::try_from_slice(&delegated_account.data.borrow())?;
if counter.label == FAIL_UNDELEGATION_LABEL {
return Err(ProgramError::Custom(FAIL_UNDELEGATION_CODE));
}
🤖 Prompt for AI Agents
In test-integration/programs/flexi-counter/src/processor.rs around lines 399 to
406, replace the use of FlexiCounter::deserialize(&mut data.as_ref()) with the
crate-consistent FlexiCounter::try_from_slice(...) call so it matches other
usages in the file; call try_from_slice on the account data slice (e.g.,
data.as_ref() or &data[..]) and keep the same Ok/Err handling (if let
Ok(counter) = ... ) so the behavior remains unchanged but follows the
established pattern.

@taco-paco taco-paco merged commit f9153fe into master Nov 22, 2025
29 of 30 checks passed
@taco-paco taco-paco deleted the feat/base-layer-ix/strip-failed-undelegation branch November 22, 2025 12:06
thlorenz added a commit that referenced this pull request Nov 22, 2025
…xec-buffer-fetch

* origin/master:
  Strip failed undelegations (#640)
  release: v0.2.4 (#672)
  fix: don't check for empty account with data (#671)
Dodecahedr0x pushed a commit that referenced this pull request Nov 24, 2025
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