Skip to content

feat: add call_handler_v2 support for ScheduleIntentBundle actions#946

Merged
taco-paco merged 8 commits intomasterfrom
feat/call-handler-v2
Feb 18, 2026
Merged

feat: add call_handler_v2 support for ScheduleIntentBundle actions#946
taco-paco merged 8 commits intomasterfrom
feat/call-handler-v2

Conversation

@taco-paco
Copy link
Copy Markdown
Contributor

@taco-paco taco-paco commented Feb 12, 2026

Summary

  • Add call_handler_v2 support for base actions scheduled via ScheduleIntentBundle, passing
    source_program to the delegation program
  • ScheduleBaseIntent (legacy) continues using call_handler for backward compatibility with
    existing deployed contracts
  • BaseAction.source_program is now Option<Pubkey>, set based on which instruction variant was
    used
  • Introduce BaseActionV2Task in the committor service to select call_handler_v2 at the type
    level, avoiding runtime flag checks

Compatibility

  • No breaking changes
  • Config change (describe):
  • Migration needed (describe):

Testing

  • tests (or explain)

Checklist

  • docs updated (if needed)
  • closes #

Summary by CodeRabbit

  • New Features

    • v2 base actions with a secure execution path and optional source_program on actions.
    • Streaming task creation to emit tasks lazily, reducing intermediate allocations.
    • Simplified intent builder usage with fluent chaining.
  • Bug Fixes

    • Enforced source_program validation in action handlers to reject invalid callers.
  • Chores

    • Updated dependency revisions.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 12, 2026

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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Updated dependency revisions in Cargo.toml entries. Added source_program: Option<Pubkey> to BaseAction and secure: bool to ConstructionContext, and threaded a secure boolean through schedule intent processing. Introduced BaseActionV2Task and an ArgsTaskType::BaseActionV2 variant, refactored task creation to an iterator/stream approach, and updated instruction emission to call call_handler_v2 for V2 actions. Tests and an integration program were updated to populate and validate source_program. Minor API surface changes reflect new fields and function parameters.

Suggested reviewers

  • snawaz
  • bmuddha
  • thlorenz
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/call-handler-v2

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
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (2)
programs/magicblock/src/magic_scheduled_base_intent.rs (2)

542-550: 🧹 Nitpick | 🔵 Trivial

The source_program field is correctly placed and typed, but consider field ordering.

The new field is inserted between destination_program and escrow_authority. For serialization safety (as noted above), appending it as the last field would be less risky. Functionally, the Option<Pubkey> type is appropriate — None for legacy, Some(pubkey) for v2.

Safer field ordering
 pub struct BaseAction {
     pub compute_units: u32,
     pub destination_program: Pubkey,
-    pub source_program: Option<Pubkey>,
     pub escrow_authority: Pubkey,
     pub data_per_program: ProgramArgs,
     pub account_metas_per_program: Vec<ShortAccountMeta>,
+    pub source_program: Option<Pubkey>,
 }

This would require updating all construction sites, but avoids breaking positional deserialization if BaseAction is ever read by old code.


575-596: ⚠️ Potential issue | 🟠 Major

Verify serialization compatibility for the new source_program field in BaseAction.

Adding source_program: Option<Pubkey> in the middle of a #[derive(Serialize, Deserialize)] struct changes the serialized layout for bincode. Since BaseAction is nested inside ScheduledIntentBundle within MagicIntentBundle, which is persisted via MagicContext on-chain state using bincode serialization, any in-flight scheduled intents serialized before this change would fail to deserialize after an upgrade.

The code includes a backward compatibility mechanism via the secure field (setting source_program to None when false), but this does not address the binary format incompatibility for already-persisted data.

If upgrades are atomic with no in-flight intents surviving, this is acceptable. Otherwise, consider:

  1. Appending the field at the end of the struct instead of inserting it in the middle to preserve binary compatibility.
  2. Ensuring all pending intents are drained before deploying this change.
🤖 Fix all issues with AI agents
In `@magicblock-committor-service/src/tasks/mod.rs`:
- Around line 169-173: BaseActionV2Task is missing a Debug impl which hampers
diagnostics; add Debug to its derives by updating the struct declaration for
BaseActionV2Task to derive(Debug, Clone). Ensure the types used in the struct
(BaseAction and Pubkey) already implement Debug (or make them implement/derive
Debug if necessary) so the derived Debug for BaseActionV2Task compiles cleanly.

Comment thread magicblock-committor-service/src/tasks/mod.rs Outdated
@taco-paco taco-paco marked this pull request as ready for review February 12, 2026 07:58
Copy link
Copy Markdown
Collaborator

@GabrielePicco GabrielePicco left a comment

Choose a reason for hiding this comment

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

LGTM!

The only concern Is that this break bincode compatibility of MagicContext (i.e., we need to guarantee it’s empty/zeroed on upgrade), or do a migration/versioning strategy

@taco-paco
Copy link
Copy Markdown
Contributor Author

LGTM!

The only concern Is that this break bincode compatibility of MagicContext (i.e., we need to guarantee it’s empty/zeroed on upgrade), or do a migration/versioning strategy

Valid concern, I think we can do it as the last time, we can kill connection couple slots prior to shutdown and the MagicContext will be emptied

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@programs/magicblock/src/magic_scheduled_base_intent.rs`:
- Around line 575-593: The two branches currently return the same error variant
InstructionError::UnsupportedProgramId for different failure cases (missing CPI
vs cross-program call); update the second branch (the else that checks
args.destination_program == parent_program_id) to return a distinct error
variant or a custom/clearer InstructionError (e.g.,
InstructionError::IncorrectProgramId or a new variant) so callers can
distinguish the "not scheduled via CPI" failure (left as UnsupportedProgramId)
from the "cross-program prohibition for v1" failure; change the Err(...) in the
else branch referencing args.destination_program and parent_program_id
accordingly and keep the existing ic_msg! logs.

Comment thread programs/magicblock/src/magic_scheduled_base_intent.rs
# Conflicts:
#	test-integration/Cargo.lock
Copy link
Copy Markdown
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.

Caution

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

⚠️ Outside diff range comments (1)
programs/magicblock/src/magicblock_processor.rs (1)

75-86: 🧹 Nitpick | 🔵 Trivial

Bare boolean literals obscure the intent of secure at the call site.

Both call sites pass an unnamed true/false without any indication of what the flag controls. A reader must navigate to process_schedule_intent_bundle to learn that secure governs call_handler_v2 selection and source_program population. A brief inline comment — or ideally a named constant — would make the distinction self-evident.

🔍 Suggested clarification
-            ScheduleBaseIntent(args) => process_schedule_intent_bundle(
-                signers,
-                invoke_context,
-                args.into(),
-                false,
-            ),
-            ScheduleIntentBundle(args) => process_schedule_intent_bundle(
-                signers,
-                invoke_context,
-                args,
-                true,
-            ),
+            // Legacy variant: use call_handler (no source_program)
+            ScheduleBaseIntent(args) => process_schedule_intent_bundle(
+                signers,
+                invoke_context,
+                args.into(),
+                false, // secure = false: legacy call_handler path
+            ),
+            // V2 variant: use call_handler_v2 (passes source_program)
+            ScheduleIntentBundle(args) => process_schedule_intent_bundle(
+                signers,
+                invoke_context,
+                args,
+                true, // secure = true: call_handler_v2 path
+            ),

Additionally, the name secure is semantically misleading — it sounds like a security/auth flag rather than a V2-handler selector. A name like use_v2_handler or pass_source_program would better express the actual branching behaviour. This applies to the function parameter in programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs (line 31) and the ConstructionContext field.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@programs/magicblock/src/magicblock_processor.rs` around lines 75 - 86, Call
sites to process_schedule_intent_bundle (ScheduleBaseIntent and
ScheduleIntentBundle) currently pass bare true/false which obscures that the
flag controls V2 handler selection and source_program population; update the API
and calls to use a clearer name (e.g. rename the parameter secure to
use_v2_handler or pass_source_program in process_schedule_intent_bundle and the
corresponding ConstructionContext field) and replace the anonymous literals at
the two call sites with the appropriate named constant or explicit inline
comment so the intent is obvious (change ScheduleBaseIntent(...) to pass the
false-named constant/comment and ScheduleIntentBundle(...) to pass the
true-named constant/comment and update all references to the renamed
parameter/field accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@programs/magicblock/src/magicblock_processor.rs`:
- Around line 75-86: Call sites to process_schedule_intent_bundle
(ScheduleBaseIntent and ScheduleIntentBundle) currently pass bare true/false
which obscures that the flag controls V2 handler selection and source_program
population; update the API and calls to use a clearer name (e.g. rename the
parameter secure to use_v2_handler or pass_source_program in
process_schedule_intent_bundle and the corresponding ConstructionContext field)
and replace the anonymous literals at the two call sites with the appropriate
named constant or explicit inline comment so the intent is obvious (change
ScheduleBaseIntent(...) to pass the false-named constant/comment and
ScheduleIntentBundle(...) to pass the true-named constant/comment and update all
references to the renamed parameter/field accordingly).

@taco-paco taco-paco merged commit 012c178 into master Feb 18, 2026
20 of 33 checks passed
@taco-paco taco-paco deleted the feat/call-handler-v2 branch February 18, 2026 17:55
thlorenz added a commit that referenced this pull request Feb 19, 2026
* master:
  hotfix: integration tests (#983)
  hotfix: integration tests (#982)
  chore: revert offset change (#981)
  fix: stop setting loaded accounts data size limit (#980)
  Fix: flaky ledger reset integration test (#977)
  Feat: tui interface for the validator (#972)
  fix: slack ready-for-review reviewer display (#978)
  fix: SetLoadedAccountsDataSize (#976)
  feat: add call_handler_v2 support for ScheduleIntentBundle actions (#946)
  feat: implement ephemeral accounts (#915)
  fix: prevent overrides on subscription updates (#970)
  fix: ignore error on delete in fat truncation. Case when the disk is … (#924)
thlorenz added a commit that referenced this pull request Feb 27, 2026
* master: (42 commits)
  chore: CI on self-hosted runner (#975)
  fix: handle failed Intents due to 5xx errors from server (#1005)
  feat: implement StreamManager for gRPC subscription management (#985)
  chore: improve delegation error messages and reuse chainslot across retries (#994)
  release: 0.8.1 (#998)
  Create RELEASE_PROCESS.md (#997)
  fix: wait for valid blockhash (#992)
  feat: Add ScheduleCommitFinalize to program-api only (#989)
  release: 0.8.0 (#979)
  hotfix: integration tests (#983)
  hotfix: integration tests (#982)
  chore: revert offset change (#981)
  fix: stop setting loaded accounts data size limit (#980)
  Fix: flaky ledger reset integration test (#977)
  Feat: tui interface for the validator (#972)
  fix: slack ready-for-review reviewer display (#978)
  fix: SetLoadedAccountsDataSize (#976)
  feat: add call_handler_v2 support for ScheduleIntentBundle actions (#946)
  feat: implement ephemeral accounts (#915)
  fix: prevent overrides on subscription updates (#970)
  ...
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