Skip to content

IxVM ingress: panic-on-miss rbtree lookups for ptr_val-keyed maps#472

Draft
arthurpaulino wants to merge 3 commits into
mainfrom
ap/ingress-ptr-lookup-panic
Draft

IxVM ingress: panic-on-miss rbtree lookups for ptr_val-keyed maps#472
arthurpaulino wants to merge 3 commits into
mainfrom
ap/ingress-ptr-lookup-panic

Conversation

@arthurpaulino

Copy link
Copy Markdown
Member

The addr_pos_map / block_start_map lookups are keyed by ptr_val.
Aiur's memory AIR strictly increments the pointer column, so the memory
table is a function ptr -> values: ptr_val equality implies content
equality (no false collisions), but the converse can fail — a malicious
witness may de-intern (same content stored at several pointers), which
the AIR permits. An honest prover interns (the executor dedups store
by content) and so always hits.

Switch the three guaranteed-present probes from
rbtree_map_lookup_or_default(.., 0) to the panic-on-miss
rbtree_map_lookup (no Nil arm — the non-exhaustive match is the
assert-present):

  • lookup_block_start: soundness fix. Its stored values are raw 0-based
    block starts, so 0 is a valid position (the first block), not an
    out-of-band sentinel. A de-interned block_addr would miss, default to
    0, and silently resolve a projection to off instead of
    block_start + off — aliasing the wrong constant. Panic-on-miss
    rejects that witness.

  • lookup_addr_pos / build_ref_idxs_and_blobs: the miss branch was a
    content-based address_eq linear scan that was dead for honest provers
    (same-cell build/lookup makes a miss impossible; augment_with_blob_refs
    keys every ref from the same list cells build_ref_idxs_and_blobs
    probes, and build_convert_inputs passes all_addrs as both the map
    source and the head-address list). Delete the dead scan
    (lookup_addr_pos_linear) and the all_addrs/pos_map params that fed
    it.

No ptr-inequality is used to infer data-inequality anywhere; the
canon_addr_map / visited_set / skip_set / emit_addrs probes keep
_or_default because "absent" is a legitimate branch there.

Regen codegen + re-pin FFT costs (small shifts from the lookup-function
split; measured, not padding — the cost model is whlog2(h) with
h = uniqueRows).

`ix name-of --ixe <path> <hex>`: given a 32-byte hex address,
scan the `.ixe` env's `named` map and print the fully-qualified
Lean.Name of the const stored under that address. Prints an
error + exits 1 if no named const matches (the address might be
an unnamed intermediate constant or a blob).

Complements `ix addr-of` (name → address). Used to backtrack
from an assertion-failure address logged mid-kernel-execution to
the offending Lean constant.
Three interlocking bugs in the Aiur block-flattening / recursor-type
builder caused `ix check --interp bytecode Lean.Syntax.rec` to fail with
`assert_eq mismatch: 0 != 1` on the declared-vs-canonical type equality:

- `build_flat_block` traversed originals once; nested-aux members
  (`Array Syntax`, `List Syntax`) never had their own ctors scanned, so
  `flat` had 2 motives when Lean's recursor declares 3. Replaced with a
  queue-based fixed point mirroring `crates/kernel/src/inductive.rs:
  build_flat_block:531-599`.

- `is_rec_field` classified any ctor field as recursive when its spine
  head Const-idx matched a flat member's ind idx. For `Lean.Syntax.ident`,
  the field `preresolved : List Preresolved` shares the base List const
  idx with the block's `List Lean.Syntax` aux and got a spurious
  `motive_2 preresolved` IH binder. Match key is now (head_idx,
  spine-arg prefix ≡ member.spec_params) — direct members carry
  `spec_params = []` and match on idx alone, auxes require the concrete
  occurrence.

- `build_all_minors` was iterating `flat` and passing the shrinking
  suffix into `build_minor_doms`, so field classification for later
  members was blind to earlier members. Split into a wrapper +
  `build_all_minors_walk` that pins the caller's full flat while the
  iteration state shrinks.

Pin `Lean.Syntax.rec` in the ixvm test suite; rebump every FFT cost
shifted by the codegen refresh (`ix codegen`).
The `addr_pos_map` / `block_start_map` lookups are keyed by `ptr_val`.
Aiur's memory AIR strictly increments the pointer column, so the memory
table is a function ptr -> values: `ptr_val` equality implies content
equality (no false collisions), but the converse can fail — a malicious
witness may de-intern (same content stored at several pointers), which
the AIR permits. An honest prover interns (the executor dedups `store`
by content) and so always hits.

Switch the three guaranteed-present probes from
`rbtree_map_lookup_or_default(.., 0)` to the panic-on-miss
`rbtree_map_lookup` (no `Nil` arm — the non-exhaustive match is the
assert-present):

- `lookup_block_start`: soundness fix. Its stored values are raw 0-based
  block starts, so `0` is a valid position (the first block), not an
  out-of-band sentinel. A de-interned `block_addr` would miss, default to
  0, and silently resolve a projection to `off` instead of
  `block_start + off` — aliasing the wrong constant. Panic-on-miss
  rejects that witness.

- `lookup_addr_pos` / `build_ref_idxs_and_blobs`: the miss branch was a
  content-based `address_eq` linear scan that was dead for honest provers
  (same-cell build/lookup makes a miss impossible; `augment_with_blob_refs`
  keys every ref from the same list cells `build_ref_idxs_and_blobs`
  probes, and `build_convert_inputs` passes `all_addrs` as both the map
  source and the head-address list). Delete the dead scan
  (`lookup_addr_pos_linear`) and the `all_addrs`/`pos_map` params that fed
  it.

No ptr-inequality is used to infer data-inequality anywhere; the
`canon_addr_map` / `visited_set` / `skip_set` / `emit_addrs` probes keep
`_or_default` because "absent" is a legitimate branch there.

Regen codegen + re-pin FFT costs (small shifts from the lookup-function
split; measured, not padding — the cost model is w*h*log2(h) with
h = uniqueRows).
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.

1 participant