rippled
LedgerHistory_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2018 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 
20 #include <ripple/app/ledger/LedgerHistory.h>
21 #include <ripple/app/ledger/LedgerMaster.h>
22 #include <ripple/app/tx/apply.h>
23 #include <ripple/beast/insight/NullCollector.h>
24 #include <ripple/beast/unit_test.h>
25 #include <ripple/ledger/OpenView.h>
26 #include <chrono>
27 #include <memory>
28 #include <sstream>
29 #include <test/jtx.h>
30 
31 namespace ripple {
32 namespace test {
33 
34 class LedgerHistory_test : public beast::unit_test::suite
35 {
36 public:
39  class CheckMessageLogs : public Logs
40  {
42  bool& found_;
43 
45  {
47 
48  public:
51  CheckMessageLogs& owner)
52  : beast::Journal::Sink(threshold, false), owner_(owner)
53  {
54  }
55 
56  void
58  override
59  {
60  if (text.find(owner_.msg_) != std::string::npos)
61  owner_.found_ = true;
62  }
63  };
64 
65  public:
71  CheckMessageLogs(std::string msg, bool& found)
73  , msg_{std::move(msg)}
74  , found_{found}
75  {
76  }
77 
80  std::string const& partition,
82  {
83  return std::make_unique<CheckMessageSink>(threshold, *this);
84  }
85  };
86 
97  jtx::Env& env,
98  LedgerHistory& lh,
99  NetClock::duration closeOffset,
101  {
102  if (!prev)
103  {
104  assert(!stx);
105  return std::make_shared<Ledger>(
107  env.app().config(),
109  env.app().family());
110  }
111  auto res = std::make_shared<Ledger>(
112  *prev, prev->info().closeTime + closeOffset);
113 
114  if (stx)
115  {
116  OpenView accum(&*res);
118  env.app(), accum, *stx, false, tapNONE, env.journal);
119  accum.apply(*res);
120  }
121  res->updateSkipList();
122 
123  {
124  res->stateMap().flushDirty(hotACCOUNT_NODE, res->info().seq);
125  res->txMap().flushDirty(hotTRANSACTION_NODE, res->info().seq);
126  }
127  res->unshare();
128 
129  // Accept ledger
130  res->setAccepted(
131  res->info().closeTime,
132  res->info().closeTimeResolution,
133  true /* close time correct*/,
134  env.app().config());
135  lh.insert(res, false);
136  return res;
137  }
138 
139  void
141  {
142  testcase("LedgerHistory mismatch");
143  using namespace jtx;
144  using namespace std::chrono;
145 
146  // No mismatch
147  {
148  bool found = false;
149  Env env{
150  *this,
151  envconfig(),
152  std::make_unique<CheckMessageLogs>("MISMATCH ", found)};
154  auto const genesis = makeLedger({}, env, lh, 0s);
155  uint256 const dummyTxHash{1};
156  lh.builtLedger(genesis, dummyTxHash, {});
157  lh.validatedLedger(genesis, dummyTxHash);
158 
159  BEAST_EXPECT(!found);
160  }
161 
162  // Close time mismatch
163  {
164  bool found = false;
165  Env env{
166  *this,
167  envconfig(),
168  std::make_unique<CheckMessageLogs>(
169  "MISMATCH on close time", found)};
171  auto const genesis = makeLedger({}, env, lh, 0s);
172  auto const ledgerA = makeLedger(genesis, env, lh, 4s);
173  auto const ledgerB = makeLedger(genesis, env, lh, 40s);
174 
175  uint256 const dummyTxHash{1};
176  lh.builtLedger(ledgerA, dummyTxHash, {});
177  lh.validatedLedger(ledgerB, dummyTxHash);
178 
179  BEAST_EXPECT(found);
180  }
181 
182  // Prior ledger mismatch
183  {
184  bool found = false;
185  Env env{
186  *this,
187  envconfig(),
188  std::make_unique<CheckMessageLogs>(
189  "MISMATCH on prior ledger", found)};
191  auto const genesis = makeLedger({}, env, lh, 0s);
192  auto const ledgerA = makeLedger(genesis, env, lh, 4s);
193  auto const ledgerB = makeLedger(genesis, env, lh, 40s);
194  auto const ledgerAC = makeLedger(ledgerA, env, lh, 4s);
195  auto const ledgerBD = makeLedger(ledgerB, env, lh, 4s);
196 
197  uint256 const dummyTxHash{1};
198  lh.builtLedger(ledgerAC, dummyTxHash, {});
199  lh.validatedLedger(ledgerBD, dummyTxHash);
200 
201  BEAST_EXPECT(found);
202  }
203 
204  // Simulate a bug in which consensus may agree on transactions, but
205  // somehow generate different ledgers
206  for (bool const txBug : {true, false})
207  {
208  std::string const msg = txBug
209  ? "MISMATCH with same consensus transaction set"
210  : "MISMATCH on consensus transaction set";
211  bool found = false;
212  Env env{
213  *this,
214  envconfig(),
215  std::make_unique<CheckMessageLogs>(msg, found)};
217 
218  Account alice{"A1"};
219  Account bob{"A2"};
220  env.fund(XRP(1000), alice, bob);
221  env.close();
222 
223  auto const ledgerBase =
225 
226  JTx txAlice = env.jt(noop(alice));
227  auto const ledgerA =
228  makeLedger(ledgerBase, env, lh, 4s, txAlice.stx);
229 
230  JTx txBob = env.jt(noop(bob));
231  auto const ledgerB = makeLedger(ledgerBase, env, lh, 4s, txBob.stx);
232 
233  lh.builtLedger(ledgerA, txAlice.stx->getTransactionID(), {});
234  // Simulate the bug by claiming ledgerB had the same consensus hash
235  // as ledgerA, but somehow generated different ledgers
236  lh.validatedLedger(
237  ledgerB,
238  txBug ? txAlice.stx->getTransactionID()
239  : txBob.stx->getTransactionID());
240 
241  BEAST_EXPECT(found);
242  }
243  }
244 
245  void
246  run() override
247  {
249  }
250 };
251 
253 
254 } // namespace test
255 } // namespace ripple
beast::Journal::Sink
Abstraction for the underlying message destination.
Definition: Journal.h:74
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
sstream
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::LedgerHistory_test::CheckMessageLogs::CheckMessageSink::CheckMessageSink
CheckMessageSink(beast::severities::Severity threshold, CheckMessageLogs &owner)
Definition: LedgerHistory_test.cpp:49
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
std::shared_ptr
STL class.
ripple::test::LedgerHistory_test::CheckMessageLogs::makeSink
std::unique_ptr< beast::Journal::Sink > makeSink(std::string const &partition, beast::severities::Severity threshold) override
Definition: LedgerHistory_test.cpp:79
ripple::Logs
Manages partitions for logging.
Definition: Log.h:48
ripple::test::LedgerHistory_test::CheckMessageLogs::CheckMessageLogs
CheckMessageLogs(std::string msg, bool &found)
Constructor.
Definition: LedgerHistory_test.cpp:71
ripple::test::LedgerHistory_test::CheckMessageLogs::CheckMessageSink::owner_
CheckMessageLogs & owner_
Definition: LedgerHistory_test.cpp:46
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
std::vector
STL class.
std::string::find
T find(T... args)
ripple::applyTransaction
ApplyResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:122
ripple::test::LedgerHistory_test::run
void run() override
Definition: LedgerHistory_test.cpp:246
ripple::test::LedgerHistory_test::makeLedger
static std::shared_ptr< Ledger > makeLedger(std::shared_ptr< Ledger const > const &prev, jtx::Env &env, LedgerHistory &lh, NetClock::duration closeOffset, std::shared_ptr< STTx const > stx={})
Generate a new ledger by hand, applying a specific close time offset and optionally inserting a trans...
Definition: LedgerHistory_test.cpp:95
ripple::test::jtx::JTx::stx
std::shared_ptr< STTx const > stx
Definition: JTx.h:49
ripple::test::jtx::Env::jt
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:437
std::chrono::duration
ripple::test::LedgerHistory_test::CheckMessageLogs::CheckMessageSink
Definition: LedgerHistory_test.cpp:44
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:141
ripple::test::LedgerHistory_test::CheckMessageLogs::found_
bool & found_
Definition: LedgerHistory_test.cpp:42
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:238
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::hotTRANSACTION_NODE
@ hotTRANSACTION_NODE
Definition: NodeObject.h:36
ripple::LedgerHistory
Retains historical ledgers.
Definition: LedgerHistory.h:34
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:31
ripple::test::LedgerHistory_test
Definition: LedgerHistory_test.cpp:34
ripple::LedgerHistory::builtLedger
void builtLedger(std::shared_ptr< Ledger const > const &, uint256 const &consensusHash, Json::Value)
Report that we have locally built a particular ledger.
Definition: LedgerHistory.cpp:431
ripple::test::LedgerHistory_test::CheckMessageLogs
Log manager that searches for a specific message substring.
Definition: LedgerHistory_test.cpp:39
ripple::base_uint< 256 >
ripple::LedgerHistory::insert
bool insert(std::shared_ptr< Ledger const > ledger, bool validated)
Track a ledger.
Definition: LedgerHistory.cpp:62
ripple::Application::family
virtual Family & family()=0
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
chrono
ripple::Application::config
virtual Config & config()=0
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::Logs::Sink
Definition: Log.h:51
ripple::LedgerHistory::validatedLedger
void validatedLedger(std::shared_ptr< Ledger const > const &, boost::optional< uint256 > const &consensusHash)
Report that we have validated a particular ledger.
Definition: LedgerHistory.cpp:472
memory
ripple::test::LedgerHistory_test::CheckMessageLogs::CheckMessageSink::write
void write(beast::severities::Severity level, std::string const &text) override
Write text to the sink at the specified severity.
Definition: LedgerHistory_test.cpp:57
ripple::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:83
ripple::Logs::threshold
beast::severities::Severity threshold() const
Definition: Log.cpp:150
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
beast::Journal::Sink::threshold
virtual Severity threshold() const
Returns the minimum severity level this sink will report.
Definition: beast_Journal.cpp:106
beast::severities::Severity
Severity
Severity level / threshold of a Journal message.
Definition: Journal.h:31
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:111
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:209
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:56
ripple::test::LedgerHistory_test::testHandleMismatch
void testHandleMismatch()
Definition: LedgerHistory_test.cpp:140
beast::severities::kDebug
@ kDebug
Definition: Journal.h:35
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::LedgerHistory_test::CheckMessageLogs::msg_
std::string msg_
Definition: LedgerHistory_test.cpp:41
std::unique_ptr< beast::Journal::Sink >
beast::insight::NullCollector::New
static std::shared_ptr< Collector > New()
Definition: NullCollector.cpp:152
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
beast
Definition: base_uint.h:646
std::chrono