Leader election ring btw
¤
A module for axiomatizing a total order
¤
module total_order(r) = {
axiom r(X,X) # Reflexivity
axiom r(X, Y) & r(Y, Z) -> r(X, Z) # Transitivity
axiom r(X, Y) & r(Y, X) -> X = Y # Anti-symmetry
axiom r(X, Y) | r(Y, X) # Totality
}
¤
Module describing a ring topology.
The module includes a ring_head and ring_tail elements, and a ring total order relation, and an auxilary ternary btw relation.
The module also includes get_next and get_prev actions.
In this module, the ring topology is arbitrary and fixed.
¤
module ring_topology(carrier) = {
individual head:carrier # ring head
individual tail:carrier # ring tail
relation le(X:carrier,Y:carrier) # total order describing ring topology
relation btw(X:carrier,Y:carrier, Z:carrier) # Y is on the acyclic path from X to Z
instantiate total_order(le) # total order
axiom le(head, X) # head is minimal
axiom le(X, tail) # tail is maximal
axiom btw(X, Y, Z) <-> (
(le(X, Y) & le(Y, Z)) |
(le(Z, X) & le(X, Y) & X ~= Z) |
(le(Y, Z) & le(Z, X) & X ~= Z)
)
action get_next(x:carrier) returns (y:carrier) = {
assume (x = tail & y = head) | (le(x,y) & x ~= y & ((le(x, Z) & x ~= Z) -> le(y, Z)))
}
action get_prev(y:carrier) returns (x:carrier) = {
assume (x = tail & y = head) | (le(x,y) & x ~= y & ((le(x, Z) & x ~= Z) -> le(y, Z)))
}
}
¤
Types, relations and functions describing state of the network
¤
type node
type id
instantiate ring : ring_topology(node)
relation le(X:id, Y:id)
instantiate total_order(le)
individual idn(X:node) : id
axiom idn(X)=idn(Y) -> X=Y # the idn function is injective
relation leader(N:node)
init ~leader(N)
relation pending(V:id, N:node) # The identity V is pending at node N
init ~pending(V, N)
¤
Protocol description
Two action: send and receive
¤
action send = {
local n1:node, n2:node {
n2 := ring.get_next(n1);
pending(idn(n1), n2) := true
}
}
action receive = {
local n1:node, n2:node, m:id {
assume pending(m, n1);
pending(m, n1) := *; # abstract the number of pending messages
if m = idn(n1) { # Found a leader
leader(n1) := true
} else {
if le(idn(n1), m) { # pass message to next node
n2 := ring.get_next(n1);
pending(m, n2) := true
} # otherwise drop the message...
}
}
}
export send
export receive
conjecture leader(X) & leader(Y) -> X = Y # at most one leader
conjecture leader(X) -> le(idn(Y), idn(X)) # leader has highest id