Skip to content

fix(generate-pie): strip VM tracebacks for "callee not deployed" reverts in receipt hashing#518

Closed
Mohiiit wants to merge 1 commit into
mainfrom
fix/strip-vm-traceback-undeployed-revert
Closed

fix(generate-pie): strip VM tracebacks for "callee not deployed" reverts in receipt hashing#518
Mohiiit wants to merge 1 commit into
mainfrom
fix/strip-vm-traceback-undeployed-revert

Conversation

@Mohiiit

@Mohiiit Mohiiit commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Problem

SNOS fails the OS block-hash consistency assertion (block_hash.cairo:79) on blocks containing a transaction that reverts because a called contract is not deployed.

Observed on Paradex mocknet block 138087 (SnosRun batch covering 138086–138090):

OS execution failed: Assertion failed: Calculated block hash 0x71fb0ec7... does not match
expected block hash 0x43fabc6f... (block_hash.cairo:79)

This wedges the orchestrator (the failed SNOS job halts new job creation).

Root cause

The OS does not compute the block-hash commitments itself — the get_block_hashes hint feeds them in from os_input.block_hash_commitments, which SNOS builds in generate-pie. Of the four commitments, only receipt_commitment diverged from the canonical chain value:

commitment SNOS (before) on-chain
transaction 0x13aa89… 0x13aa89…
event 0x5a0a24… 0x5a0a24…
receipt 0x247f69… 0x286ef0…
state_diff 0x55da92… 0x55da92…

The receipt commitment is hashed over the transaction's revert-reason string. For the failing tx (0x37e4ace…), the callee (class hash 0x0) is not deployed, so blockifier renders the caller's VM traceback:

0: Error in the called contract (...):
Error at pc=0:35988:
Cairo traceback (most recent call last):
Unknown location (pc=0:330)
Unknown location (pc=0:11695)

1: Error in the called contract (..., class hash 0x0, ...):
Requested contract address 0x041a78e… is not deployed.

The canonical chain receipt omits that traceback block (822 → 701 chars). But should_strip_vm_tracebacks only stripped tracebacks for the constructor-chain shape (has_constructor_frame && "Execution failed. Failure reason:"). This stack has no Constructor frame, so SNOS hashed the un-stripped 822-char string → wrong receipt_commitment → wrong block hash → assertion failure.

Fix

Extend should_strip_vm_tracebacks to also fire for the "callee not deployed" shape (a StringFrame containing "is not deployed."), so the receipt commitment is hashed over the same stripped string the chain stored. The existing constructor-chain path is unchanged (refactored into a named is_nested_constructor_failure helper for clarity).

Validation

Re-ran generate-pie against the live mocknet RPC for block 138087 (SNOS v0.14.2-rc.2 / sequencer APOLLO-0.14.2-RC.7):

  • revert reason strip_applied=true, 822 → 701 chars
  • receipt_commitment = 0x286ef0…aaf2b5 (matches chain)
  • block hash = 0x43fabc…857f50
  • PIE generation completed successfully — no block_hash.cairo assertion

Tests

cargo test -p generate-pie revert_reason — 11 passed, 0 failed. New:

  • undeployed_contract_revert_strips_vm_tracebacks_for_block_hash
  • transaction_output_uses_stripped_undeployed_revert_reason
  • undeployed_contract_revert_reason_hash_regression — pins the exact 701-char receipt bytes via starknet_keccak (0xc31ec2f2…), the value behind the on-chain receipt_commitment.

Pre-existing revert-reason tests (incl. the non-constructor "keeps tracebacks" case) remain green, so the change is non-regressive.

🤖 Generated with Claude Code

…rts in receipt hashing

The block-hash receipt commitment is hashed over the revert-reason string. For a
contract call whose callee is not deployed, blockifier renders the caller's VM
traceback ("Error at pc=...\nCairo traceback ..."), but the canonical chain
receipt omits it. `should_strip_vm_tracebacks` was gated on a constructor frame
only, so SNOS hashed the un-stripped string, computed a different
receipt_commitment, and therefore a different block hash -- failing the OS
`block_hash.cairo` consistency assertion.

Extend the gate to also fire for the "...is not deployed." shape so the receipt
commitment is computed over the same (stripped) string the chain stored. The
constructor-chain path is unchanged.

Validated against Paradex mocknet block 138087 (tx
0x37e4ace7cf678da99e30d39c32677dd197a7babbd51b4d05e4faccf921cfa8d): the receipt
revert reason goes 822 -> 701 chars, receipt_commitment becomes 0x286ef0...aaf2b5,
block hash becomes 0x43fabc...857f50, and SNOS PIE generation completes (previously
failed at block_hash.cairo:79). Adds a starknet_keccak regression pinning the exact
receipt bytes plus strip/no-strip coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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