Skip to content

MIP-008: Increase events & actions limits for verifier compatibility #2184

@richardpringle

Description

@richardpringle

Summary

MIP-008
proposes raising zkApp event and action limits from 100 to 1024 total
field elements per transaction and removing the per-event/per-action
cap of 16 field elements. This is a hard fork change. The OCaml
reference implementation is at
MinaProtocol/mina#17573.

The Rust verifier currently cannot process post-MIP-008 blocks.
Two changes are required.

Required changes

1. Wire format: remove per-event 16 field element limit

File: crates/p2p-messages/src/v2/generated.rs:2197

// CURRENT - rejects any event with >16 field elements during
// binprot deserialization
pub struct MinaBaseAccountUpdateBodyEventsStableV1(
    pub List<ArrayN16<crate::bigint::BigInt>>
);

ArrayN16 enforces a hard cap of 16 elements per individual
event/action at the deserialization layer. Post-fork blocks containing
events with >16 field elements will fail to deserialize — the
verifier would never even get to process them.

Fix: Change ArrayN16 to an unbounded type (e.g., List<BigInt>
or a new larger-bounded array type). Note: the other ArrayN16
usages in this file (lines ~393-504) are for Pickles proof structures
and must not be changed.

2. Genesis constants: raise total element limit from 100 to 1024

File: crates/ledger/src/scan_state.rs:36-37

// CURRENT - rejects transactions with >100 total field elements
// across all events/actions
max_event_elements: 100,
max_action_elements: 100,

This is checked in valid_size() at
crates/ledger/src/scan_state/transaction_logic/zkapp_command.rs:2847-2848,
which runs both for transaction pool admission and incoming block
validation. Post-fork transactions with up to 1024 elements will be
rejected as invalid.

Fix: Change both values to 1024.

What does NOT need changing

Component Why it's fine
Runtime types (Event, Events, Actions) Already use unbounded Vec<Fp>
Hash computation (events_to_field) Parametric over input size
Snark verification Uses the same hash functions, no hardcoded limits
Conversion code (conv.rs) Maps generically between wire and runtime

Verification path analysis

p2p receive → binprot deser [BLOCKS - ArrayN16]
  → wire→runtime conversion [OK]
  → valid_size() check [BLOCKS - limit 100]
  → hash computation [OK]
  → snark verification [OK]

Additional notes

  • There is no fork-height activation mechanism in the Rust code —
    the constants are hardcoded. The binary with these changes needs to
    be deployed to coincide with the hard fork activation.
  • The OCaml reference implementation (PR #17573) changes two files:
    account_update.ml (remove inner 16 limit) and
    unconfigurable_constants.ml (100 → 1024).
  • MIP-008 status: Finalization (last-call-deadline 2025-10-29).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions