rippled
Loading...
Searching...
No Matches
TrustGraph.h
1#pragma once
2
3#include <test/csf/random.h>
4
5#include <boost/container/flat_set.hpp>
6
7#include <chrono>
8#include <numeric>
9#include <random>
10#include <vector>
11
12namespace xrpl {
13namespace test {
14namespace csf {
15
23template <class Peer>
25{
27
29
30public:
33 TrustGraph() = default;
34
35 Graph const&
37 {
38 return graph_;
39 }
40
50 void
51 trust(Peer const& from, Peer const& to)
52 {
53 graph_.connect(from, to);
54 }
55
64 void
65 untrust(Peer const& from, Peer const& to)
66 {
67 graph_.disconnect(from, to);
68 }
69
70 //< Whether from trusts to
71 bool
72 trusts(Peer const& from, Peer const& to) const
73 {
74 return graph_.connected(from, to);
75 }
76
83 auto
84 trustedPeers(Peer const& a) const
85 {
86 return graph_.outVertices(a);
87 }
88
98
99 //< Return nodes that fail the white-paper no-forking condition
101 forkablePairs(double quorum) const
102 {
103 // Check the forking condition by looking at intersection
104 // of UNL between all pairs of nodes.
105
106 // TODO: Use the improved bound instead of the whitepaper bound.
107
108 using UNL = std::set<Peer>;
109 std::set<UNL> unique;
110 for (Peer const peer : graph_.outVertices())
111 {
112 unique.emplace(std::begin(trustedPeers(peer)), std::end(trustedPeers(peer)));
113 }
114
115 std::vector<UNL> uniqueUNLs(unique.begin(), unique.end());
117
118 // Loop over all pairs of uniqueUNLs
119 for (int i = 0; i < uniqueUNLs.size(); ++i)
120 {
121 for (int j = (i + 1); j < uniqueUNLs.size(); ++j)
122 {
123 auto const& unlA = uniqueUNLs[i];
124 auto const& unlB = uniqueUNLs[j];
125 double rhs = 2.0 * (1. - quorum) * std::max(unlA.size(), unlB.size());
126
127 int intersectionSize =
128 std::count_if(unlA.begin(), unlA.end(), [&](Peer p) { return unlB.find(p) != unlB.end(); });
129
130 if (intersectionSize < rhs)
131 {
132 res.emplace_back(ForkInfo{unlA, unlB, intersectionSize, rhs});
133 }
134 }
135 }
136 return res;
137 }
138
142 bool
143 canFork(double quorum) const
144 {
145 return !forkablePairs(quorum).empty();
146 }
147};
148
149} // namespace csf
150} // namespace test
151} // namespace xrpl
T begin(T... args)
bool connected(Vertex source, Vertex target) const
Check if two vertices are connected.
Definition Digraph.h:118
bool connect(Vertex source, Vertex target, EdgeData e)
Connect two vertices.
Definition Digraph.h:54
bool disconnect(Vertex source, Vertex target)
Disconnect two vertices.
Definition Digraph.h:81
auto outVertices() const
Range over vertices in the graph.
Definition Digraph.h:129
auto trustedPeers(Peer const &a) const
Range over trusted peers.
Definition TrustGraph.h:84
bool trusts(Peer const &from, Peer const &to) const
Definition TrustGraph.h:72
std::vector< ForkInfo > forkablePairs(double quorum) const
Definition TrustGraph.h:101
void trust(Peer const &from, Peer const &to)
Create trust.
Definition TrustGraph.h:51
TrustGraph()=default
Create an empty trust graph.
bool canFork(double quorum) const
Check whether this trust graph satisfies the whitepaper no-forking condition.
Definition TrustGraph.h:143
void untrust(Peer const &from, Peer const &to)
Remove trust.
Definition TrustGraph.h:65
T count_if(T... args)
T emplace_back(T... args)
T end(T... args)
T max(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
T size(T... args)
A single peer in the simulation.
An example of nodes that fail the whitepaper no-forking condition.
Definition TrustGraph.h:92