0xMiden / 0xMiden/protocol

LocalTransactionProver proves precompile claims locally (prove_sync) instead of deferring them (prove_partial_sync)

Offen
#3,835 10 Kommentare 0 Reaktionen 1 zugewiesene Person Beansprucht von @PhilippGackstatter Auf GitHub ansehen
Vorherrschende Sprache
Rust
Sterne
132
Forks
167
Ø Merge
1 T. 23 Std.
Gemergte PRs (30 T.)
110

Beschreibung

`LocalTransactionProver::prove` calls `miden_prover::prove_sync`, the final-proof API, so every local prove also generates the precompile-VM STARK for its deferred claims. Precompile proving is meant to happen at batch level; the local prover should call `prove_partial_sync` and ship the claims as a wire.

**Symptom.** A locally proven transaction whose auth verifies ECDSA signatures carries `DeferredProof::Stark` (~277 KB) next to the ~100 KB VM STARK, and that precompile STARK is 55-72% of local prove time.

**Repro.** Prove any ECDSA-authenticated transaction with `LocalTransactionProver::default()` and match on `proven.proof().deferred_proof()`: it is `Stark { .. }`. Cause: `crates/miden-tx/src/prover/mod.rs:17` imports `prove_sync` and `:148` calls it (same on `next` and 0.16.0-rc.9). `prove_partial_sync` is the documented API for claims "proved later by a delegated or batching prover" (miden-prover 0.29.4, `src/lib.rs:164`).

**Expected.** `DeferredProof::Wire`; the claims are checked natively by the verifier and proven at batch level. On `next` the verifier side already exists: `TransactionVerifier` handles `PrecompileStatus::Deferred` via `validate_deferred_witness` (`crates/miden-protocol/src/transaction/verifier.rs:76-95`), so there the fix is the prover switch plus tests.

**Impact.** Browser local proving (MT wasm, 6 threads) is 3.5x slower than necessary for guarded accounts and 2.8x for single-sig: with the one-line switch, guarded 7.99 s to 2.27 s and single-sig 4.58 s to 1.66 s; native guarded 1.68 s to 0.63 s. The proven transaction shrinks from 391 KB to 104 KB.

On 0.16.0-rc.9 (VM 0.29.4) the switch alone is not deployable: `miden_verifier::verify` returns `UnsupportedDeferredProof` for `Wire`, and both the node RPC (`crates/rpc/src/server/api/submit_proven_tx.rs:108`) and the validator (`bin/validator/src/tx_validation/mod.rs:52`) call `TransactionVerifier::verify`, so a client cannot opt in. Fixing 0.16 needs `TransactionVerifier` to accept partial proofs (`Verifier::verify_partial` exists in 0.29.4; rehydrating the wire re-evaluates every node under the registry, so native settlement is a root check) plus the node picking it up.

Evidence: runtime probes (0.16.0-rc.9 protocol crates, VM 0.29.4, web-sdk 0.16.0-rc.7)

Native, `LocalTransactionProver::default().prove(executed)`, printing `proven.proof().deferred_proof()`:

```
# 2 ECDSA claims (guarded multisig: 1 approver at threshold 1 + guardian)
tx: total_cycles=29095 auth_procedure=19847
DEFERRED_PROOF Stark { proof: 276768 bytes, public_root: Word([10652471043400787702, 12148757343284257120, 17083288024192604590, 7234156251587950621]) }
VM_PROOF 101663 bytes

# 1 ECDSA claim (BasicAuth)
tx: total_cycles=17720 auth_procedure=9865
DEFERRED_PROOF Stark { proof: 283680 bytes, public_root: Word([13415207134405930995, 16485817212495615892, 12092707907113953811, 2871210035726898790]) }
VM_PROOF 99711 bytes

# same two shapes after switching miden-tx to prove_partial_sync
DEFERRED_PROOF Wire (partial, claims NOT proven)
VM_PROOF 100447 bytes # 2 claims
VM_PROOF 100895 bytes # 1 claim
```

Browser, `client.proveTransaction(txResult, TransactionProver.newLocalProver())`, `proven.serialize().length`:

```
single-sig provenTxBytes 378589
guarded provenTxBytes 391045
guarded, prove_partial_sync build provenTxBytes 104118
```

Evidence: code pointers

- `crates/miden-tx/src/prover/mod.rs:17` `use miden_prover::{ExecutionProof, Word, prove_sync};` and `:148` `prove_sync(` (`next` at b5cbb343d; identical in 0.16.0-rc.9).
- miden-prover 0.29.4 `src/lib.rs:123` `prove_sync` (final), `:164` `prove_partial_sync`, `:235-241` `prove_deferred_state` inside the `precompile_vm` span, `:248-258` the wire variant.
- miden-core 0.29.4 `src/proof.rs:261-275` `DeferredProof::{Empty, Wire, Stark}`.
- miden-verifier 0.29.4 `src/lib.rs:177-188` `resolve_final_deferred_root`: `Wire` yields `UnsupportedDeferredProof`; `src/lib.rs:123-135` `verify_partial` returns `Unsettled(DeferredState)`.
- miden-protocol 0.16.0-rc.9 `src/transaction/verifier.rs:33` calls `miden_verifier::verify` (full).
- node `next`: `crates/rpc/src/server/api/submit_proven_tx.rs:108` and `bin/validator/src/tx_validation/mod.rs:52` call `TransactionVerifier::new(MIN_PROOF_SECURITY_LEVEL).verify`.
- web-sdk `crates/web-client/src/new_transactions.rs:713` `LocalTransactionProver::default()` for `newLocalProver()`.

Measurements (M5, 4P+6E; native concurrent; browser MT wasm at 6 threads, 9 timed proves per run after a discarded warm-up, medians)

| shape | prover | native prove | browser prove | proven tx |
|---|---|---|---|---|
| single-sig ECDSA | `prove_sync` (today) | 1376 ms | 4584 ms | 379 KB |
| single-sig ECDSA | `prove_partial_sync` | 602 ms | 1663 ms | ~104 KB |
| guarded (2 ECDSA claims) | `prove_sync` (today) | 1678 ms | 7987 ms | 391 KB |
| guarded (2 ECDSA claims) | `prove_partial_sync` | 630 ms | 2272 ms | 104 KB |

The native `precompile_vm` span accounts for the whole difference (744 ms and 998 ms respectively; 0 ms with the partial API). The guarded premium over single-sig drops from 302 ms to 28 ms, since only the main trace remains and both shapes pad to 2^15 rows.

The one-line switch used for the "partial" rows, applied to 0.16.0-rc.9 and reverted afterwards:

```diff
-use miden_prover::{ExecutionProof, Word, prove_sync};
+use miden_prover::{ExecutionProof, Word, prove_partial_sync};
...
- let (stack_outputs, proof) = prove_sync(
+ let (stack_outputs, proof) = prove_partial_sync(
```

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.