runtimeverification / runtimeverification/kontrol
[cse] Precondition Refinement
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 122
- Forks
- 16
- PR merge metrics
- No merged PRs in 30d
Description
Background
Presently, the CSE initiates symbolic execution from the call graph's leaf nodes progressing towards the root (enabled by the --cse option). The contract execution commences either from the symbolic values of its parameters or from the state post-execution of the constructor (using --run-constructor). This approach results in overly abstract initial states for the functions, making it exceedingly time-consuming to determine the final states of the functions. Consequently, this prevents us from synthesizing reusable function summaries.
Running Example
Using DualGovernance.activateNextState() as an example, the ActivateNextStateTest.testActivateNextStateTermination serves as a test harness for this function. The current situation is as follows:
kontrol prove ActivateNextStateTest.testActivateNextStateTermination: The proof is successful. The process starts from the root of the call graph, executing the constructor andsetUpbefore runningtestActivateNextStateTermination, and finally invokingactivateNextState.- Adding
csewithkontrol prove ActivateNextStateTest.testActivateNextStateTermination --cse: The proof fails. This failure occurs becauseDualGovernance.activateNextState()is symbolically executed without calling the constructor andsetUp, resulting in a PROOF-FAILED outcome forDualGovernance.activateNextState(). Consequently,ActivateNextStateTest.testActivateNextStateTerminationinherits this failure when it uses the summary, leading to its own failure. This indicates that we should not executeactivateNextStatefrom the most abstract state to obtain its summary, i.e.,kontrol prove DualGovernance.activateNextState. - Adding
--run-constructorwithkontrol prove DualGovernance.activateNextState: Verification out-of-time or out-of-memory. While the function inputs are correctly configured by the constructor, the state includes improbable and unreasonable conditions that can arise during function calls. The excessive branching states prevent termination. Even if termination is achieved, the final state obtained throughminimize_proofand node merging remains too abstract, causing the verification to fail.
Solution
To address the above problem, precondition refinement is necessary: more reasonable constraints should be provided for the initial state of the function. The following approaches can be considered. Given the simplicity of the activateNextState example, the first approach should suffice to resolve the issue:
- Modify the current
--cseoption to run theconstructorandsetUpbefore executing functions from the leaf to the root of the call graph. - Introduce a new method to specify preconditions for each contract function, where the initial state is derived from these preconditions.
Additionally, function summaries should do the following before being included as lemmas:
- Ensure the summary can be used by removing any context unrelated to the callee contract and function, such as the test contract loaded during setUp.
- Improve rewrite efficiency by minimizing summaries using
minimize_proofand node merging.
Result / Expected
Upon the successful implementation of minimize_proof with node merging (issue #703), all tests within ActivateNextStateTest are expected to be verified within seconds or minutes.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.