‹ BackHN Continuity

Thread

Developing provably correct Rust code with Verus

161 points · 78 comments · Betelbuddy

Loading the complete thread in the background. This saved snapshot is available now. Refresh

  1. sourdecor · · focus · HN ↗
    Verus seems to be exactly what I have been looking for! I discovered AllConcur[0] on HN a while back, and I wanted to port it to Go, but since it used TLA+ and C, and it was very confusing for me to understand how you can trust the implementation unless you can compile TLA+ to C.

    I was talking to Gemini about comparing Verus to TLA+ and it said that TLA+ is usually used (for example) "to prove that a distributed consensus protocol is logically sound" but when I asked if Verus can do that too, it said yes. So Verus can be compiled and integrated with Rust, whereas TLA+ is used more for blueprint development that then guides the implementation in the mind of the implementer.

    Seems awesome!

    [0]: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12357976">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12357976

    1. japgolly · · focus · HN ↗

      [dead]

    2. pjmlp · · focus · HN ↗
      That is my pet peeve against TLA+ advocacy, the disassociation between a theoretical proof of a specific algorithm, data structures, and the actual implementation in production.

      I rather push for tooling that allows code generation based on the formal proofs like FStart or Dafny, or is integrated with specific programming languages like SPARK, Frama-C or this Verus.

      1. igornotarobot · · focus · HN ↗
        You can write everything in Lean and generate an implementation. Given that LLMs can now generate Lean proofs, this does not seem to be prohibitively expensive anymore. The real issue with distributed algorithms is that they are hard to reason about, and reasoning about them at the code level does not make the verification problem easier, it makes it harder.
      2. kreneskyp · · focus · HN ↗
        I&#x27;m working on a ISO-29148 aligned spec standard with formal modelling baked in. It&#x27;s meant to sit above the code with types, contracts, proofs and other objects that lower mechanically into code and&#x2F;or are deterministically verified.

        I&#x27;m targeting Rust primarily but my goal is that any language could sit under it via an integration layer.

        <a href="https:&#x2F;&#x2F;github.com&#x2F;agent-ix&#x2F;quoin" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;agent-ix&#x2F;quoin

        The first public version of the formal specification standard isn&#x27;t available yet. Pushing hard to get it out soon! But Quoin ships with an earlier version of the spec standard. It features derived property tests, which was the POC for fully adopting a formal-spec-to-derived-formal-verification ecosystem.

        1. pjmlp · · focus · HN ↗
          Thanks for sharing, always like to learn about this stuff.
    3. jgalt212 · · focus · HN ↗
      &gt; as very confusing for me to understand how you can trust the implementation unless you can compile TLA+ to C.

      Preach. I feel like I&#x27;m taking crazy pills every time someone claims TLA+ as the sine qua non of provably correct systems. They should sub probably for provably.

      1. zozbot234 · · focus · HN ↗
        There is no contradiction here, TLA+ is mostly about proving properties of toy models, not end-to-end proofs about real programs. As TLA+ practitioners like to point out, the latter is only applicable to favorable &quot;local&quot; properties - this is what type systems do, they state claims that are quite aligned with the program&#x27;s syntactic structure; or else to rather trivial programs where proving &quot;whole-program&quot; claims is still feasible. Even Verus itself doesn&#x27;t really change this.
      2. digilypse · · focus · HN ↗
        Isn’t the value in being able to verify the design before implementing? It would be more ideal surely to prove correctness of the deployed code, but I still find it very useful.
        1. jgalt212 · · focus · HN ↗
          &gt; Isn’t the value in being able to verify the design before implementing?

          Fair enough, but to be truly safe you really need the whole pipeline connected. model -&gt; validation -&gt; emitted code.

  2. kobahiro · · focus · HN ↗

    [dead]

  3. jdw64 · · focus · HN ↗
    That&#x27;s fascinating. Does it mean it verifies mathematical proofs directly within the Rust code? Does anyone know the underlying principles of how this is possible?
    1. Jtsummers · · focus · HN ↗
      [delayed]
      1. jdw64 · · focus · HN ↗
        thanks!
    2. kite42 · · focus · HN ↗
      All it does is dispatch proof obligations to an SMT solver like Z3. There is nothing special about Verus, it works in the same way other program verification frameworks like Dafny and Frama-C work - except it&#x27;s for Rust. Most of this article presents nothing unique to Verus and is more of an advertisement for the authors research work and the other work AWS is doing.
      1. anonymousDan · · focus · HN ↗
        I like how they also neglected to mention that Verus was invented at Microsoft...
        1. hwayne · · focus · HN ↗
          Not the first time Microsoft employees invented a formal methods tool, Microsoft ignored them, and AWS scooped them up. Not the second or third time, either.
          1. anonymousDan · · focus · HN ↗
            I don&#x27;t think it&#x27;s entirely fair to say they ignored them. As far as I know they are still employed at Microsoft Research and working on developing and improving the tool?
  4. canadiantim · · focus · HN ↗
    This seems like a big deal
  5. jongjong · · focus · HN ↗
    What if the &#x27;mathematical specification of its functionality&#x27; is incorrect? How to prove the correctness of the mathematical specification faster than the underlying environment, code and dependencies change?

    IMO, formal verification is never going to work. It&#x27;s very clear that a lot of people are desperate to see it used in mainstream software development, but every innovation which proponents have seen as an opportunity to finally prove its utility has only served to further discredit it.

    Now proponents are at a point that they literally have to convince us that people who aren&#x27;t able to write correct code are somehow able to write correct mathematical specifications!

    This is quite an extraordinary claim given that the mathematical specification is an order of magnitude longer and more complex than the code itself... And every experienced software engineer knows that mistakes grow proportionally to the size of the logic... Unfortunately, mathematical spec is logic; just like code, except it&#x27;s more complex and thus more error-prone.

    And don&#x27;t even get me started on the fact that APIs, engines and languages change constantly from under you and thus the mathematical spec would get completely invalidated every week or so each time you did an update. Unfortunately, even in the best case scenario, reality is always going to change and invalidate our proofs faster than we can publish them. By the time you&#x27;ve proven the theory, its underlying assumptions already ceased to hold true.

    Even in a far simpler world, the software&#x27;s execution would change the reality which it relied on to prove its own correctness and would thus invalidate its own correctness.

    1. gr_norm · · focus · HN ↗
      &gt; How to prove the correctness of the mathematical specification?

      You can show that your specifications satisfy well-accepted criteria like confidentiality and integrity. This is usually done as the final verification step. For example, AWS just did it for the Nitro hypervisor used by EC2: <a href="https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;compute&#x2F;aws-nitro-isolation-engine-formally-verifying-the-hypervisor-in-the-aws-nitro-system" rel="nofollow">https:&#x2F;&#x2F;aws.amazon.com&#x2F;blogs&#x2F;compute&#x2F;aws-nitro-isolation-eng....

    2. stevenhuang · · focus · HN ↗
      So it moves from both &quot;my implementation and specification is incorrect&quot;, to just &quot;my specification is incorrect&quot;.

      I don&#x27;t understand this type of thinking. Proving what you can is still better. Don&#x27;t let perfect be the enemy of good.

      1. jongjong · · focus · HN ↗
        &gt;&gt; Don&#x27;t let perfect be the enemy of good.

        I feel like the exact same line could be used to argue the opposite point against formal verification.

        I&#x27;m not saying that proof is inherently bad. If it was free, then I agree it would be good, but my point is that it&#x27;s not free, proofs are expensive to produce, maintain, they lock-down flawed implementations, discourage change and they create false confidence about reliability because sometimes the bug is in the spec itself, especially as the spec gets more complicated.

    3. atoav · · focus · HN ↗
      [delayed]
    4. lou1306 · · focus · HN ↗
      &gt; people who aren&#x27;t able to write correct code are somehow able to write correct mathematical specifications

      This describes about one or two thirds of the Theoretical CS academic community (conservative estimate) &#x2F;s

      &gt; This is quite an extraordinary claim given that the mathematical specification is an order of magnitude longer and more complex than the code itself

      I find this hard to believe. The mathematical specification for &quot;array a is sorted&quot; is &quot;forall n in Nat: 0 &lt; n &lt; len(a) -&gt; a[n] &gt;= a[n+1]&quot;. The average sorting algorithm is usually a tad longer than this.

      &gt; the mathematical spec would get completely invalidated every week or so each time you did an update

      Well of course nobody serious advocates for formalizing&#x2F;verifying code that is subject to that much churn (be it internal or external).

    5. imtringued · · focus · HN ↗
      Nothing forces developers to write a complete specification of the algorithm. You want to have it both ways. If developers keep the spec concise but incomplete, then you say the spec is incorrect so now you have to prove that the spec is correct. Ok, but people already use unit tests to sample the behaviour of a function so they already accept some degree of inaccuracy. By your logic you have to enumerate the entire input space otherwise unit testing is worthless.

      If developers decide to build a complete specification of the algorithm, you counter that the specification is now too long so they should not bother.

      You are basically arguing with yourself.

      The update argument doesn&#x27;t make sense either, because you generally want to prove properties like absence of panics throughout your entire codebase. Again this is just a roundabout way of arguing against the very idea of a tradeoff.

  6. homarp · · focus · HN ↗
    see also <a href="https:&#x2F;&#x2F;lean-lang.org&#x2F;use-cases&#x2F;aeneas&#x2F;" rel="nofollow">https:&#x2F;&#x2F;lean-lang.org&#x2F;use-cases&#x2F;aeneas&#x2F; <a href="https:&#x2F;&#x2F;github.com&#x2F;AeneasVerif&#x2F;aeneas" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;AeneasVerif&#x2F;aeneas (by Microsoft)
  7. m00dy · · focus · HN ↗
    &gt;&gt;The result is fast code that&#x27;s more correct and secure than average.

    Welcome to Rust

    1. Ohentis · · focus · HN ↗
      I mean... rust alone doesn&#x27;t have this feature. And many languages have a &quot;slap z3 onto it&quot; tool.
  8. m00dy · · focus · HN ↗
    Ive been using Rust with LLMs for the past 2 years already. It&#x27;s just amazing, I can&#x27;t really think anything else to code with. Normally, been testing my codes unit tests + integration tests where necessary. But, I will take a look at this seriously.
  9. m00dy · · focus · HN ↗
    I just read the whole thing, the post would be even better if it includes an example for concurrency. It&#x27;s not easy to imagine it just by looking at the binary search&#x27;s example.
    1. gregwebs · · focus · HN ↗
      They have separate machinery for concurrent code: <a href="https:&#x2F;&#x2F;verus-lang.github.io&#x2F;verus&#x2F;state_machines&#x2F;intro.html" rel="nofollow">https:&#x2F;&#x2F;verus-lang.github.io&#x2F;verus&#x2F;state_machines&#x2F;intro.html
  10. Meneth · · focus · HN ↗
    &quot;Beware of bugs in the above code; I have only proved it correct, not tried it.&quot; - Donald Knuth.
  11. nottorp · · focus · HN ↗
    Would it help with the bugs in the new and improved ubuntu coreutils?
    1. Betelbuddy · · focus · HN ↗
      It will prove the bugs were corrected implemented... :-) And that your mistaken specifcsation of the tax rules in Switzerland were correctly translated to code, and that your mistaken specification of the process to request a mortgage is mathematically valid...

      Jesus, I cant stand formal methods people...

      1. nottorp · · focus · HN ↗
        I was picking mostly on the rust religion at first. But then I looked things up and ran into <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Rice%27s_theorem" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Rice%27s_theorem …
        1. cmrx64 · · focus · HN ↗
          naive applications of this would lead you to believe no knowledge is possible, and that progress is not meaningful when liveness can’t be guaranteed.

          it’s all rubbish, grandparent is a small mind who can’t figure out how it’s a step up from nothing.

          1. svieira · · focus · HN ↗
            I wouldn&#x27;t say it&#x27;s all rubbish - it&#x27;s very easy for someone new to theorem proving to presume the equivalent of &quot;strong typing will eliminate the possibility of errors&quot;, but the more correct understanding is &quot;strong typing will reduce the number of things you have to keep in your head at any one time thus reducing the possibility of errors&quot;.
            1. nottorp · · focus · HN ↗
              The thing with ubuntu&#x27;s rust coreutils is that they, for example, crash when told to recurse because they use actual recursive calls to go into subdirs and run out of stack space if the structure is big enough.

              What formal correctness proof will detect that?

              1. cmrx64 · · focus · HN ↗
                any of the quite many cost-aware logical frameworks. it’s SO. easy. to. do. you fools are just willfully ignorant on how to represent reasoning, despite alleging yourselves to be computer scientists?
      2. Jtsummers · · focus · HN ↗
        [delayed]
        1. Betelbuddy · · focus · HN ↗
          Testers are not selling guarantees...
          1. Jtsummers · · focus · HN ↗
            [delayed]
            1. Betelbuddy · · focus · HN ↗
              Oh my my...

              &quot;Program testing can be used to show the presence of bugs, but never to show their absence&quot;

                -  Edsger Dijkstra
              1. Jtsummers · · focus · HN ↗
                [delayed]
                1. Betelbuddy · · focus · HN ↗
                  You are trying to convince me that because you pressed &quot;A&quot; once on the vending machine and worked, you declare &quot;A&quot; is proven to dispense Coke...
                  1. Jtsummers · · focus · HN ↗
                    [delayed]
                    1. Betelbuddy · · focus · HN ↗
                      Have you considered a career is stand up comedy?

                      The quote from Dijkstra stands on its own...quoting a famous person stating something independently demonstrable, does not magically turn the statement into an appeal to authority :-))

                      &gt;&gt; a man who was a major proponent of formal methods.

                      No he was not, but you see, its irrelevant in the context of the argument you failed to defend.And Dijkstra fails you purity test. He himself wrote that he saw &quot;no specific virtue in being a formalist&quot; and would use formal methods &quot;when I feel they help.&quot;

          2. rcxdude · · focus · HN ↗
            Tests are guaranteeing that the product doesn&#x27;t fail under the test conditions. Formal verification is guaranteeing the product doesn&#x27;t deviate from the formal spec under a given set of assumptions. Both of them are useful but depend on how well the thing being checked actually correlates with what you care about.
            1. Betelbuddy · · focus · HN ↗
              Interesting definition of guarantee....what about the people who run millions of them? Well Microsoft: &quot;AS IS.&quot; Apple: &quot;WITH ALL FAULTS&quot; Adobe: &quot;no guarantee of error-free operation.&quot;

              Apparently their lawyers never got the memo that the tests already guaranteed the software...

              1. rcxdude · · focus · HN ↗
                Well yeah, why would they guarantee if they don&#x27;t have to?
  12. lukeify · · focus · HN ↗
    Reminds me of Whiley, which was developed by one of my university professors.
  13. bcjdjsndon · · focus · HN ↗
    &gt; With Verus, however, developers can mathematically prove the safety of their unsafe Rust code, re-establishing machine-checked safety guarantees

    Why then does rust even need the unsafe keyword?

    1. ijustlovemath · · focus · HN ↗
      I&#x27;d rather have all the unsafe code scoped and the safety invariants explained that the alternatives. You still can&#x27;t do a whole class of scary things in an unsafe block; common misconception
      1. bsaul · · focus · HN ↗
        That&#x27;s indeed a weird feeling when going back to another language after having coded in rust. First you&#x27;re happy not having to write any &quot;unsafe&quot; keyword. Then you&#x27;re horrified for the very same reason.
      2. bcjdjsndon · · focus · HN ↗
        Yeah but if this program can prove unsafe code is safe... Why can&#x27;t rust compiler do it, and hence, why do we even need unsafe if the compiler can do it.
        1. Jtsummers · · focus · HN ↗
          [delayed]
        2. ijustlovemath · · focus · HN ↗
          It generates additional code that&#x27;s fed into an SMT solver. Poor compiler performance is a top issue developers have with Rust, which they&#x27;re working to solve. I think adding this layer into every piece of code (which is probably impossible since inferring the invariants is essentially inferring your business logic) would eat away gains they&#x27;ve achieved.

          I also think the functional style, typestate, and borrow checker is enough for writing correct code across many business domains, so there&#x27;s no need to add this to your toolchain. We are a med device company building a class III (really 3 class II) device, and Verus is making our verification story extremely compelling.

    2. hwayne · · focus · HN ↗
      There&#x27;s a huge difference between &quot;Verus can prove the safety of unsafe code&quot; and &quot;Verus can EASILY prove the safety of unsafe code.&quot; And I bet it can&#x27;t prove everything, like calls to a C ABI.
    3. afdbcreid · · focus · HN ↗
      Because Rust is not Verus, and not all unsafe code needs formal-verification-level of rigorousness. Also, there are other verifiers as well.
  14. 112233 · · focus · HN ↗
    &gt; With Verus, however, developers can mathematically prove the safety of their unsafe Rust code

    what about proving safety of not-unsafe code? The meme that rust is &quot;safe&quot; is becoming tiring. Does this thing allow proving absence of infinite loops? Bounded resource use? Correctness of comparison operations? Etc.

    Also, why is there still no hardware tagging to simply prevent memory misuse at cpu level, if it actually is such an important issue?

    1. ijustlovemath · · focus · HN ↗
      What exactly is your objection? Rust doesn&#x27;t solve the halting problem? You can absolutely prove bounded resource use with eg SmallVec and arenas
      1. 112233 · · focus · HN ↗
        Objection was against &quot;memory safety&quot; somehow having become &quot;safety&quot;. Here is an epic tool that allows one to attach and formally prove assertions. Genuinely impressive and massively useful.

        Yet the pitch is that it is needed for the &quot;unsafe&quot; unsafe code, to make it &quot;safe&quot;. Not for all code, to make all code safe.

  15. 63 · · focus · HN ↗
    If you found this interesting, you may also be interested to hear about some related projects with similar goals&#x2F;scopes: Miri[0], Kani[1], and Creusot[2]. There looks to be some significant overlap between Verus, Kani, and Creusot but I&#x27;ve not used any of them so I&#x27;ll refrain from trying to differentiate them.

    [0]<a href="https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri

    [1]<a href="https:&#x2F;&#x2F;github.com&#x2F;model-checking&#x2F;kani" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;model-checking&#x2F;kani

    [2]<a href="https:&#x2F;&#x2F;github.com&#x2F;creusot-rs&#x2F;creusot" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;creusot-rs&#x2F;creusot

    1. gregwebs · · focus · HN ↗
      Miri: proves pre-defined properties, no changes to code other than adding a few annotations

      Kani: use in a test suite

      Creusot: annotations

      Verus: annotations or macro

      The macro system looks very nice if it doesn&#x27;t slow down the normal build.

      1. gregwebs · · focus · HN ↗
        AI tells me that code using the verus! macro everywhere would double in build time but if only used ocassionally the verus! macro would only increase build time by a few percent. The attribute annotation would basically be free, but there is a downside that loop invariants would be rejected by stable rustc.
  16. MeetingsBrowser · · focus · HN ↗
    I have long been critical of verification tools requiring annotations. Humans cannot write correct code, so asking them to write correct proof annotations seems futile.

    But maybe this changes in the age of LLMs. A deterministic check to let LLMs verify the correctness of an API could improve the success rate of large scale refactors or performance optimizations.

    Exciting!

    1. afdbcreid · · focus · HN ↗
      You seem to have misunderstood the idea. The entire idea of proof annotations is that they are not manual. Rather, the verifier checks you fulfill the preconditions for the method you calls, and it checks inside the method that if the preconditions are fulfilled then the postconditions are too. This just helps the verifier reason locally. At the end besides more burden, the only thing you really need to check is the top-level annotations, like any formal verifier.
      1. MeetingsBrowser · · focus · HN ↗
        &gt; the only thing you really need to check is the top-level annotations

        Sorry if I wasn’t clear.

        My point is that the annotations are manual and inherently prone to error.

        If humans could correctly write annotations according to a spec, we wouldn’t need verifiers at all. We could just write correct code directly.

        There is an argument to be made that the annotations are a smaller surface than full blown code and therefore easier for humans to reason about.

        However, in practice formal verification tools and annotations are far more obscure than regular code.

        Most people writing annotations have a PhD in some field adjacent to formal verification.

        1. rcxdude · · focus · HN ↗
          the vast majority of such annotations are checked though. There&#x27;s generally three kinds of annotations in formal proof systems: assertions about inputs that cannot be checked by the system, statements of propositions that want to be checked, and proofs that those propositions follow from the assertions. The proofs are checked by the system, so writing them is mainly just tedious and difficult, not really a source of error. What needs to be verified carefully is that the assertions are true, and that the propositions actually correlate with what people actually want out of the system. The mark of how effective a formal verification system is is in how strong of a proposition can be proven from how small a set of assertions. (well, and then how difficult it is to write the proofs).
          1. MeetingsBrowser · · focus · HN ↗
            &gt; the propositions actually correlate with what people actually want out of the system

            My point is that this is the hard part, and writing annotations does nothing to help with this problem.

            1. rcxdude · · focus · HN ↗
              To me it seems easier than proving the code does something useful without pinning down what that actually is.
              1. MeetingsBrowser · · focus · HN ↗
                I agree on paper, but in practice most verification annotations in real code require a PhD to understand.

                To me, it’s essentially implementing the same code twice in two languages and checking the behavior matches.

                If the same person implements both, what are the odds they implement the same bug in both?

                Only verification annotations are generally even harder to read and write than the code itself, making it even more difficult to tell if you implemented the proof according to the spec, or just mirrored what the function actually does.

        2. afdbcreid · · focus · HN ↗
          You were clear, and you were wrong. The annotations are checked like I said, you cannot break the guarantees using them. If they&#x27;re incorrect they won&#x27;t pass verification. They just help the verifier.
          1. MeetingsBrowser · · focus · HN ↗
            Sorry I’ll try to put it simply.

            Programmer intends to write code that does Y, but writes code that does X. Then they make the same mistake again and write an annotation that verifies the function does X.

            Verification passes, but the code does the wrong thing.

            1. afdbcreid · · focus · HN ↗
              Unless the function is a public API and unused in the library (i.e. if the function is used by code that expects it to do Y), it won&#x27;t pass verification.

              If it is public API, it indeed can pass. This is similar to theorem provers - if you get your axioms or theorems wrong, you can incorrectly &quot;prove&quot; things. But verifiers are still useful because most of the code has larger internal surface than external surface.

    2. rzmmm · · focus · HN ↗
      I think it provides best bang for buck when the annotation is &quot;obviously correct&quot; but the implementation is complex.

      For example if you are trying to prove that your new sorting algorithm yields sorted list for all inputs.

      If there is as much annotations as there is code, then testing is better tool for the job than verification.

  17. freethinky · · focus · HN ↗
    Does anyone now if something like this exist for .NET&#x2F;C#, not like Dafny where I write in another language (unlikely my company would allow that). Also as annotations (likely that I can start with it).
    1. genxy · · focus · HN ↗
      You might see if this nascent CLR backend to Rust can do what you need <a href="https:&#x2F;&#x2F;github.com&#x2F;FractalFir&#x2F;rustc_codegen_clr" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;FractalFir&#x2F;rustc_codegen_clr
  18. reddit_clone · · focus · HN ↗
    This is very interesting.

    I am new to Rust and also new to formal verification.

    Can someone ELI5 this for me?

    (Also, when does the proof happen? During compilation or by running extra tests during unit testing?)

    1. Jtsummers · · focus · HN ↗
      [delayed]
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.