The aggregate submission entrypoint in ProofRegistry does substantial layout parsing: it reads `AGG_FIELD_NUM_CREDENTIALS`, enforces `2 <= num <= MAX_BATCH_SIZE`, walks per-credential field offsets, matches each issuer pubkey at `field_offset + 1`, and extracts per-credential thresholds. This offset arithmetic is exactly the kind of code that breaks silently if the public-input layout shifts.
Scope
- Add contract tests for the aggregate path:
- Happy path: a well-formed aggregate of 2..MAX credentials stores each claim with the right type/issuer/threshold and emits one event each.
- `num < 2`, `num > MAX_BATCH_SIZE`, and `issuer_ids.len() != credential_types.len()` all revert with `AggregateLayoutInvalid`.
- A mismatched issuer pubkey at a given block reverts with `IssuerKeyMismatch`.
- Threshold extraction per credential is correct for mixed types.
- Use fixtures that exercise the field-offset walking for at least two different credential widths.
Acceptance
- The aggregate path has coverage for the happy path, every layout-rejection branch, and per-credential threshold/pubkey extraction.
The aggregate submission entrypoint in ProofRegistry does substantial layout parsing: it reads `AGG_FIELD_NUM_CREDENTIALS`, enforces `2 <= num <= MAX_BATCH_SIZE`, walks per-credential field offsets, matches each issuer pubkey at `field_offset + 1`, and extracts per-credential thresholds. This offset arithmetic is exactly the kind of code that breaks silently if the public-input layout shifts.
Scope
Acceptance