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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use BTreeSet;
use crateQuorumBridge;
use crateQuorumTree;
use crateQuorumSet;
/// Relation between quorum sets whose quorums always intersect.
///
/// Quorum sets A and B have **quorum intersection**, written `A ~ B`, when:
/// `∀ qᵢ ∈ A, ∀ qⱼ ∈ B: qᵢ ∩ qⱼ != ø`.
/// In words, every quorum in A intersects every quorum in B. Consensus
/// protocols use this relation to make membership changes without losing
/// overlap between old and new decisions.
///
/// The relation is symmetric, and both universal quantifiers are load-bearing:
/// weakening either one to "some quorum" (∃) breaks safety, because a reader
/// or a candidate cannot know which quorum is "the right one" — the overlap
/// must hold for every quorum it may legally assemble. E.g. for write quorums
/// `{a,b}, {b,c}, {a,c}` and read quorums `{b,c}, {x,y}`: every write quorum
/// intersects *some* read quorum, yet a read using `{x,y}` observes no
/// committed write.
///
/// In a Raft-style membership change, quorum intersection is one safety
/// requirement. The protocol also has to prevent an old, smaller candidate
/// from being elected during the transition.
/// Exhaustively check the [`QuorumIntersection`] relation between two quorum
/// sets.
///
/// Returns `true` iff every quorum of `a` intersects every quorum of `b`.
/// Unlike [`QuorumIntersection::intersects_with`], which may answer `None`,
/// this check is exact for any two [`QuorumSet`] implementations, e.g. a read
/// [`QuorumTree`] against a write [`QuorumTree`].
///
/// It tests every split of the combined voter IDs `U` into `(S, U ∖ S)`: a
/// disjoint quorum pair exists iff for some split, `S` is a quorum of `a` and
/// `U ∖ S` is a quorum of `b`. Quorum sets are upward-closed, so "some quorum
/// of `b` fits inside `U ∖ S`" is the same as "`U ∖ S` is itself a quorum of
/// `b`". This argument relies on two [`QuorumSet`] rules: implementations are
/// upward-closed, and IDs outside [`QuorumSet::ids`] never affect
/// [`QuorumSet::is_quorum`].
///
/// The check runs `2^n` quorum evaluations for `n` distinct IDs. It is meant
/// for validating small configurations and as a test oracle.
///
/// # Panics
///
/// Panics if `a` and `b` together track 64 or more distinct IDs.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// use quorum_set::verify_intersection;
///
/// let abc = BTreeSet::from([1, 2, 3]);
/// let de = BTreeSet::from([4, 5]);
///
/// // Majorities of one voter set always intersect each other.
/// assert!(verify_intersection(&abc, &abc));
/// // Majorities of disjoint voter sets never intersect.
/// assert!(!verify_intersection(&abc, &de));
/// ```