rippled
DistributedValidatorsSim_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2016 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 #include <ripple/beast/clock/manual_clock.h>
20 #include <ripple/beast/unit_test.h>
21 #include <test/csf.h>
22 #include <utility>
23 
24 #include <boost/algorithm/string/classification.hpp>
25 #include <boost/algorithm/string/split.hpp>
26 #include <algorithm>
27 #include <fstream>
28 #include <sstream>
29 #include <string>
30 
31 namespace ripple {
32 namespace test {
33 
36 class DistributedValidators_test : public beast::unit_test::suite
37 {
38  void
40  std::size_t numPeers,
42  bool printHeaders = false)
43  {
44  using namespace csf;
45  using namespace std::chrono;
46 
47  // Initialize persistent collector logs specific to this method
48  std::string const prefix =
49  "DistributedValidators_"
50  "completeTrustCompleteConnectFixedDelay";
51  std::fstream txLog(prefix + "_tx.csv", std::ofstream::app),
52  ledgerLog(prefix + "_ledger.csv", std::ofstream::app);
53 
54  // title
55  log << prefix << "(" << numPeers << "," << delay.count() << ")"
56  << std::endl;
57 
58  // number of peers, UNLs, connections
59  BEAST_EXPECT(numPeers >= 1);
60 
61  Sim sim;
62  PeerGroup peers = sim.createGroup(numPeers);
63 
64  // complete trust graph
65  peers.trust(peers);
66 
67  // complete connect graph with fixed delay
68  peers.connect(peers, delay);
69 
70  // Initialize collectors to track statistics to report
71  TxCollector txCollector;
72  LedgerCollector ledgerCollector;
73  auto colls = makeCollectors(txCollector, ledgerCollector);
74  sim.collectors.add(colls);
75 
76  // Initial round to set prior state
77  sim.run(1);
78 
79  // Run for 10 minues, submitting 100 tx/second
80  std::chrono::nanoseconds const simDuration = 10min;
81  std::chrono::nanoseconds const quiet = 10s;
82  Rate const rate{100, 1000ms};
83 
84  // Initialize timers
85  HeartbeatTimer heart(sim.scheduler);
86 
87  // txs, start/stop/step, target
88  auto peerSelector = makeSelector(
89  peers.begin(),
90  peers.end(),
91  std::vector<double>(numPeers, 1.),
92  sim.rng);
93  auto txSubmitter = makeSubmitter(
94  ConstantDistribution{rate.inv()},
95  sim.scheduler.now() + quiet,
96  sim.scheduler.now() + simDuration - quiet,
97  peerSelector,
98  sim.scheduler,
99  sim.rng);
100 
101  // run simulation for given duration
102  heart.start();
103  sim.run(simDuration);
104 
105  // BEAST_EXPECT(sim.branches() == 1);
106  // BEAST_EXPECT(sim.synchronized());
107 
108  log << std::right;
109  log << "| Peers: " << std::setw(2) << peers.size();
110  log << " | Duration: " << std::setw(6)
111  << duration_cast<milliseconds>(simDuration).count() << " ms";
112  log << " | Branches: " << std::setw(1) << sim.branches();
113  log << " | Synchronized: " << std::setw(1)
114  << (sim.synchronized() ? "Y" : "N");
115  log << " |" << std::endl;
116 
117  txCollector.report(simDuration, log, true);
118  ledgerCollector.report(simDuration, log, false);
119 
120  std::string const tag = std::to_string(numPeers);
121  txCollector.csv(simDuration, txLog, tag, printHeaders);
122  ledgerCollector.csv(simDuration, ledgerLog, tag, printHeaders);
123 
124  log << std::endl;
125  }
126 
127  void
129  std::size_t numPeers,
131  bool printHeaders = false)
132  {
133  using namespace csf;
134  using namespace std::chrono;
135 
136  // Initialize persistent collector logs specific to this method
137  std::string const prefix =
138  "DistributedValidators__"
139  "completeTrustScaleFreeConnectFixedDelay";
140  std::fstream txLog(prefix + "_tx.csv", std::ofstream::app),
141  ledgerLog(prefix + "_ledger.csv", std::ofstream::app);
142 
143  // title
144  log << prefix << "(" << numPeers << "," << delay.count() << ")"
145  << std::endl;
146 
147  // number of peers, UNLs, connections
148  int const numCNLs = std::max(int(1.00 * numPeers), 1);
149  int const minCNLSize = std::max(int(0.25 * numCNLs), 1);
150  int const maxCNLSize = std::max(int(0.50 * numCNLs), 1);
151  BEAST_EXPECT(numPeers >= 1);
152  BEAST_EXPECT(numCNLs >= 1);
153  BEAST_EXPECT(
154  1 <= minCNLSize && minCNLSize <= maxCNLSize &&
155  maxCNLSize <= numPeers);
156 
157  Sim sim;
158  PeerGroup peers = sim.createGroup(numPeers);
159 
160  // complete trust graph
161  peers.trust(peers);
162 
163  // scale-free connect graph with fixed delay
164  std::vector<double> const ranks =
165  sample(peers.size(), PowerLawDistribution{1, 3}, sim.rng);
166  randomRankedConnect(
167  peers,
168  ranks,
169  numCNLs,
170  std::uniform_int_distribution<>{minCNLSize, maxCNLSize},
171  sim.rng,
172  delay);
173 
174  // Initialize collectors to track statistics to report
175  TxCollector txCollector;
176  LedgerCollector ledgerCollector;
177  auto colls = makeCollectors(txCollector, ledgerCollector);
178  sim.collectors.add(colls);
179 
180  // Initial round to set prior state
181  sim.run(1);
182 
183  // Run for 10 minues, submitting 100 tx/second
184  std::chrono::nanoseconds simDuration = 10min;
185  std::chrono::nanoseconds quiet = 10s;
186  Rate rate{100, 1000ms};
187 
188  // Initialize timers
189  HeartbeatTimer heart(sim.scheduler);
190 
191  // txs, start/stop/step, target
192  auto peerSelector = makeSelector(
193  peers.begin(),
194  peers.end(),
195  std::vector<double>(numPeers, 1.),
196  sim.rng);
197  auto txSubmitter = makeSubmitter(
198  ConstantDistribution{rate.inv()},
199  sim.scheduler.now() + quiet,
200  sim.scheduler.now() + simDuration - quiet,
201  peerSelector,
202  sim.scheduler,
203  sim.rng);
204 
205  // run simulation for given duration
206  heart.start();
207  sim.run(simDuration);
208 
209  // BEAST_EXPECT(sim.branches() == 1);
210  // BEAST_EXPECT(sim.synchronized());
211 
212  log << std::right;
213  log << "| Peers: " << std::setw(2) << peers.size();
214  log << " | Duration: " << std::setw(6)
215  << duration_cast<milliseconds>(simDuration).count() << " ms";
216  log << " | Branches: " << std::setw(1) << sim.branches();
217  log << " | Synchronized: " << std::setw(1)
218  << (sim.synchronized() ? "Y" : "N");
219  log << " |" << std::endl;
220 
221  txCollector.report(simDuration, log, true);
222  ledgerCollector.report(simDuration, log, false);
223 
224  std::string const tag = std::to_string(numPeers);
225  txCollector.csv(simDuration, txLog, tag, printHeaders);
226  ledgerCollector.csv(simDuration, ledgerLog, tag, printHeaders);
227 
228  log << std::endl;
229  }
230 
231  void
232  run() override
233  {
234  std::string const defaultArgs = "5 200";
235  std::string const args = arg().empty() ? defaultArgs : arg();
236  std::stringstream argStream(args);
237 
238  int maxNumValidators = 0;
239  int delayCount(200);
240  argStream >> maxNumValidators;
241  argStream >> delayCount;
242 
243  std::chrono::milliseconds const delay(delayCount);
244 
245  log << "DistributedValidators: 1 to " << maxNumValidators << " Peers"
246  << std::endl;
247 
255  for (int i = 2; i <= maxNumValidators; i++)
256  {
258  }
259 
267  for (int i = 2; i <= maxNumValidators; i++)
268  {
270  }
271  }
272 };
273 
274 BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(DistributedValidators, consensus, ripple, 2);
275 
276 } // namespace test
277 } // namespace ripple
sstream
ripple::test::DistributedValidators_test::completeTrustCompleteConnectFixedDelay
void completeTrustCompleteConnectFixedDelay(std::size_t numPeers, std::chrono::milliseconds delay=std::chrono::milliseconds(200), bool printHeaders=false)
Definition: DistributedValidatorsSim_test.cpp:39
fstream
std::string
STL class.
std::uniform_int_distribution
utility
ripple::Rate
Represents a transfer rate.
Definition: Rate.h:37
std::fstream
STL class.
std::vector
STL class.
std::chrono::milliseconds
std::stringstream
STL class.
algorithm
ripple::test::BEAST_DEFINE_TESTSUITE_MANUAL_PRIO
BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(CrossingLimits, tx, ripple, 10)
ripple::test::DistributedValidators_test::completeTrustScaleFreeConnectFixedDelay
void completeTrustScaleFreeConnectFixedDelay(std::size_t numPeers, std::chrono::milliseconds delay=std::chrono::milliseconds(200), bool printHeaders=false)
Definition: DistributedValidatorsSim_test.cpp:128
std::to_string
T to_string(T... args)
ripple::test::DistributedValidators_test
In progress simulations for diversifying and distributing validators.
Definition: DistributedValidatorsSim_test.cpp:36
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::endl
T endl(T... args)
std::right
T right(T... args)
std::string::empty
T empty(T... args)
std::size_t
std::setw
T setw(T... args)
std::max
T max(T... args)
ripple::test::DistributedValidators_test::run
void run() override
Definition: DistributedValidatorsSim_test.cpp:232
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30
std::chrono
string