Skip to content
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

Model ledgerBranches sparsely. #6138

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Model ledgerBranches sparsely. #6138

wants to merge 4 commits into from

Conversation

lemmy
Copy link
Collaborator

@lemmy lemmy commented Apr 19, 2024

Refactor modeling of ledgerBranch[i] from seq into function.

@lemmy lemmy added the tla TLA+ specifications label Apr 19, 2024
@lemmy lemmy marked this pull request as ready for review April 20, 2024 03:30
@lemmy lemmy requested a review from a team as a code owner April 20, 2024 03:30
@@ -63,11 +62,11 @@ RwTxExecuteAction ==
\* that it can be picked up by the current leader or any former leader
/\ \E view \in DOMAIN ledgerBranches:
ledgerBranches' = [ledgerBranches EXCEPT ![view] =
Append(@,[view |-> view, tx |-> history[i].tx])]
@ @@ (Max(DOMAIN ledgerBranches[view] \cup {0})+1) :> [view |-> view, tx |-> history[i].tx]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have this pattern in multiple places, can we pull it out and name it?

SparseLen(s) == Max(DOMAIN s \cup {0})

SparseAppend(s, e) == s @@ (SparseLen(s) + 1 :> e)

For the others that don't have multiple callers its less clear-cut, but maybe still more readable to introduce SparseSelectSeq and SparseSubSeq?

@achamayou
Copy link
Member

Let's hold off until we have the trace validation matching to make changes to the model that directly help the trace validate.

@achamayou
Copy link
Member

achamayou commented Apr 23, 2024

So interestingly, making the branches sparse may not be a the clear simplicity win I expected, because although it means we can probably remove BackfillLedgerBranch(es), it means that we can no longer call RwTxExecuteAction and IsRoTxResponseAction directly from the spec, and must replace them with copies that choose the txid instead.

With the dense models, we have to add two backfill actions, but every action from the trace can directly call its namesake in the spec.

@lemmy
Copy link
Collaborator Author

lemmy commented Apr 24, 2024

it means that we can no longer call RwTxExecuteAction and IsRoTxResponseAction directly from the spec, and must replace them with copies that choose the txid instead.

I don't understand what you mean by "choose the txid"? RoTxResponseAction already chooses the maximum tx_id in the branch. What would be the new predicate that you want to choose on?

@achamayou
Copy link
Member

I don't understand what you mean by "choose the txid"?

I forgot we could use conditions on future states to constrain the state, so perhaps we could do:

IsRwTxExecuteAction ==
    /\ IsEvent("RwTxExecuteAction")
    \* Model action
    /\ RwTxExecuteAction
    \* Match message contents
    /\ Last(history').tx = logline.tx
    \* RwTxExecuteAction can only take place if a branch exists for the view
    \* If there is no branch, BackfillLedgerBranches will create the right amount of branches
    /\ Len(ledgerBranches) >= logline.tx_id[1]
    /\ logline.tx_id[2] \in DOMAIN ledgerBranches'[logline.tx_id[1]]

But that does not seem work.

RoTxResponseAction already chooses the maximum tx_id in the branch. What would be the new predicate that you want to choose on?

The framework exposes the KV read version, which is dependent on all previous transactions, not just transactions to that key. To match that, we either need to insert a single Tx at read versions, where they don't match one of the model's Tx (because it's a signature, some governance, yadda yadda), or modify the application code to return an applicative read version that's really the version of last previous write.

@achamayou
Copy link
Member

Summary of discussion with @lemmy yesterday:

  1. Selection of sparse transactions does not work because Execute is constrained to seqno + 1. This would need to be opened up in the action, and bounded in the MC through an action constraint, which the TV would not be subject to.
  2. The branches backfill needs to stay in some form, as an equivalent to the rollback.
  3. Either the Ro response needs to backfill one other OtherTxn just before it, to get the right read version, or we need to change the app to return an app-specific version-of-last-write as the read version.

For the time being, because the validation passes, this is not urgent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tla TLA+ specifications
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants