-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reason about common behavior among controllers in the reconciliation logic #168
Comments
I want to record the "common behaviors" in this issue, so let me first formally explain the case in the top comment. |
If for a reconcile state We require Then we have such a lemma: |
This is similar for some safety invariants. We want to have an invariant that controller being at some state implies there is a pending request which is either in flight or has an in-flight matched response. Previously, we proved this property for a number of states, see: To avoid repetition, think about if we want a state It is now a property of controller runtime that can apply to different controllers. |
Context and problem
To reduce developers' proof effort, Anvil needs to provide highly applicable lemmas that encodes representative liveness/safety reasoning for different controllers and can be directly applied to any specific newly-developed controller.
We had several such lemmas in
controller_runtime_liveness
andcontroller_runtime_safety
. However, they are limited to reasoning about state transitions and invariants for the initial, error, or done step because these properties do not talk about the core reconcile process (i.e., thecontinue_reconcile
action of controller, determined byreconcile_core
).Despite such generic lemmas, we still need to write controller-specific lemmas when reasoning about how
reconcile_core
transitions the state (i.e., the precondition of each transition and the resulting new state). Unfortunately, we end up writing highly repeated but slightly different lemmas that reason about howreconcile_core
starting from a concrete state can lead to another concrete state. This practice is tedious and error-prone and causes unnecessary code bloat for our proof.Solution
With all the lessons learned along the way of proving liveness of the zookeeper controller, we notice that there are indeed many common patterns among the controller-specific lemmas. In other words, when proving
spec |= a ~> b
, we may not require the details of whata
andb
are or what operations give us the~>
relation. Instead, it only requires certain relations betweena
andb
.If we can formalize such relation correctly in the form of preconditions, there is a chance to significantly simplify the proof by replacing all such controller-specific lemmas with a more general one.
Take the zookeeper controller for example. The following code block demonstrates how the controller advances from different steps:
An important observation is that the three cases are quite similar: we can see that there is only one possible next step for each of the three steps. Therefore, the proof strategies of
spec |= at_step(current_step) ~> at_step(next_step)
for them resemble each other at a high level. Instead of writing three lemmas that talk about the three transitions (which is what we did), we can come up with one lemma that talks about how the zookeeper controller advances from the current step to the next step, if that step is the only possible step that is directly reachable from the current step (this is what #166 does!). Note that this lemma can be further generalized to apply to other controllers.Future work
Later we can move on to fold more complicated reasoning patterns into highly usable lemmas, including what we have before the reconciliation and how objects are changed after that. Actually, I think the operations can be generally categorized into several types. Besides, taking the common behavior in the
reconcile_core
into consideration, we can also prove many general safety invariants that can apply to different states of many different controllers.The progress so far shows that this approach is promising in reducing proof efforts for newly-developed controllers.
The text was updated successfully, but these errors were encountered: