I have a toy model attached below that I’m using to introduce some concepts around CRDTs. Right now I’m trying to write a check like “sync is idempotent” but I’m having some trouble. I’m not actually sure how to express this! In words, I’d say “if sync
happens two times in a row, the values do not change.” I’m not sure how to grab the value after the first sync but before the second one. Is that even the right way to approach this? I feel pretty stuck right now, even after reading through the spec for actions and searching around on the forums for various things.
enum Bool { True, False }
fun merge[a, b: Bool]: Bool {
a = True implies True else b
}
check MergeIsCommutative {
all a, b: Bool | merge[a, b] = merge[b, a]
}
check MergeIsAssociative {
all a, b, c: Bool | merge[merge[a, b], c] = merge[a, merge[b, c]]
}
check MergeIsIdempotent {
all a, b: Bool | merge[a, b] = merge[merge[a, b], b]
}
sig Document {
var value: one Bool,
}
fun bool_not[b: Bool]: Bool {
b = True implies False else True
}
pred flip[d: Document] {
value' = value ++ d->bool_not[d.value]
}
pred sync[d1, d2: Document] {
let merged = merge[d1.value, d2.value] {
value' = value ++ (d1->merged + d2->merged)
}
}
pred init {
value = Document -> False
}
pred do_nothing {
value' = value
}
fact traces {
init
always {
do_nothing
or (one d: Document | flip[d])
or (some d1, d2: Document | sync[d1, d2])
}
}