Skip to content

Support large-account commits in MagicBlock Protocol v2 #191

Description

@taco-paco

Goal

Commit and finalize account states larger than 10 KiB (10,240 bytes) through MagicBlock Protocol v2, including changes that grow the destination account.

Why

The existing buffered commit path creates a full-sized commit-state PDA in one CPI, which can fail with Failed to reallocate account data for large states. The reported devnet transaction demonstrates the original failure. MBV now rejects oversized accounts earlier; that makes the limitation clearer but does not provide support.

V2 already has incremental state-buffer uploads, while finalization still resizes the destination in one call. Buffer capacity alone does not establish end-to-end support.

Scope

This is v2 work under #132. Backporting support to v1 is outside this issue.

Activity

  1. GabrielePicco commented on Aug 4, 2026

    @GabrielePicco
    Contributor

    Proposed design

    One generic preallocate instruction (buffer-kind arg) covering both the commit_state PDA and the undelegate buffer PDA — fixes commit of large accounts and prevents the corresponding undelegation failure for
    the same accounts.

    Since the 10,240-byte growth cap resets per top-level instruction, a small instruction can grow a DLP-owned PDA in ≤10,240-byte steps, and all steps can be packed into the same transaction as the commit/finalize
    (or undelegate), preserving atomicity.

    New instruction: PreallocateBuffer (discriminator 28)

    • Args (borsh, ~13 bytes total incl. discriminator): kind: enum { CommitState, UndelegateBuffer, DelegatedAccount }, target_size: u32.
    • Accounts: payer (signer, writable), delegated_account, delegation_record, buffer PDA (writable), commit_record, system_program.
    • Behavior (idempotent, "move current size toward target by ≤10,240"):
      • buffer uninitialized → create_pda with min(target, 10_240);
      • buffer already DLP-owned → verify PDA derivation, then resize by min(remaining, 10_240) (direct realloc + rent top-up from payer);
      • refuses to touch the buffer of an in-flight commit (commit_record must be uninitialized).
    • kind = DelegatedAccount (optional, for the finalize growth case): pre-grows the delegated account itself; gated on payer == delegation_record.authority since it changes observable base-layer state. The
      buffer kinds can stay permissionless: the PDAs are DLP-owned and always zero-filled, size is corrected at commit/undelegate time, and all rent is swept to the validator when the buffer is closed.

    A validator committing an account of size N sends ceil(N / 10_240) preallocate instructions followed by the commit + finalize in one transaction (e.g. 15,524 bytes → 2 chunks).

    Processor changes

    • process_commit_state_internal: replace require_uninitialized_pda(commit_state_account, ...) with a derivation-only check, then branch — uninitialized → create_pda at exact size (current behavior,
      ≤10,240-byte accounts unaffected); already DLP-owned → resize to exact data_len (shrink uncapped, residual growth ≤10,240). Double-commit protection rests on the unchanged commit_record uninitialized check,
      which is sufficient since commit_state/commit_record are always created and closed together.
    • Same relaxation for the undelegate buffer in undelegate.rs and undelegate_confined_account.rs (their pending-commit guard already runs before buffer creation).
    • New pinocchio resize_pda helper in src/processor/fast/utils/pda.rs (rent top-up transfer + AccountView::resize), mirroring the slow-path resize_pda.

    Safety note: a preallocated buffer can only ever contain zeros (created zeroed, growth zero-fills, only DLP can write it), which matches the zero-tail assumption of merge_diff_copy, and copy_from_slice fully
    overwrites it after the exact-size resize.

    SDK / API

    • dlp-api: new discriminator variant, args struct, and instruction builder, including a convenience helper returning the full Vec<Instruction> chunk sequence for a given size; IDL entry in
      idl/delegation.json.
    • Validator-side (separate repo): the committor must emit the preallocate chunks when data_len > 10_240.
  2. taco-paco commented on Aug 4, 2026

    @taco-paco
    ContributorAuthor

    Do we need buffer account then which is handled currently by magicblock-committor-program?
    See diff_buffer_account in process_commit_diff_from_buffer which would contain same data as commit_state now.

    It would be good to have one of them. Say we get rid of magicblock-committor-program.
    Then 2 flows are:

    1. process_commit_diff_from_buffer/process_commit_state_from_buffer got called - commit_state must be initialized.
    2. process_commit_diff/process_commit_state is called - commit_state isn't initialized and we need to create it and copy arg data into it

    1st flow wouldn't necessarily mean data over 10kb in this case. Validator might choose it because otherwise it may not fit data in tx(if it would be via Args)

  3. added theissue type on Aug 4, 2026
  4. GabrielePicco commented on Aug 7, 2026

    @GabrielePicco
    Contributor

    Do we need buffer account then which is handled currently by magicblock-committor-program? See diff_buffer_account in process_commit_diff_from_buffer which would contain same data as commit_state now.

    It would be good to have one of them. Say we get rid of magicblock-committor-program. Then 2 flows are:

    1. process_commit_diff_from_buffer/process_commit_state_from_buffer got called - commit_state must be initialized.
    2. process_commit_diff/process_commit_state is called - commit_state isn't initialized and we need to create it and copy arg data into it

    1st flow wouldn't necessarily mean data over 10kb in this case. Validator might choose it because otherwise it may not fit data in tx(if it would be via Args)

    No ideally we don't, if that's roughly the same amounts of changes, we should to it right away

  5. snawaz commented on Aug 7, 2026

    @snawaz
    Collaborator

    The proposed solution should work.

    However, what @taco-paco suggested is also a great optimization. We should eventually implement that as well.

  6. GabrielePicco commented on Sep 14, 2026

    @GabrielePicco
    Contributor

    We now fail early mentioning we don't support this case, and it's gonna be supported in dlpv2

  7. changed the title [-][Bug] Failed to reallocate account data[/-] [+]Support large-account commits in MagicBlock Protocol v2[/+] on Sep 17, 2026
  8. added
    enhancementNew feature or request
    and removed
    bugSomething isn't working
    on Sep 17, 2026
  9. changed the issue type fromtoon Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions