Skip to content

Concurrent creates sharing a missing writable action account fail their post-finalize actions #101

Description

@Dodecahedr0x

Problem

AccountAccessor::create can bundle post-finalize actions, but the composed transaction does not materialize writable accounts that the actions need and that do not exist yet (ER-only PDAs a follow-up action is supposed to initialize). The action path fails with PostFinalize: Immutable / InvalidArgument on the missing account.

This bites hard under concurrency: in the sealed-bid workload, every delegated bid ticket clone carries a record_bid post-delegation action, and the first record_bid must initialize the shared auction tree and permission accounts via create_ephemeral. When many ticket clones race, they all name the same not-yet-existing shared accounts, their actions fail each other, and the losing tickets are rescue-undelegated without ever recording.

Reproduction

Prerequisites: rustup, the Solana CLI, Anchor CLI 1.x, Node 20+ with pnpm, and mb-stack (npm i -g @magicblock-labs/ephemeral-validator@0.14.10).

  1. Clone the test workload and the validator (validator fix-stack tip) side by side — the workload's test harness builds and launches the sibling validator with cargo run automatically:
git clone -b dode/test-undelegation https://github.com/magicblock-labs/sealed-bid-metadao
git clone -b dode/committor-backlog-ordering https://github.com/magicblock-labs/magicblock-validator
  1. Point the validator at the engine revision missing this fix (head of dode/adb-slot-reuse, the base of feat: prepare empty accounts #104):
sed -i '' 's/ec741da47eca2f43f5797dde2530640ecb12aa39/d13dc0dd4e9c1e54a365d320ec614b38142c01ce/g' magicblock-validator/Cargo.toml
# Linux: sed -i (without '')
  1. Run the oversized-result lifecycle test (41,000 bid tickets delegated, recorded, and undelegated in one burst):
cd sealed-bid-metadao
pnpm install
MOCHA_GREP="grows the published result" pnpm test:local
  1. Observe: the drain phase (oversized result: draining ... progress lines) stalls with tickets stuck in pending/delegated. On failure the harness preserves magicblock-stack-<timestamp>.log in the sealed-bid repo root; it shows post-finalize action failures (PostFinalize ... Immutable) for the shared tree and permission accounts, and the affected tickets rescue-undelegate without recording. At unit level, concurrent_creates_share_one_missing_writable in engine/tests/accounts.rs (added with the fix) shows every racer failing.

Restoring rev ec741da47eca2f43f5797dde2530640ecb12aa39 (this fix applied, #104) lets concurrent creates converge.

Expected

A create that bundles actions materializes the missing writable accounts idempotently in the same transaction, so a single create's actions can initialize them and concurrent creates converge on whichever transaction materializes them first instead of failing each other.

Context

engine/src/accessor.rs (AccountAccessor::create), programs/magic-root-program, dev @ cd02197 (0.3.1).

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions