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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use BTreeSet;
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.
/// Builds an intermediate quorum set that has [`QuorumIntersection`] with both
/// the source and the target quorum set.
/// 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));
/// ```