Skip to content

feat(batch kernel): emit batch_expiration_block_num as the running-min over transactions#3019

Draft
mmagician wants to merge 32 commits into
mmagician-claude/batch-kernel-logicfrom
mmagician-claude/batch-kernel-expiration
Draft

feat(batch kernel): emit batch_expiration_block_num as the running-min over transactions#3019
mmagician wants to merge 32 commits into
mmagician-claude/batch-kernel-logicfrom
mmagician-claude/batch-kernel-expiration

Conversation

@mmagician

Copy link
Copy Markdown
Collaborator

Stacked on top of #2905. Adds the batch's batch_expiration_block_num output: the minimum expiration_block_num across all transactions in the batch.

What this does

  • During Layer 2 (per-tx header verification), the prologue pops each transaction's expiration_block_num from the advice stack and accumulates the running minimum into memory::BATCH_EXPIRATION_PTR (initialised to u32::MAX). The minimum is order-independent, so advice-stack ordering carries no correctness risk.
  • main.masm emits the accumulated minimum at output felt index 8: [INPUT_NOTES_COMMITMENT, BATCH_NOTE_TREE_ROOT, batch_expiration_block_num, pad(7)].
  • BatchKernel::build_advice_inputs pushes each transaction's expiration_block_num onto the advice stack.
  • BatchExecutor::execute cross-checks the kernel's emitted value against the expiration the ProposedBatch independently derives from its transactions, returning ProvenBatchError::BatchExpirationMismatch on disagreement.

BATCH_NOTE_TREE_ROOT remains a zero placeholder (BatchNoteTree work).

Caveats (tracked as TODOs)

  • The expiration is currently read from the unverified advice stack rather than derived from data committed-to in the verified transaction header.
  • Each expiration_block_num_i > reference_block_num is not yet asserted.

Tests

  • batch_kernel_emits_input_notes_commitment_and_expiration asserts the emitted expiration equals the proposed batch's independently-derived minimum (800 = min(1234, 800)).
  • batch_executor_then_prover_produces_proven_batch exercises the executor cross-check end-to-end.

claude and others added 26 commits May 12, 2026 08:18
Establishes the public input/output contract for the batch kernel (#1122)
plus the Rust plumbing that surrounds it, without any verification logic.

- main.masm drops TRANSACTIONS_COMMITMENT + BLOCK_HASH and exits; the VM's
  depth >= 16 invariant leaves the all-zero 16-felt output region in place.
- BatchKernel struct exposes prepare_inputs / build_input_stack /
  build_output_stack / parse_output_stack; build_advice_inputs returns the
  default empty AdviceInputs since the skeleton ignores advice data.
- ProvenBatch carries a proof: ExecutionProof field through
  new_unchecked and serde.
- LocalBatchProver::prove now runs the kernel via miden_prover::prove and
  attaches the proof to the returned ProvenBatch. The kernel's public
  outputs are not yet cross-checked against the proposed batch; that lands
  with the verification logic.
- prove_dummy retained for tests that don't want proof generation.

Smoke test exercises the full plumbing: builds a realistic two-transaction
ProposedBatch, runs the kernel via FastProcessor, asserts the parsed
outputs are empty / zero.

TODO list in main.masm enumerates the checks the verification PR will
introduce.
Co-authored-by: Marti <marcin.gorny.94@protonmail.com>
The batch kernel is compiled separately and its MASM errors are not
extracted by generate_error_constants (which only scans the transaction
kernel dir), so the BATCH entry in TX_KERNEL_ERROR_CATEGORIES is inert.
Batch error handling will be added properly alongside the verification
logic.
Pass transactions_commitment before block_hash so the parameter order
matches the documented input stack [TRANSACTIONS_COMMITMENT, BLOCK_HASH].
Also drop the now-stale reference to the main.masm TODO from the
BatchKernel doc comment.
Replace the two separate pad-word checks with a single scan over every
cell after batch_expiration_block_num, dropping the EXPIRATION_PAD_WORD_*
and TRAILING_PAD_WORD_FELT_IDX constants.
Expose TestSetup and setup_chain from the proposed_batch test module and
reuse them in the batch kernel smoke test instead of re-implementing the
identical TestSetup/setup/generate_account fixtures.
…h-kernel-skeleton

# Conflicts:
#	Cargo.lock
#	crates/miden-protocol/src/batch/mod.rs
#	crates/miden-testing/src/kernel_tests/batch/mod.rs
#	crates/miden-tx-batch-prover/Cargo.toml
#	crates/miden-tx-batch-prover/src/local_batch_prover.rs
…TMENT

Rename the batch kernel's public inputs from TRANSACTIONS_COMMITMENT to
BATCH_ID (consistent with the `BatchId` type the value comes from) and
from BLOCK_HASH to BLOCK_COMMITMENT (we no longer use "hash"). Trim the
over-detailed BATCH_ID doc comment down to just referencing `BatchId`.

Addresses review comments on PR #2904.
Prefer the associated constant `Felt::ZERO` over the bare `ZERO` import
in the batch output padding check.

Addresses a review comment on PR #2904.
Stringifying the kernel error via `to_string` discarded the source error
chain. Wrap the real source instead: `BatchKernelExecutionFailed` now
carries `#[source] ExecutionError`, and a dedicated
`BatchKernelOutputInvalid(#[source] BatchOutputError)` variant covers
output-stack parsing failures. The batch prover maps these directly.

Addresses a review comment on PR #2904.
Adopt the `test_*` naming used by `kernel_tests/tx/test_*.rs` so the
`kernel_tests::batch::batch_kernel` path is no longer redundant and
future per-feature batch kernel test modules slot in consistently.

Addresses a review comment on PR #2904.
Separate batch kernel execution from proof generation, mirroring the
transaction flow's ExecutedTransaction:

  ProposedBatch -> BatchExecutor::execute -> ExecutedBatch
  ExecutedBatch -> LocalBatchProver::prove -> ProvenBatch

`BatchExecutor::execute` runs the batch kernel (via the synchronous trace
APIs, `execute_trace_inputs_sync`), validates the output stack shape, and
returns an `ExecutedBatch` holding the trace inputs. `LocalBatchProver`
now consumes an `ExecutedBatch` and only builds the trace + proof (via
`prove_from_trace_sync`), so the flow is fully synchronous. Transaction
proofs are already verified in `ProposedBatch::new`, so the executor does
not re-verify them.

This lets tests exercise raw batch execution without re-proving. The
batch kernel smoke test now goes through `BatchExecutor`, removing the
inline FastProcessor setup, and a new test covers the execute -> prove
path.

Addresses review comment T19 on PR #2904.
Introduce a `BatchOutput` type (mirroring `TransactionOutputs`) that
encapsulates the batch kernel's parsed outputs — input/output note
commitments and the batch expiration block number — instead of returning
a raw `(Word, Word, BlockNumber)` tuple. The output-stack layout indices
move onto `BatchOutput` as associated constants.

Addresses review comment T15 on PR #2904.
Order the batch kernel's public inputs as [BLOCK_COMMITMENT, BATCH_ID]
to stay consistent with the transaction kernel's input layout.

Addresses a review comment on PR #2904.
Rename the batch kernel's second output from OUTPUT_NOTES_COMMITMENT to
BATCH_NOTE_TREE_ROOT (and the `BatchOutput` field/accessor/layout const
accordingly). The end-goal output is the root of the batch's note tree,
which lets the block kernel aggregate per-batch note trees instead of a
flat output-notes commitment; renaming now fixes the contract name even
though the value is still wired up in a follow-up.

Addresses a review comment on PR #2904.
Take `BatchId` instead of a raw `Word` so the input contract is expressed
through the domain type.
The type holds multiple outputs; rename it for consistency with
`TransactionOutputs`.
Replace `BatchKernel::parse_output_stack` with `BatchOutputs::parse`, and
return `BatchOutputError::OutputStackInvalid` instead of panicking when a
required output word or element is missing from the stack.
Store the parsed `BatchOutputs` on `ExecutedBatch` and expose it via a
typed `batch_outputs()` accessor, replacing the raw `stack_outputs()`.
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-expiration branch from 5972411 to ef11540 Compare June 1, 2026 10:25
Add unit tests for the well-formed stack, non-zero padding rejection, and
oversized expiration block number rejection.
@mmagician mmagician changed the title feat: emit batch_expiration_block_num as the running-min over transactions feat: emit batch_expiration_block_num as the running-min over transactions Jun 1, 2026
@mmagician mmagician changed the title feat: emit batch_expiration_block_num as the running-min over transactions feat(batch kernel): emit batch_expiration_block_num as the running-min over transactions Jun 1, 2026
@mmagician mmagician added kernels Related to transaction, batch, or block kernels pr-from-maintainers PRs that come from internal contributors or integration partners. They should be given priority labels Jun 1, 2026
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-logic branch from 7e97e87 to 7dbd6b7 Compare June 1, 2026 10:42
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-expiration branch from ef11540 to 56363ea Compare June 1, 2026 10:46
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-logic branch from 7dbd6b7 to 5bccee1 Compare June 1, 2026 11:25
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-expiration branch from 56363ea to fc480f2 Compare June 1, 2026 11:26
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-logic branch from 5bccee1 to 133f9bb Compare June 1, 2026 11:38
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-expiration branch from fc480f2 to ea42818 Compare June 1, 2026 11:43
Fill in the batch kernel to verify the batch's transaction list against
its BATCH_ID (Layer 1), verify each transaction header (Layer 2), and
recompute the batch INPUT_NOTES_COMMITMENT from the verified per-tx input
notes (Layer 3). Output-notes (BATCH_NOTE_TREE_ROOT) and the expiration
running-min stay as zero placeholders, wired up in follow-up PRs.
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-logic branch from 133f9bb to 59c2efb Compare June 1, 2026 13:51
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-expiration branch from ea42818 to af57214 Compare June 1, 2026 13:57
claude added 3 commits June 1, 2026 14:20
… injection

Add BatchExecutor::extend_advice_inputs (mirroring TransactionContextBuilder)
so the kernel's rejection paths can be exercised through the normal executor
with tampered advice, and drop the low-level run_kernel test helper. The three
negative tests now corrupt the Layer 1/2/3 advice-map entries via the executor.
Match the operand-stack (# =>) and advice-stack (# AS =>) comment style used
throughout the rest of the protocol assembly.
…tions

The batch kernel accumulates the minimum expiration_block_num across all
transactions (popped per-tx from the advice stack during Layer 2 header
verification) and emits it as the batch_expiration_block_num output.
BatchExecutor cross-checks the kernel's value against the expiration the
ProposedBatch independently derives, erroring with BatchExpirationMismatch
on disagreement.
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-expiration branch from af57214 to b46a277 Compare June 1, 2026 14:24
@mmagician mmagician force-pushed the mmagician-claude/batch-kernel-logic branch from 093ac8e to 622bee3 Compare June 3, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kernels Related to transaction, batch, or block kernels pr-from-maintainers PRs that come from internal contributors or integration partners. They should be given priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants