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/split.hpp>
25 #include <boost/algorithm/string/classification.hpp>
26 #include <algorithm>
27 #include <sstream>
28 #include <fstream>
29 #include <string>
30 
31 namespace ripple {
32 namespace test {
33 
36 class DistributedValidators_test : public beast::unit_test::suite
37 {
38 
39  void
41  std::size_t numPeers,
43  bool printHeaders = false)
44  {
45  using namespace csf;
46  using namespace std::chrono;
47 
48  // Initialize persistent collector logs specific to this method
49  std::string const prefix =
50  "DistributedValidators_"
51  "completeTrustCompleteConnectFixedDelay";
53  txLog(prefix + "_tx.csv", std::ofstream::app),
54  ledgerLog(prefix + "_ledger.csv", std::ofstream::app);
55 
56  // title
57  log << prefix << "(" << numPeers << "," << delay.count() << ")"
58  << std::endl;
59 
60  // number of peers, UNLs, connections
61  BEAST_EXPECT(numPeers >= 1);
62 
63  Sim sim;
64  PeerGroup peers = sim.createGroup(numPeers);
65 
66  // complete trust graph
67  peers.trust(peers);
68 
69  // complete connect graph with fixed delay
70  peers.connect(peers, delay);
71 
72  // Initialize collectors to track statistics to report
73  TxCollector txCollector;
74  LedgerCollector ledgerCollector;
75  auto colls = makeCollectors(txCollector, ledgerCollector);
76  sim.collectors.add(colls);
77 
78  // Initial round to set prior state
79  sim.run(1);
80 
81  // Run for 10 minues, submitting 100 tx/second
82  std::chrono::nanoseconds const simDuration = 10min;
83  std::chrono::nanoseconds const quiet = 10s;
84  Rate const rate{100, 1000ms};
85 
86  // Initialize timers
87  HeartbeatTimer heart(sim.scheduler);
88 
89  // txs, start/stop/step, target
90  auto peerSelector = makeSelector(peers.begin(),
91  peers.end(),
92  std::vector<double>(numPeers, 1.),
93  sim.rng);
94  auto txSubmitter = makeSubmitter(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";
141  txLog(prefix + "_tx.csv", std::ofstream::app),
142  ledgerLog(prefix + "_ledger.csv", std::ofstream::app);
143 
144  // title
145  log << prefix << "(" << numPeers << "," << delay.count() << ")"
146  << std::endl;
147 
148  // number of peers, UNLs, connections
149  int const numCNLs = std::max(int(1.00 * numPeers), 1);
150  int const minCNLSize = std::max(int(0.25 * numCNLs), 1);
151  int const maxCNLSize = std::max(int(0.50 * numCNLs), 1);
152  BEAST_EXPECT(numPeers >= 1);
153  BEAST_EXPECT(numCNLs >= 1);
154  BEAST_EXPECT(1 <= minCNLSize
155  && minCNLSize <= maxCNLSize
156  && maxCNLSize <= numPeers);
157 
158  Sim sim;
159  PeerGroup peers = sim.createGroup(numPeers);
160 
161  // complete trust graph
162  peers.trust(peers);
163 
164  // scale-free connect graph with fixed delay
165  std::vector<double> const ranks =
166  sample(peers.size(), PowerLawDistribution{1, 3}, sim.rng);
167  randomRankedConnect(peers, ranks, numCNLs,
168  std::uniform_int_distribution<>{minCNLSize, maxCNLSize},
169  sim.rng, delay);
170 
171  // Initialize collectors to track statistics to report
172  TxCollector txCollector;
173  LedgerCollector ledgerCollector;
174  auto colls = makeCollectors(txCollector, ledgerCollector);
175  sim.collectors.add(colls);
176 
177  // Initial round to set prior state
178  sim.run(1);
179 
180  // Run for 10 minues, submitting 100 tx/second
181  std::chrono::nanoseconds simDuration = 10min;
182  std::chrono::nanoseconds quiet = 10s;
183  Rate rate{100, 1000ms};
184 
185  // Initialize timers
186  HeartbeatTimer heart(sim.scheduler);
187 
188  // txs, start/stop/step, target
189  auto peerSelector = makeSelector(peers.begin(),
190  peers.end(),
191  std::vector<double>(numPeers, 1.),
192  sim.rng);
193  auto txSubmitter = makeSubmitter(ConstantDistribution{rate.inv()},
194  sim.scheduler.now() + quiet,
195  sim.scheduler.now() + simDuration - quiet,
196  peerSelector,
197  sim.scheduler,
198  sim.rng);
199 
200  // run simulation for given duration
201  heart.start();
202  sim.run(simDuration);
203 
204  //BEAST_EXPECT(sim.branches() == 1);
205  //BEAST_EXPECT(sim.synchronized());
206 
207  log << std::right;
208  log << "| Peers: "<< std::setw(2) << peers.size();
209  log << " | Duration: " << std::setw(6)
210  << duration_cast<milliseconds>(simDuration).count() << " ms";
211  log << " | Branches: " << std::setw(1) << sim.branches();
212  log << " | Synchronized: " << std::setw(1)
213  << (sim.synchronized() ? "Y" : "N");
214  log << " |" << std::endl;
215 
216  txCollector.report(simDuration, log, true);
217  ledgerCollector.report(simDuration, log, false);
218 
219  std::string const tag = std::to_string(numPeers);
220  txCollector.csv(simDuration, txLog, tag, printHeaders);
221  ledgerCollector.csv(simDuration, ledgerLog, tag, printHeaders);
222 
223  log << std::endl;
224  }
225 
226  void
227  run() override
228  {
229  std::string const defaultArgs = "5 200";
230  std::string const args = arg().empty() ? defaultArgs : arg();
231  std::stringstream argStream(args);
232 
233  int maxNumValidators = 0;
234  int delayCount(200);
235  argStream >> maxNumValidators;
236  argStream >> delayCount;
237 
238  std::chrono::milliseconds const delay(delayCount);
239 
240  log << "DistributedValidators: 1 to " << maxNumValidators << " Peers"
241  << std::endl;
242 
250  for(int i = 2; i <= maxNumValidators; i++)
251  {
253  }
254 
262  for(int i = 2; i <= maxNumValidators; i++)
263  {
265  }
266  }
267 };
268 
269 BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(DistributedValidators, consensus, ripple, 2);
270 
271 } // namespace test
272 } // 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:40
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:227
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30
std::chrono
string