Skip to content

feat: ephemeral cranks - #9

Open
Dodecahedr0x wants to merge 47 commits into
mainfrom
dode/ephemeral-cranks
Open

feat: ephemeral cranks#9
Dodecahedr0x wants to merge 47 commits into
mainfrom
dode/ephemeral-cranks

Conversation

@Dodecahedr0x

@Dodecahedr0x Dodecahedr0x commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Closes #8

Summary by CodeRabbit

  • New Features

    • Added an ephemeral Hydra program with cranker support through --ephemeral.
    • Added mode-specific scheduling, rewards, cancellation, and account lifecycle handling.
    • Added standardized commands for building, testing, linting, formatting, and benchmarks.
  • Bug Fixes

    • Improved schedule synchronization after successful triggers.
    • Updated reward and staleness behavior for base and ephemeral modes.
  • Documentation

    • Expanded guidance for ephemeral rollups, metrics, builds, testing, and usage examples.
  • Tests

    • Added live end-to-end coverage for ephemeral crank creation and repeated execution.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

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

This PR adds the hydra-ephemeral on-chain program, shared base and ephemeral APIs and processors, cranker mode selection, updated examples and tests, live end-to-end coverage, and standardized Makefile and CI workflows.

Changes

Ephemeral Rollup Crank Feature

Layer / File(s) Summary
Shared contracts, CPI, and processor logic
crates/hydra-api/...
Splits constants, IDs, PDAs, instruction builders, and CPI wrappers into base and ephemeral namespaces. Adds byte-oriented serialization and shared processor validation, scheduling, and settlement helpers.
Base and ephemeral on-chain programs
programs/hydra/*, programs/hydra-ephemeral/*
Adds ephemeral create, trigger, cancel, and close processing with Magic account lifecycle operations. Refactors base processors to use shared helpers.
Runtime support and validation
crates/hydra-cranker/*, examples/*, tests/*
Adds ephemeral cranker mode, mode-specific rewards and instruction builders, updated examples, unit tests, noop logging, and live validator-based end-to-end scenarios.
Build, CI, and documentation
.github/workflows/ci.yml, Makefile, Cargo.toml, .gitignore, README.md
Adds standardized build, lint, test, formatting, CI, workspace, and ephemeral-rollup documentation workflows.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • magicblock-labs/hydra#6: Reuses and updates the multi-instruction crank format, serialization, tail handling, and trigger assembly.

Suggested reviewers: gabrielepicco

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: adding ephemeral crank support.
Linked Issues check ✅ Passed The implementation adds ephemeral-account crank support across the API, programs, cranker, tests, and documentation, matching issue #8.
Out of Scope Changes check ✅ Passed The CI, build, documentation, and test changes support the ephemeral-crank implementation and stated cleanup objectives; no unrelated scope is evident.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dode/ephemeral-cranks

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.

@Dodecahedr0x
Dodecahedr0x changed the base branch from main to dode/multiple-instructions July 1, 2026 14:01
@Dodecahedr0x
Dodecahedr0x changed the base branch from dode/multiple-instructions to main July 6, 2026 14:10
@Dodecahedr0x
Dodecahedr0x force-pushed the dode/ephemeral-cranks branch from 7b9b392 to 7e38e4a Compare July 7, 2026 08:55
@Dodecahedr0x
Dodecahedr0x marked this pull request as ready for review July 7, 2026 09:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (2)
.github/workflows/ci.yml (1)

1-119: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add least-privilege permissions: and disable credential persistence.

Static analysis flags the default GITHUB_TOKEN permissions (unset → broad scope) and actions/checkout persisting credentials on the runner across all three jobs. Since none of these jobs need to write to the repo, tighten both.

🔒 Proposed hardening
 on:
   push:
     branches: [main]
   pull_request:
 
+permissions:
+  contents: read
+
 # Cancel superseded runs on the same ref to save runner minutes.
 concurrency:

And for each actions/checkout@v4 step:

       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 1 - 119, The CI workflow currently
relies on the default broad GITHUB_TOKEN scope and persists checkout credentials
in all jobs; tighten this by adding an explicit least-privilege permissions
block for the workflow/jobs and disabling credential persistence on each
actions/checkout@v4 step. Update the workflow definitions in the CI jobs (fmt,
default, e2e) and the checkout configuration so they do not retain repository
credentials after cloning.

Source: Linters/SAST tools

programs/hydra/src/processor/trigger.rs (1)

112-119: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use data_mut_ptr() for the write path
AccountView::data_ptr() is *const u8, but write_u64 takes *mut u8. Switch this back to data_mut_ptr() or add an explicit cast if the write is intentional.

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

In `@programs/hydra/src/processor/trigger.rs` around lines 112 - 119, The write
path in the trigger update block is using `AccountView::data_ptr()` even though
`write_u64` requires a mutable pointer. Update the `crank_ai` access in the
`unsafe` section to use `data_mut_ptr()` instead, or make the mutability
explicit if that is the intended write path, so the `write_u64` calls for
`OFF_NEXT_EXEC_SLOT`, `OFF_EXECUTED`, and `OFF_REMAINING` operate on a `*mut
u8`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 27-104: The CI workflow still uses mutable action refs, so update
the workflows in ci.yml to pin each third-party action to an immutable commit
SHA instead of tags or branches. Replace the uses entries for actions/checkout,
dtolnay/rust-toolchain, taiki-e/install-action, Swatinem/rust-cache, and
actions/setup-node with their corresponding commit-pinned versions, and keep the
existing step structure and names unchanged.

In `@crates/hydra-api/Cargo.toml`:
- Around line 33-37: `ephemeral-rollups-pinocchio` is currently always enabled
in `hydra-api` instead of being gated like the other optional dependencies.
Update `Cargo.toml` so this crate is declared optional and only activated
through the appropriate feature in the same way as `solana-define-syscall` and
`solana-program-error`, then wire it into the relevant feature set in
`hydra-api` (for example the `cpi-pinocchio` path or a dedicated `ephemeral`
feature) to match the intent described by `program/mod.rs`.

In `@crates/hydra-api/src/cpi.rs`:
- Around line 16-25: Update the doc example under hydra_api::cpi::native so it
matches the current CPI API: change the import path to
hydra_api::cpi::base::native and adjust the hydra_cpi::create example to include
the required signer_seeds argument. Keep the example aligned with the current
create signature in cpi.rs so the snippet copy-pastes and compiles.

---

Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 1-119: The CI workflow currently relies on the default broad
GITHUB_TOKEN scope and persists checkout credentials in all jobs; tighten this
by adding an explicit least-privilege permissions block for the workflow/jobs
and disabling credential persistence on each actions/checkout@v4 step. Update
the workflow definitions in the CI jobs (fmt, default, e2e) and the checkout
configuration so they do not retain repository credentials after cloning.

In `@programs/hydra/src/processor/trigger.rs`:
- Around line 112-119: The write path in the trigger update block is using
`AccountView::data_ptr()` even though `write_u64` requires a mutable pointer.
Update the `crank_ai` access in the `unsafe` section to use `data_mut_ptr()`
instead, or make the mutability explicit if that is the intended write path, so
the `write_u64` calls for `OFF_NEXT_EXEC_SLOT`, `OFF_EXECUTED`, and
`OFF_REMAINING` operate on a `*mut u8`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e7404ae9-aebb-49ea-847c-4f3bb5e5d028

📥 Commits

Reviewing files that changed from the base of the PR and between 2718469 and 07d584a.

📒 Files selected for processing (49)
  • .github/workflows/ci.yml
  • .gitignore
  • Cargo.toml
  • Makefile
  • README.md
  • crates/hydra-api/Cargo.toml
  • crates/hydra-api/src/consts.rs
  • crates/hydra-api/src/cpi.rs
  • crates/hydra-api/src/instruction.rs
  • crates/hydra-api/src/lib.rs
  • crates/hydra-api/src/program/helpers.rs
  • crates/hydra-api/src/program/mod.rs
  • crates/hydra-api/src/program/processor.rs
  • crates/hydra-api/src/state.rs
  • crates/hydra-cranker/src/cache.rs
  • crates/hydra-cranker/src/fire.rs
  • crates/hydra-cranker/src/main.rs
  • crates/hydra-cranker/src/mode.rs
  • examples/anchor/Anchor.toml
  • examples/anchor/programs/hydra-example-anchor/Cargo.toml
  • examples/anchor/programs/hydra-example-anchor/src/lib.rs
  • examples/anchor/programs/hydra-example-anchor/tests/mollusk.rs
  • examples/native/src/lib.rs
  • examples/native/tests/mollusk.rs
  • examples/pinocchio/src/lib.rs
  • examples/pinocchio/tests/mollusk.rs
  • programs/hydra-ephemeral/Cargo.toml
  • programs/hydra-ephemeral/src/entrypoint.rs
  • programs/hydra-ephemeral/src/lib.rs
  • programs/hydra-ephemeral/src/processor/cancel.rs
  • programs/hydra-ephemeral/src/processor/close.rs
  • programs/hydra-ephemeral/src/processor/common.rs
  • programs/hydra-ephemeral/src/processor/create.rs
  • programs/hydra-ephemeral/src/processor/mod.rs
  • programs/hydra-ephemeral/src/processor/trigger.rs
  • programs/hydra/Cargo.toml
  • programs/hydra/src/entrypoint.rs
  • programs/hydra/src/lib.rs
  • programs/hydra/src/processor/cancel.rs
  • programs/hydra/src/processor/close.rs
  • programs/hydra/src/processor/common.rs
  • programs/hydra/src/processor/create.rs
  • programs/hydra/src/processor/mod.rs
  • programs/hydra/src/processor/trigger.rs
  • tests/e2e/Cargo.toml
  • tests/e2e/tests/ephemeral_cranks.rs
  • tests/lib.rs
  • tests/programs/noop/Cargo.toml
  • tests/programs/noop/src/lib.rs

Comment thread .github/workflows/ci.yml
Comment thread crates/hydra-api/Cargo.toml
Comment thread crates/hydra-api/src/cpi.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
programs/hydra-ephemeral/src/processor/trigger.rs (1)

88-94: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Use checked arithmetic for executed.

executed + 1 can overflow when the persisted counter reaches u64::MAX, aborting the trigger instead of returning a program error.

Proposed fix
+    let next_executed = executed
+        .checked_add(1)
+        .ok_or(ProgramError::ArithmeticOverflow)?;
     {
         let mut data = crank_ai.try_borrow_mut()?;
         let s = unsafe { load_crank_mut(&mut data)? };
         s.set_next_exec_slot(next_slot);
-        s.set_executed(executed + 1);
+        s.set_executed(next_executed);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@programs/hydra-ephemeral/src/processor/trigger.rs` around lines 88 - 94,
Update the counter increment in the crank state mutation block using checked
arithmetic for executed + 1, and propagate the overflow as the processor’s
existing program error type before calling set_executed. Preserve normal
increment behavior for values below u64::MAX and leave the remaining counter
logic unchanged.
programs/hydra/src/processor/trigger.rs (1)

112-115: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use data_mut_ptr() for these writes. data_ptr() returns *const u8, so this write_u64 path needs a mutable pointer or mutable borrow instead.

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

In `@programs/hydra/src/processor/trigger.rs` around lines 112 - 115, Update the
unsafe write block in the trigger processing flow to obtain the pointer via
crank_ai.data_mut_ptr() instead of data_ptr(), while preserving the existing
OFF_NEXT_EXEC_SLOT and OFF_EXECUTED writes.

Source: MCP tools

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

Outside diff comments:
In `@programs/hydra-ephemeral/src/processor/trigger.rs`:
- Around line 88-94: Update the counter increment in the crank state mutation
block using checked arithmetic for executed + 1, and propagate the overflow as
the processor’s existing program error type before calling set_executed.
Preserve normal increment behavior for values below u64::MAX and leave the
remaining counter logic unchanged.

In `@programs/hydra/src/processor/trigger.rs`:
- Around line 112-115: Update the unsafe write block in the trigger processing
flow to obtain the pointer via crank_ai.data_mut_ptr() instead of data_ptr(),
while preserving the existing OFF_NEXT_EXEC_SLOT and OFF_EXECUTED writes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 088f3920-5be2-4fe7-a2be-c52d7ee287e5

📥 Commits

Reviewing files that changed from the base of the PR and between 07d584a and 7897dd1.

📒 Files selected for processing (8)
  • programs/hydra-ephemeral/src/processor/cancel.rs
  • programs/hydra-ephemeral/src/processor/close.rs
  • programs/hydra-ephemeral/src/processor/create.rs
  • programs/hydra-ephemeral/src/processor/trigger.rs
  • programs/hydra/src/processor/cancel.rs
  • programs/hydra/src/processor/close.rs
  • programs/hydra/src/processor/create.rs
  • programs/hydra/src/processor/trigger.rs

@Dodecahedr0x
Dodecahedr0x force-pushed the dode/ephemeral-cranks branch from 7897dd1 to 07d584a Compare July 22, 2026 13:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
crates/hydra-cranker/src/cache.rs (2)

172-196: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Protect optimistic trigger advancement from stale subscription snapshots.

The cache advances before transaction confirmation, but subscription updates can still apply an older account snapshot. This can restore the previous schedule and submit the same crank again.

  • crates/hydra-cranker/src/cache.rs#L172-L196: Add monotonic snapshot validation or a pending-trigger barrier before replacing an optimistically advanced entry.
  • crates/hydra-cranker/src/main.rs#L25-L31: Keep the one-slot cooldown only after stale snapshot reconciliation is enforced.
  • crates/hydra-cranker/src/main.rs#L350-L353: Reconcile the optimistic update with subscription or confirmed RPC state before allowing another trigger.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/hydra-cranker/src/cache.rs` around lines 172 - 196, Protect
advance_after_trigger in crates/hydra-cranker/src/cache.rs:172-196 from older
subscription snapshots by adding monotonic snapshot validation or a
pending-trigger barrier before replacing an optimistically advanced cache entry.
In crates/hydra-cranker/src/main.rs:25-31, retain the one-slot cooldown only
after stale-snapshot reconciliation is enforced. In
crates/hydra-cranker/src/main.rs:350-353, reconcile the optimistic advancement
with subscription or confirmed RPC state before permitting another trigger.

29-32: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep existing crank accounts compatible before changing the decoder layout.

CrankEntry::from_raw now decodes interval_slots at [72..80], but the on-chain Crank state plus Trigger/Close still use the previous layout. If old crank accounts can remain on chain, add a layout version or migration; otherwise old data decodes with the wrong schedule.

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

In `@crates/hydra-cranker/src/cache.rs` around lines 29 - 32, Update
CrankEntry::from_raw and the associated on-chain Crank/Trigger/Close layout
handling so existing crank accounts remain decodable after adding interval_slots
at [72..80]. Add an explicit layout version or migration path that distinguishes
legacy accounts and preserves their prior schedule, while using the new layout
only for upgraded accounts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/hydra-cranker/src/cache.rs`:
- Around line 172-196: Protect advance_after_trigger in
crates/hydra-cranker/src/cache.rs:172-196 from older subscription snapshots by
adding monotonic snapshot validation or a pending-trigger barrier before
replacing an optimistically advanced cache entry. In
crates/hydra-cranker/src/main.rs:25-31, retain the one-slot cooldown only after
stale-snapshot reconciliation is enforced. In
crates/hydra-cranker/src/main.rs:350-353, reconcile the optimistic advancement
with subscription or confirmed RPC state before permitting another trigger.
- Around line 29-32: Update CrankEntry::from_raw and the associated on-chain
Crank/Trigger/Close layout handling so existing crank accounts remain decodable
after adding interval_slots at [72..80]. Add an explicit layout version or
migration path that distinguishes legacy accounts and preserves their prior
schedule, while using the new layout only for upgraded accounts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: df214b72-aae9-4490-baa2-8beb6bb72021

📥 Commits

Reviewing files that changed from the base of the PR and between 7897dd1 and b70f301.

📒 Files selected for processing (2)
  • crates/hydra-cranker/src/cache.rs
  • crates/hydra-cranker/src/main.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
crates/hydra-cranker/src/main.rs (1)

350-356: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Defer cache advancement to signature confirmation.

fire_trigger only polls get_signature_status() when skip_preflight is true; when preflight is enabled, its Ok(()) path can run after send_transaction_with_config acceptance rather than confirmation. Advance entry.pubkey in advance_after_trigger only after an authoritative success/status, or defer until the subscription echo arrives.

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

In `@crates/hydra-cranker/src/main.rs` around lines 350 - 356, Remove the
immediate cache::advance_after_trigger call from the fire_trigger success path
and defer advancing entry.pubkey until an authoritative successful signature
status is observed or the programSubscribe echo arrives. Ensure
send_transaction_with_config returning Ok(()) alone cannot advance the cache or
clear the failure record.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/e2e/tests/ephemeral_cranks.rs`:
- Line 52: Update the cleanup flow in the ephemeral crank tests after wait_until
joins the reader thread: explicitly release the ManuallyDrop-wrapped _sub with
bounded cleanup so each scenario closes its WebSocket and subscription instead
of retaining PubsubLogsClientSubscription until process exit.

---

Outside diff comments:
In `@crates/hydra-cranker/src/main.rs`:
- Around line 350-356: Remove the immediate cache::advance_after_trigger call
from the fire_trigger success path and defer advancing entry.pubkey until an
authoritative successful signature status is observed or the programSubscribe
echo arrives. Ensure send_transaction_with_config returning Ok(()) alone cannot
advance the cache or clear the failure record.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e355afd8-6189-48d9-81ae-3a883c7dabe9

📥 Commits

Reviewing files that changed from the base of the PR and between b70f301 and f473693.

📒 Files selected for processing (5)
  • Makefile
  • crates/hydra-api/src/consts.rs
  • crates/hydra-cranker/src/cache.rs
  • crates/hydra-cranker/src/main.rs
  • tests/e2e/tests/ephemeral_cranks.rs
💤 Files with no reviewable changes (1)
  • crates/hydra-api/src/consts.rs

Comment thread tests/e2e/tests/ephemeral_cranks.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (3)
crates/hydra-cranker/src/main.rs (1)

352-355: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Suppress a terminal crank until the cache reconciles it.

If the final trigger lands but programSubscribe does not update the cache before the next interval, Line 355 advances only next_exec_slot. The entry still has remaining == 1, as specified by crates/hydra-cranker/src/cache.rs Lines 295-304. The cranker then submits another trigger for an exhausted crank after the one-slot cooldown.

Mark a final execution as pending and exclude it from eligibility until an account update or bounded RPC reconciliation resolves the submission. Keep a retry path for submissions that did not land.

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

In `@crates/hydra-cranker/src/main.rs` around lines 352 - 355, Update the trigger
handling around cache::advance_after_trigger so a final execution with remaining
== 1 is marked pending and excluded from eligibility until programSubscribe or
bounded RPC reconciliation confirms the account state; preserve a retry path
when the submission does not land, while leaving non-terminal interval
advancement unchanged.
crates/hydra-api/src/cpi.rs (1)

183-190: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Pass signer_seeds in the ephemeral CPI example.

hydra_api::cpi::ephemeral::native::create requires signer_seeds, but the example stops after CreateArgs.

📝 Proposed fix
         //!     sponsor_ai, crank_ai, vault_ai, magic_program_ai,
         //!     &CreateArgs { seed, authority: [0u8; 32], /* ... */ },
+        //!     &signer_seeds,
         //! )?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/hydra-api/src/cpi.rs` around lines 183 - 190, Update the ephemeral
native create example around hydra_cpi::create to include the required
signer_seeds argument after the CreateArgs argument, using the appropriate
seed-slice representation while preserving the existing example flow.
crates/hydra-api/src/instruction.rs (1)

75-182: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align the Create serializer with the stored crank tail layout.

create::write_to and create::body_len currently write each scheduled ix as [u8 num_accounts][u16 data_len][program_id][metas][data], but scheduled_ixs_from_crank reads the on-chain tail as [u16 num_accounts][metas][program_id][u16 data_len][data], and processor::measure_region/write_tail also use that crank layout. This width/order mismatch breaks Trigger.followup byte matching, so either the crank parser needs to match the serializer or the serializer needs to emit and count u16 num_accounts first.

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

In `@crates/hydra-api/src/instruction.rs` around lines 75 - 182, Align
CreateArgs::write_to and CreateArgs::body_len with the crank tail layout
consumed by scheduled_ixs_from_crank, processor::measure_region, and write_tail:
encode each scheduled instruction as a u16 account count, metas, program_id, u16
data length, then data. Update the size calculation to include the u16 count and
place all fields in that same order so Trigger.followup byte matching remains
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/hydra-api/src/cpi.rs`:
- Around line 183-190: Update the ephemeral native create example around
hydra_cpi::create to include the required signer_seeds argument after the
CreateArgs argument, using the appropriate seed-slice representation while
preserving the existing example flow.

In `@crates/hydra-api/src/instruction.rs`:
- Around line 75-182: Align CreateArgs::write_to and CreateArgs::body_len with
the crank tail layout consumed by scheduled_ixs_from_crank,
processor::measure_region, and write_tail: encode each scheduled instruction as
a u16 account count, metas, program_id, u16 data length, then data. Update the
size calculation to include the u16 count and place all fields in that same
order so Trigger.followup byte matching remains consistent.

In `@crates/hydra-cranker/src/main.rs`:
- Around line 352-355: Update the trigger handling around
cache::advance_after_trigger so a final execution with remaining == 1 is marked
pending and excluded from eligibility until programSubscribe or bounded RPC
reconciliation confirms the account state; preserve a retry path when the
submission does not land, while leaving non-terminal interval advancement
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: db449768-4719-479d-836a-92370d7037cf

📥 Commits

Reviewing files that changed from the base of the PR and between f473693 and a69b7d7.

📒 Files selected for processing (9)
  • crates/hydra-api/Cargo.toml
  • crates/hydra-api/src/cpi.rs
  • crates/hydra-api/src/instruction.rs
  • crates/hydra-cranker/Cargo.toml
  • crates/hydra-cranker/src/cache.rs
  • crates/hydra-cranker/src/fire.rs
  • crates/hydra-cranker/src/main.rs
  • tests/e2e/Cargo.toml
  • tests/e2e/tests/ephemeral_cranks.rs

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.

feat: cranks on ephemeral accounts

1 participant