Toy consensus2
include indexset
instance nodeord : unbounded_sequence
instance nodecard : unbounded_sequence
instance nodeset : indexset(nodeord,nodecard)
alias node = nodeord.t
type value
alias quorum = nodeset.set
object proto = {
action cast_vote(n:node, v:value)
action decide(v:value, q:quorum)
relation vote(N:node, V:value)
object spec = {
before cast_vote {
assert ~vote(n,V)
}
before decide {
assert q.majority;
assert nodeset.member(N, q) -> vote(N, v)
}
}
object impl = {
relation decision(V:value)
after init {
vote(N,V) := false;
decision(V) := false
}
implement cast_vote {
vote(n, v) := true
}
implement decide {
decision(v) := true
}
safety property:
conjecture decision(V1) & decision(V2) -> V1 = V2
inductive invariant:
conjecture vote(N,V1) & vote(N,V2) -> V1 = V2
conjecture decision(V) -> exists Q:quorum. nodeset.majority(Q) &
forall N:node. nodeset.member(N, Q) -> vote(N,V)
}
}
export proto.cast_vote
export proto.decide
export nodeset.empty
export nodeset.add
isolate iso_p = proto with nodeset
isolate iso_n = nodeset with nodeord,nodecard
object conc = {
interpret value -> bv[1]
init nodeset.n = 3
}
extract iso_impl = proto,nodeset,nodeord,nodecard