Aurel Bílý,João C. Pereira,Jan Schär,Peter Müller
Abstract:Refinement transforms an abstract system model into a concrete, executable program, such that properties established for the abstract model carry over to the concrete implementation. Refinement has been used successfully in the development of substantial verified systems. Nevertheless, existing refinement techniques have limitations that impede their practical usefulness. Some techniques generate executable code automatically, which generally leads to implementations with sub-optimal performance. Others employ bottom-up program verification to reason about efficient implementations, but impose strict requirements on the structure of the code, the structure of the refinement proofs, as well as the employed verification logic and tools.
In this paper, we present a novel refinement technique that removes these limitations. It supports a wide range of program structures, data representations, and proof structures. Our approach supports reasoning about both safety and liveness properties. We implement our approach in a state-of-the-art verifier for the Rust language, which itself offers a strong foundation for memory safety. We demonstrate the practicality of our approach on a number of substantial case studies.
What problem does this paper attempt to address?
The problem that this paper attempts to solve is the limitations of existing refinement techniques in practical applications. Specifically, these limitations include:
1. **Performance issues of automatically generated code**: Some refinement techniques automatically generate executable code, but this code usually has poor performance.
2. **Strict structural requirements**: Other techniques rely on bottom - up program verification methods, which impose strict requirements on code structure, refinement proof structure, and the verification logic and tools used, limiting their flexibility.
To solve these problems, the author proposes a new refinement technique aimed at removing these limitations. The characteristics of the new method are as follows:
- **Support for a wide range of program structures and data representations**: No specific implementation structure is required, and refinement reasoning can be localized to the code locations corresponding to the steps of the abstract model. Therefore, refinement proofs can be added without rewriting the existing implementation, and it can handle multi - threaded processes and distributed systems.
- **Automation and extensibility**: Use off - the - shelf SMT - based deductive verifiers to meet proof obligations and verify safety properties with only a moderate annotation overhead. To ensure extensibility, the method is method - level and thread - level modular.
- **Liveness property verification**: This method can handle the verification of liveness properties in a deductive verification setting by embedding LTL formulas into the assertion language and combining them with obligations, thereby preventing non - termination or lack of progress.
- **Integration and reusability**: This method is implemented in the state - of - the - art general - purpose deductive verifier, and the defined standard library method specifications are reusable and integrated with existing functional safety specifications.
### Specific applications of refinement techniques
The author's method embeds an abstract model (in the form of a transition system) as a ghost state in the implementation and allows the program to obtain a view of the abstract state through a ghost lock and finally release it, indicating which transition has occurred. Each thread in a multi - threaded process or each node in a distributed system has its own ghost lock handle, and the ghost lock is erased at compile time, so it does not provide synchronization. Operations must be linear in order to reason about the behavior of a single node in a modular way.
In addition, the author shows how to combine LTL formulas with obligations to prove safety and liveness properties and applies it to the specific programming language Rust, using its ownership type system to ensure memory safety and maximize performance. In this way, the author's method not only improves the flexibility and practicality of verification but also enables effective verification in complex distributed systems.
### Summary
The main contributions of this paper are:
- Proposing a more flexible refinement verification method that solves the limitations of existing techniques in program structure, automation, and practical integration.
- Introducing a novel local control - flow - sensitive guarded invariant reasoning technique.
- Combining LTL formulas with obligations so that the proofs of safety and liveness properties can be integrated into executable code.
- Implementing this method in the state - of - the - art Rust verifier, providing strong automation capabilities and the ability to reuse general - purpose verification techniques.
- Demonstrating the expressiveness of this method and its ability to adapt to evolving code bases through the evaluation of multiple case studies.
Through these improvements, the author hopes to make refinement techniques more practical and efficient in actual development.