Repository navigation
Conversation
Adds Rocq proofs, against SpecTec's Wasm 2.0 semantics (the same Wasm2.v Nightstream's formal/wasm-rocq uses), that the local-cleanup rewrites local.set/get -> local.tee, local.tee;drop -> local.set and get/global.get/const;drop -> nothing add no behaviour. The main theorem, invoke_refines in Nested.v: rewrite a store's function bodies with these rules anywhere, at any block depth. Then every run of a call into the rewritten store that ends in values or a trap has a run of the same call into the original store ending in the same result, with final stores equal except for code. The only assumptions are the 55 numeric primitives Wasm2.v leaves abstract, identical to Nightstream's audit.expected. Rules 3, 4 (dead stores) and 6 (local removal) are not yet covered. Signed-off-by: rvcas <x@rvcas.dev>
Extends invoke_refines to all five local-cleanup rules, applied anywhere in function bodies and in any mix. Rules 3 and 4 delete writes to locals the function never reads, so the simulation now relates frames that differ in those locals, and checks that every local.get the two programs share reads one they agree on. Rule 3 deletes a local.tee, which needs a value under it. Without Wasm's type system the proof cannot rule out an original with nothing there, so the theorem now allows a second outcome: the original gets stuck before the end. Validated modules never do. The only assumptions are still the 55 numeric primitives Wasm2.v leaves abstract, identical to Nightstream's audit.expected. Signed-off-by: rvcas <x@rvcas.dev>
| the prover proves the rewritten code. The second case is there because of | ||
| rule 3. Deleting `local.tee` drops an instruction that needs a value under | ||
| it, and without Wasm's type system the proof cannot rule out an original | ||
| with nothing there. Wasm's type soundness rules it out for validated |
Contributor
There was a problem hiding this comment.
I think spectec does have proofs of proofs of progress, btw: https://github.com/Wasm-DSL/spectec/blob/95c256c2c/spectec/test-rocq/theories/type_progress.v#L5853
(with some limitations apparently, but may not matter for our supported subset)
I didn't pull them because I didn't need them. But I think probably we don't need them here neither tbh, I think the property as stated is fine for our case. We don't really care about what the optimizer would do to non validated wasm.
| (* In particular: invoking a function of the rewritten store gives the same | ||
| result as invoking it in the original store, unless the original goes | ||
| wrong, which validated code does not. *) | ||
| Corollary invoke_refines : forall s1 s2 f vs a z2f res, |
Contributor
There was a problem hiding this comment.
Maybe we should also prove that the optimization preserves validation?
So validated wasm -> opt -> validated wasm
Maybe it is trivial/not a concern though.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Rocq proofs that the five local-cleanup rules from #284 add no behaviour:
local.set N; local.get N→local.tee Nlocal.tee N; drop→local.set Nlocal.tee N, where N is never read → nothinglocal.set N, where N is never read →droplocal.get,global.getor a constant, thendrop→ nothingThey are proved against SpecTec's Wasm 2.0 semantics. That is the same
Wasm2.vthat Nightstream'sformal/wasm-rocqproves the Neo-Wasm circuit against, copied verbatim; the copy is 18k of the added lines.The main theorem is
invoke_refinesinstarstream-wasm-opt/rocq/Nested.v.That is the direction that matters here, because the prover proves the rewritten code.
The second outcome is there because of rule 3. Deleting
local.teeremoves an instruction that needs a value under it. Without Wasm's type system, the proof cannot rule out an original that has no value there. Wasm's type soundness rules that out for validated modules, but that theorem isn't proved against these semantics.How the proof works
LocalRewrites.v: each rule on its own. From the same state, the original instructions and their rewrite run to the same configuration.StepInversion.v: every step happens at a configuration's first non-value instruction. This is checked against all of SpecTec's rules.Nested.v: a simulation.local.getthe two programs share reads a local whose value is the same on both sides.Not yet proved
CI doesn't build the proofs yet.
Testing
makebuilds everything in about 40s with the pinned Nightstream toolchain: OCaml 5.3.0, Rocq 9.0.1, MathComp ssreflect 2.4.0, RecordUpdate 0.3.6. The README has the setup.Admitted,admitorAxiomin our files.Print Assumptions invoke_refineslists 55 axioms, all abstract numeric primitives inWasm2.v. The names are identical to Nightstream'sformal/wasm-rocq/scripts/audit.expected.