-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtft_singleB_safety.ivy
81 lines (61 loc) · 2.1 KB
/
tft_singleB_safety.ivy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#lang ivy1.7
type peer
# type block
# States
# relation prepared(P:peer)
relation joined(P:peer)
relation left(P:peer)
# TFT relations
relation has_sent(P:peer)
relation holds(P:peer)
# Every peer is in a single state
# relation single_state(P:peer)
# definition single_state(P) = (~(prepared(P) & joined(P)) &
# ~(prepared(P) & left(P)) &
# ~(joined(P) & left(P)) &
# (prepared(P) | joined(P) | left(P)))
individual seeder:peer
# Initially all peers are not left, but some are joined, some are prepared.
# Intially a seeder holds all blocks and is joined.
# Initially no peer has sent any block.
after init {
# ensure single_state(P) & (exists S. (joined(S) & holds(S, B))) & ~has_sent(Q, B);
joined(P) := *;
joined(seeder) := true;
left(P) := false;
# prepared(P) := false if joined(P) else true;
holds(P) := *;
holds(seeder) := true;
has_sent(P) := false;
}
# Sender must hold the block, receiver must not, and both are joined
action send(p1:peer, p2:peer) = {
require holds(p1) & ~holds(p2) & joined(p1) & joined(p2);
holds(p2) := true;
has_sent(p1) := true;
}
# A peer can join if there is at least one other peer joined
action join(p:peer) = {
require ~joined(p) & ~left(p) & (exists Q. joined(Q));
# prepared(p) := false;
holds(p) := *;
joined(p) := true;
}
action leave(p:peer) = {
require joined(p) & ~left(p);
require has_sent(p) | (forall Q. (joined(Q) -> (holds(Q) & ~has_sent(Q))));
joined(p) := false;
left(p) := true;
}
export send
export join
export leave
invariant ~(joined(P) & left(P))
private {
invariant has_sent(P) -> holds(P)
invariant (~joined(P) & ~left(P) -> ~has_sent(P))
# Godel class with equality: undecidable under EPR if there is equality!!
invariant joined(P) & has_sent(P) -> (exists Q. joined(Q) & ~has_sent(Q) & holds(Q))
}
invariant ((exists P. joined(P)) -> (exists Q. (holds(Q) & joined(Q))))
invariant left(P) -> holds(P)