feat(prover): add composable prover interface - #3437
Conversation
|
This PR contains unsigned commits. All commits must be cryptographically signed (GPG or SSH). Unsigned commits:
For instructions on setting up commit signing and re-signing existing commits, see: |
2 similar comments
|
This PR contains unsigned commits. All commits must be cryptographically signed (GPG or SSH). Unsigned commits:
For instructions on setting up commit signing and re-signing existing commits, see: |
|
This PR contains unsigned commits. All commits must be cryptographically signed (GPG or SSH). Unsigned commits:
For instructions on setting up commit signing and re-signing existing commits, see: |
2503624 to
49bbc76
Compare
|
This PR contains unsigned commits. All commits must be cryptographically signed (GPG or SSH). Unsigned commits:
For instructions on setting up commit signing and re-signing existing commits, see: |
49bbc76 to
2ec75c4
Compare
| /// Returns the deferred proof material associated with the Miden VM proof. | ||
| pub const fn deferred_proof(&self) -> &DeferredProof { | ||
| &self.deferred | ||
| impl Deserializable for VmProof { |
There was a problem hiding this comment.
Vec<VmProof> uses Deserializable::min_serialized_size() before allocation, and the default is the 64-byte in-memory size even though the shortest encoding is 34 bytes.
I think we need to override the minima for StarkProof and VmProof (plus optionally an all-settled batch round-trip test) to keep canonical encodings readable.
There was a problem hiding this comment.
I think this concern is still live
There was a problem hiding this comment.
Fixed. StarkProof now reports the minimum size of its encoded byte vector plus hash-function tag, and VmProof composes that with the deferred-root encoding. This gives VmProof its actual 34-byte minimum rather than its 64-byte in-memory size, so budgeted Vec decoding continues to accept compact canonical encodings.
I also added a regression test that checks the reported StarkProof and VmProof minima against their shortest canonical encodings.
|
This PR contains unsigned commits. All commits must be cryptographically signed (GPG or SSH). Unsigned commits:
For instructions on setting up commit signing and re-signing existing commits, see: |
1 similar comment
|
This PR contains unsigned commits. All commits must be cryptographically signed (GPG or SSH). Unsigned commits:
For instructions on setting up commit signing and re-signing existing commits, see: |
487ae98 to
293e599
Compare
293e599 to
9bbc353
Compare
673b3db to
a09439b
Compare
huitseeker
left a comment
There was a problem hiding this comment.
I think the aggregate limit issue is still unsolved as well.
| /// Returns the deferred proof material associated with the Miden VM proof. | ||
| pub const fn deferred_proof(&self) -> &DeferredProof { | ||
| &self.deferred | ||
| impl Deserializable for VmProof { |
There was a problem hiding this comment.
I think this concern is still live
In the above, what's the difference between |
Here, The In contrast, |
|
@huitseeker Agreed that the full aggregate policy was still unresolved. I have split the work into:
This removes the unbounded operations introduced by this PR without defining the broader resource-policy interface in the middle of the prover lifecycle review. |
| } | ||
|
|
||
| impl Deserializable for ExecutionProof { | ||
| impl Deserializable for PrecompileProof { |
There was a problem hiding this comment.
PrecompileProof still inherits the 56-byte in-memory default for min_serialized_size(), although its smallest valid encoding is 35 bytes.
This makes the recommended budgeted decoder reject valid collections: two singleton proofs encode in 71 bytes, but Vec<PrecompileProof>::read_from_bytes_with_budget(..., 71) fails with requested 2 elements but reader can provide at most 1.
We should override the minimum for the required one-root shape (and optionally add a budgeted two-proof round-trip test).
|
|
||
| The deferred-wire canonical decode-and-reencode policy remains unchanged. The outer execution-proof | ||
| decoder now rejects trailing bytes and encodings that do not round-trip exactly. Hydration takes an | ||
| explicit deferred-element bound, and decoding retains its per-allocation ceiling. Merging resets the |
There was a problem hiding this comment.
This paragraph now describes the opposite of 74a5bed7: PrecompileWitness::merge requires max_elements, enforces it across the whole merged state, and caps the list at MAX_PRECOMPILE_ROOTS.
The same stale policy appears in docs/src/design/deferred/semantics.md, and docs/src/design/stack/precompiles.md still shows the old one-argument call.
Can you update all three together?
| roots: Vec<DeferredRoot>, | ||
| } | ||
|
|
||
| let Fields { proof, roots } = Fields::deserialize(deserializer)?; |
There was a problem hiding this comment.
nit: The 4,096-root check in from_parts runs only after this Vec has been fully deserialized, so a serde/Postcard caller can reserve and parse more roots than the cap before rejection.
There's no in-repo serde consumer of PrecompileProof, and the standard ExecutionProof transport uses the early-checked binary decoder, so this is not currently reachable here.
Still, could we either use a bounded visitor or document this serde path as trusted-only?
Summary
Closes #3420.
This PR replaces the intermediate partial-proof APIs with a composable execution-proof lifecycle
built around the upstream canonical
miden_core::program::ExecutionClaim.ExecutionWitness { VmWitness, Option<PrecompileWitness> }artifacts.ExecutionProof::Deferred.supplied STARK, and reports any authenticated outstanding precompile root.
Public lifecycle
ExecutionProofhas two public states:Public construction and serialization preserve representation; they are not cryptographic proof
validation.
ExecutionProof::validate_structureis the shared structural-validation seam used byVerifier::verify. For deferred proofs, verification verifies the VM STARK and returns itsauthenticated precompile root as an outstanding obligation. For complete proofs, it verifies the VM
STARK and any supplied precompile STARK and returns the minimum component security level.
VerificationOutcomeis#[must_use]because successful verification may still leave anoutstanding precompile obligation.
Examples
Complete local proving
VM-first proving and later completion
Migration
miden_core::program::ExecutionClaim; the branch-local competing claim wasremoved. Its encoding, commitment, and recursive-verification semantics are unchanged from Recursive verifier API #3422.
TraceWitnessis now privateTraceReplay.ExecutionTraceis nowVmTrace.execute_trace_inputs*is nowexecute_for_proving*and returnsExecutionWitness.Prover::{prove, prove_full, prove_precompile}instead of the removed async, partial, andtrace-input free proving APIs.
ProvingOptionsis removed. Configure aProverwithwith_hash_fn.prove_sync(&Prover, ...)remains for the optimized overlapped synchronousroute; later Executor work will own this orchestration.
ExecutionProof/DeferredProofenvelope withVmProof,PrecompileProof, andExecutionProof::{Deferred, Complete}.ExecutionProof::completereturnsExecutionProofError; the artifact-recovery completion error isremoved.
Verifier::verify(&claim, &proof)and inspect its#[must_use]VerificationOutcomeinstead of the removed free/partial verification APIs.max_proof_sizeis nowmax_stark_proof_size, clarifying that the limit applies independently toeach inner STARK.
miden_vm::read_execution_proof_from_bytes; custom registries useExecutionProof::read_from_bytes(bytes, registry, max_elements).Transport and resource policy
ExecutionProof::to_bytesandPrecompileWitness::to_bytesare fallible because canonicaldeferred-state materialization may detect an integrity error.
structural and cryptographic validity remains the verifier's responsibility.
StarkProofandVmProofreport their actual minimum encoded sizes so budgeted sequence decodingdoes not reject valid compact encodings.
limit of
1 << 20approximate field elements.Verifierdefaults to 64 MiB for each VM or precompile STARK independently. A configured smalleraccepted-proof limit does not replace the separate 64 MiB per-allocation decoding ceiling.
in Define and enforce aggregate execution-proof resource limits #3458, the successor to planning ticket 022.
Remaining work / non-goals
VmWitnesstransport is obsolete for this PR.Prover::prove_vmis private, this PR has no delegated VM-worker transport dependency, and anyseparate transport work must adapt to the merged API independently.
bounds, merged-witness budgeting, and decoder preallocation policy.
Executor, a protocol settlement envelope, a delegated VM-workerAPI, a new registry identity model, or replacement serde fuzzing.
Suggested review order
core/src/proof.rs,core/src/deferred/witness.rs.processor/src/trace/,processor/src/fast/.prover/src/prover.rs.verifier/src/lib.rs.miden-vm/src/,miden-vm/tests/integration/prove_verify.rs.Validation
Post-rebase branch validation:
RUSTFLAGS=" -D warnings" cargo +stable xclippycargo +nightly fmt --all --checkmiden-vmlifecycle: 2 passed; buffered/overlapped regression stress loop: 50/50 passedmiden-vmrecursive verification: 1 passedmiden-verifier: 10 passedmiden-prover --features concurrent: 5 passedmiden-processorwitness/claim tests: 2 passedmiden-core-libdeferred-root/request-flow recursive tests: 2 passedcargo-shear: passedLatest review-fix validation:
miden-coreproof minimum-size regression: 1 passedmiden-verifier: 10 passedmiden-vmdeferred/merged lifecycle: 1 passedChecklist
nextbefore marking ready.