Skip to content

feat: prove_transaction L2→L1 messages, ProofMode::None behavior change#915

Merged
3alpha merged 7 commits intomainfrom
feat/prove-transaction-l2-to-l1-messages
Apr 9, 2026
Merged

feat: prove_transaction L2→L1 messages, ProofMode::None behavior change#915
3alpha merged 7 commits intomainfrom
feat/prove-transaction-l2-to-l1-messages

Conversation

@3alpha
Copy link
Copy Markdown
Collaborator

@3alpha 3alpha commented Apr 8, 2026

Usage related changes

  • prove_transaction response now includes l2_to_l1_messages extracted via transaction simulation
  • ProofMode::None no longer strips proof_facts — invalid proof_facts will cause ValidationFailure
  • prove_transaction endpoint now accepts full BroadcastedTransaction (not just invoke)

Development related changes

  • Added deploy_l2_msg_contract helper and 3 new integration tests for L2→L1 message extraction and None mode proof_facts validation
  • Fixed invoke_in_proof_mode_none test (block retention buffer, stale gas prices, proof_facts now validated) now when it validates proof_facts.

Checklist:

  • Checked out the contribution guidelines
  • Applied formatting - ./scripts/format.sh
  • No linter errors - ./scripts/clippy_check.sh
  • No unused dependencies - ./scripts/check_unused_deps.sh
  • No spelling errors - ./scripts/check_spelling.sh
  • Performed code self-review
  • Rebased to the latest commit of the target branch (or merged it into my branch)
  • Updated the docs if needed - ./website/README.md
  • Linked the issues resolvable by this PR - linking info
  • Updated the tests if needed; all passing - execution info

Summary by CodeRabbit

  • New Features

    • starknet_proveTransaction now returns L2→L1 messages alongside proof and proof facts.
  • Bug Fixes

    • Enhanced error handling for transaction execution failures during proof generation.
  • Improvements

    • Proof facts expanded to include message hashing verification.
    • Clarified proof_mode=none behavior: validates proof facts while ignoring the proof field.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 8, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e580852d-f5fa-4cd5-a39e-dfd3b4e0479d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'auto_resolve_threads'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

This PR extends the proof generation system to capture and expose L2→L1 messages. Changes include: adding a new ProvingError::TransactionExecutionFailed variant, removing conditional proof-facts adjustment in invoke transaction handling, modifying Starknet::prove_transaction to take mutable self and return an additional Vec<OrderedMessageToL1>, implementing message extraction from transaction simulation in proofs.rs, integrating a messages hash into the proof-facts structure (expanding it from 8 to 9 elements), updating API response models to include the extracted messages, and expanding integration tests to validate message extraction and error handling. Documentation and CLI help text are updated to reflect the proof-facts inclusion in ProofMode::None.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • 0xSpaceShard/starknet-devnet#909: Directly modifies proof-related types and functions (ProvingError, proofs::prove_transaction, Starknet::prove_transaction) that are core to this PR's changes.
  • 0xSpaceShard/starknet-devnet#914: Updates the prove_transaction RPC endpoint and API models (endpoints.rs, ProveTransactionResponse) which intersect with this PR's message-exposure changes.
  • 0xSpaceShard/starknet-devnet#697: Modifies Starknet proving flow and error enums, overlapping with the signature and error-handling changes in this PR.

Suggested labels

enhancement

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarizes the main changes: adding L2→L1 messages to prove_transaction and modifying ProofMode::None behavior regarding proof_facts validation.
Description check ✅ Passed The pull request description includes both Usage related changes and Development related changes sections, covers all significant modifications, and includes a completed checklist confirming standard repository checks were performed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/prove-transaction-l2-to-l1-messages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

- Simulate transactions during proof generation to extract L2→L1 messages
- Add l2_to_l1_messages field to ProveTransactionResponse
- Add messages() and all_messages() accessors to FunctionInvocation
- Change ProofMode::None to ignore proof but preserve and validate proof_facts
- Fix flaky integration test: add block retention buffer and re-fetch gas prices
- Add integration tests for L2→L1 message extraction and proof_facts validation
- Update CLI help text and documentation
@3alpha 3alpha force-pushed the feat/prove-transaction-l2-to-l1-messages branch from eea7639 to 8379968 Compare April 8, 2026 17:11
3alpha added 2 commits April 9, 2026 09:57
…ailure

- Extract proof generation into separate `generate_proof` function
- Add `compute_messages_hash` to bind L2→L1 messages into proof/proof_facts
- Swap order in `prove_transaction`: execute tx first, then generate proof
- Replace silent failure in `extract_l2_to_l1_messages` with
  `ProvingError::TransactionExecutionFailed` for all failure paths
- Add `TransactionExecutionFailed` variant to `ProvingError`
- Update proof_facts from 8 to 9 elements (includes messages_hash)
- Update verify_proof to validate 9-element proof_facts
- Add integration test for execution failure error propagation
@3alpha 3alpha marked this pull request as ready for review April 9, 2026 08:24
@3alpha
Copy link
Copy Markdown
Collaborator Author

3alpha commented Apr 9, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
website/docs/proofs.md (2)

65-69: ⚠️ Potential issue | 🟡 Minor

Request-shape section is outdated for transaction type.

Line 68 still says only broadcasted INVOKE v3, but this PR updates starknet_proveTransaction to accept a full BroadcastedTransaction.

📝 Proposed doc patch
-- `transaction` (a broadcasted `INVOKE v3` transaction payload)
+- `transaction` (a full broadcasted transaction payload)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/docs/proofs.md` around lines 65 - 69, The docs for
starknet_proveTransaction are outdated: update the request-shape description for
the `transaction` parameter to state it accepts a full `BroadcastedTransaction`
(not just a broadcasted `INVOKE v3` payload). Edit the
`starknet_proveTransaction` request-shape section (where `transaction` is
documented) to reference the `BroadcastedTransaction` type and, if present, link
or point to its definition so readers know the exact fields expected.

103-133: ⚠️ Potential issue | 🟡 Minor

Update proof-facts cardinality in docs to 9.

Line 131 still states 8 facts, and the example currently shows 8 entries, but current behavior expects 9.

📝 Proposed doc patch
     "proof_facts": [
       "0x...",
       "0x...",
       "0x...",
       "0x...",
       "0x...",
       "0x...",
       "0x...",
-      "0x..."
+      "0x...",
+      "0x..."
     ],
@@
-`proof_facts` length is expected to be 8 in devnet mode.
+`proof_facts` length is expected to be 9 in devnet mode.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/docs/proofs.md` around lines 103 - 133, Update the docs to reflect
that `proof_facts` length is 9 in devnet mode: change the explanatory sentence
that currently says "expected to be 8 in devnet mode" to "expected to be 9 in
devnet mode" and update the example `proof_facts` array to contain nine entries
(add one more "0x..." entry) so the sample JSON matches current behavior; ensure
the surrounding text referencing `proof_facts` and the adjacent
`l2_to_l1_messages` note remain consistent with this change.
🧹 Nitpick comments (3)
tests/integration/prove_transaction.rs (2)

677-679: Hardcoded nonce may cause test fragility.

The deploy call uses a hardcoded .nonce(Felt::ONE), assuming the declare transaction consumed nonce 0. If the account's initial nonce or declaration behavior changes, this test will fail.

Consider fetching the current nonce dynamically:

♻️ Suggested improvement
+    let provider = account.provider();
+    let nonce = provider
+        .get_nonce(BlockId::Tag(BlockTag::Latest), account.address())
+        .await
+        .expect("Failed to get nonce");
     contract_factory
         .deploy_v3(constructor_calldata, salt, false)
-        .nonce(Felt::ONE)
+        .nonce(nonce)
         .send()
         .await
         .expect("Failed to deploy messaging contract");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/prove_transaction.rs` around lines 677 - 679, The test is
brittle because it hardcodes .nonce(Felt::ONE) for the deploy_v3 call; replace
this with a dynamic read of the account's current nonce (e.g., call the
account/client method that returns nonce or query the chain for the sender's
nonce) and pass that value to .nonce(...) before .send(); locate the deploy
invocation using deploy_v3(constructor_calldata, salt, false) and remove the
Felt::ONE constant so the test computes and uses the up-to-date nonce at
runtime.

871-876: Test removes proof fields but doesn't verify the specific error cause.

The test manually removes proof and proof_facts from the serialized transaction, then expects "Transaction execution failed". However, the error might be due to the invalid contract call (0xdeadbeef), not the missing proof fields. The test setup conflates two potential failure modes.

Consider either:

  1. Using a valid contract call to isolate the "no proof" failure path, or
  2. Clarifying the test name/comment to indicate the primary failure is the invalid contract call
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/prove_transaction.rs` around lines 871 - 876, The test
removes the "proof" and "proof_facts" fields from the serialized transaction
(variable transaction derived from invoke_for_prove) but then may be asserting a
generic "Transaction execution failed" which could instead be caused by the
invalid contract call (0xdeadbeef); either make the contract call valid so the
failure is isolated to the missing proof fields (adjust the invoke_for_prove
setup to use a known-good contract/address) or change the test assertion and
name/comment to explicitly expect the invalid-contract failure (or explicitly
assert for a "missing proof" error string) so the test no longer conflates the
two failure modes.
crates/starknet-devnet-core/src/starknet/proofs.rs (1)

134-171: Consider handling reverted transactions more explicitly.

The current implementation only returns messages for ExecutionInvocation::Succeeded. For reverted transactions, it returns an error. This is likely the intended behavior since reverted transactions shouldn't produce valid L2→L1 messages, but consider whether the error message could be more informative.

♻️ Optional: More informative error for reverted executions
         if let ExecutionInvocation::Succeeded(func) = invoke_trace.execute_invocation {
             return Ok(func.all_messages());
         }
-        return Err(ProvingError::TransactionExecutionFailed(
-            "invoke execution did not succeed".to_string(),
-        )
-        .into());
+        // Handle reverted case explicitly for better error messages
+        if let ExecutionInvocation::Reverted(reverted) = invoke_trace.execute_invocation {
+            return Err(ProvingError::TransactionExecutionFailed(
+                format!("invoke execution reverted: {}", reverted.revert_reason),
+            )
+            .into());
+        }
+        return Err(ProvingError::TransactionExecutionFailed(
+            "invoke execution did not succeed".to_string(),
+        )
+        .into());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/starknet-devnet-core/src/starknet/proofs.rs` around lines 134 - 171,
The function extract_l2_to_l1_messages currently treats any non-Succeeded invoke
as a generic failure; update the handling of the invoke trace (the match on
TransactionTrace::Invoke and the check of invoke_trace.execute_invocation) to
explicitly match other ExecutionInvocation variants (e.g., Failed/Reverted) and
return a more informative ProvingError that includes the execution status and
any available failure reason or revert messages from invoke_trace (use
invoke_trace.execute_invocation and any error/revert fields on invoke_trace or
the ExecutionInvocation variant) so callers can see that the transaction
reverted and why instead of a generic "did not succeed".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration/prove_transaction.rs`:
- Around line 765-768: The assertion incorrectly expects the L2→L1 message
from_address to be the account; update the check to assert that
result.l2_to_l1_messages[0].from_address equals the messaging contract address
(contract_address) because send_message_to_l1 sets from_address to the calling
contract (the deployed messaging contract used by withdraw()). Replace the
assert comparing msg.from_address to account.address() with one comparing it to
contract_address and keep the other assertions unchanged.

---

Outside diff comments:
In `@website/docs/proofs.md`:
- Around line 65-69: The docs for starknet_proveTransaction are outdated: update
the request-shape description for the `transaction` parameter to state it
accepts a full `BroadcastedTransaction` (not just a broadcasted `INVOKE v3`
payload). Edit the `starknet_proveTransaction` request-shape section (where
`transaction` is documented) to reference the `BroadcastedTransaction` type and,
if present, link or point to its definition so readers know the exact fields
expected.
- Around line 103-133: Update the docs to reflect that `proof_facts` length is 9
in devnet mode: change the explanatory sentence that currently says "expected to
be 8 in devnet mode" to "expected to be 9 in devnet mode" and update the example
`proof_facts` array to contain nine entries (add one more "0x..." entry) so the
sample JSON matches current behavior; ensure the surrounding text referencing
`proof_facts` and the adjacent `l2_to_l1_messages` note remain consistent with
this change.

---

Nitpick comments:
In `@crates/starknet-devnet-core/src/starknet/proofs.rs`:
- Around line 134-171: The function extract_l2_to_l1_messages currently treats
any non-Succeeded invoke as a generic failure; update the handling of the invoke
trace (the match on TransactionTrace::Invoke and the check of
invoke_trace.execute_invocation) to explicitly match other ExecutionInvocation
variants (e.g., Failed/Reverted) and return a more informative ProvingError that
includes the execution status and any available failure reason or revert
messages from invoke_trace (use invoke_trace.execute_invocation and any
error/revert fields on invoke_trace or the ExecutionInvocation variant) so
callers can see that the transaction reverted and why instead of a generic "did
not succeed".

In `@tests/integration/prove_transaction.rs`:
- Around line 677-679: The test is brittle because it hardcodes
.nonce(Felt::ONE) for the deploy_v3 call; replace this with a dynamic read of
the account's current nonce (e.g., call the account/client method that returns
nonce or query the chain for the sender's nonce) and pass that value to
.nonce(...) before .send(); locate the deploy invocation using
deploy_v3(constructor_calldata, salt, false) and remove the Felt::ONE constant
so the test computes and uses the up-to-date nonce at runtime.
- Around line 871-876: The test removes the "proof" and "proof_facts" fields
from the serialized transaction (variable transaction derived from
invoke_for_prove) but then may be asserting a generic "Transaction execution
failed" which could instead be caused by the invalid contract call (0xdeadbeef);
either make the contract call valid so the failure is isolated to the missing
proof fields (adjust the invoke_for_prove setup to use a known-good
contract/address) or change the test assertion and name/comment to explicitly
expect the invalid-contract failure (or explicitly assert for a "missing proof"
error string) so the test no longer conflates the two failure modes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c2ad11f2-2589-44bb-bf93-c02c412c2eb3

📥 Commits

Reviewing files that changed from the base of the PR and between fe4cb6c and dc26f96.

📒 Files selected for processing (12)
  • crates/starknet-devnet-core/src/error.rs
  • crates/starknet-devnet-core/src/starknet/add_invoke_transaction.rs
  • crates/starknet-devnet-core/src/starknet/mod.rs
  • crates/starknet-devnet-core/src/starknet/proofs.rs
  • crates/starknet-devnet-server/src/api/endpoints.rs
  • crates/starknet-devnet-server/src/api/models/mod.rs
  • crates/starknet-devnet-types/src/rpc/transactions.rs
  • crates/starknet-devnet/src/cli.rs
  • tests/integration/common/background_devnet.rs
  • tests/integration/get_transaction_by_hash.rs
  • tests/integration/prove_transaction.rs
  • website/docs/proofs.md

Comment thread tests/integration/prove_transaction.rs
@3alpha 3alpha merged commit 6ee8c9c into main Apr 9, 2026
6 checks passed
@3alpha 3alpha deleted the feat/prove-transaction-l2-to-l1-messages branch April 9, 2026 12:20
@3alpha 3alpha mentioned this pull request Apr 14, 2026
10 tasks
@3alpha 3alpha added the enhancement New feature or request label Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant