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{*this,
150  envconfig(),
151  std::make_unique<CheckMessageLogs>("MISMATCH ", found)};
153  auto const genesis = makeLedger({}, env, lh, 0s);
154  uint256 const dummyTxHash{1};
155  lh.builtLedger(genesis, dummyTxHash, {});
156  lh.validatedLedger(genesis, dummyTxHash);
157 
158  BEAST_EXPECT(!found);
159  }
160 
161  // Close time mismatch
162  {
163  bool found = false;
164  Env env{*this,
165  envconfig(),
166  std::make_unique<CheckMessageLogs>(
167  "MISMATCH on close time", found)};
169  auto const genesis = makeLedger({}, env, lh, 0s);
170  auto const ledgerA = makeLedger(genesis, env, lh, 4s);
171  auto const ledgerB = makeLedger(genesis, env, lh, 40s);
172 
173  uint256 const dummyTxHash{1};
174  lh.builtLedger(ledgerA, dummyTxHash, {});
175  lh.validatedLedger(ledgerB, dummyTxHash);
176 
177  BEAST_EXPECT(found);
178  }
179 
180  // Prior ledger mismatch
181  {
182  bool found = false;
183  Env env{*this,
184  envconfig(),
185  std::make_unique<CheckMessageLogs>(
186  "MISMATCH on prior ledger", found)};
188  auto const genesis = makeLedger({}, env, lh, 0s);
189  auto const ledgerA = makeLedger(genesis, env, lh, 4s);
190  auto const ledgerB = makeLedger(genesis, env, lh, 40s);
191  auto const ledgerAC = makeLedger(ledgerA, env, lh, 4s);
192  auto const ledgerBD = makeLedger(ledgerB, env, lh, 4s);
193 
194  uint256 const dummyTxHash{1};
195  lh.builtLedger(ledgerAC, dummyTxHash, {});
196  lh.validatedLedger(ledgerBD, dummyTxHash);
197 
198  BEAST_EXPECT(found);
199  }
200 
201  // Simulate a bug in which consensus may agree on transactions, but
202  // somehow generate different ledgers
203  for (bool const txBug : {true, false})
204  {
205  std::string const msg = txBug
206  ? "MISMATCH with same consensus transaction set"
207  : "MISMATCH on consensus transaction set";
208  bool found = false;
209  Env env{*this,
210  envconfig(),
211  std::make_unique<CheckMessageLogs>(msg, found)};
213 
214  Account alice{"A1"};
215  Account bob{"A2"};
216  env.fund(XRP(1000), alice, bob);
217  env.close();
218 
219  auto const ledgerBase =
221 
222  JTx txAlice = env.jt(noop(alice));
223  auto const ledgerA =
224  makeLedger(ledgerBase, env, lh, 4s, txAlice.stx);
225 
226  JTx txBob = env.jt(noop(bob));
227  auto const ledgerB = makeLedger(ledgerBase, env, lh, 4s, txBob.stx);
228 
229  lh.builtLedger(ledgerA, txAlice.stx->getTransactionID(), {});
230  // Simulate the bug by claiming ledgerB had the same consensus hash
231  // as ledgerA, but somehow generated different ledgers
232  lh.validatedLedger(
233  ledgerB,
234  txBug ? txAlice.stx->getTransactionID()
235  : txBob.stx->getTransactionID());
236 
237  BEAST_EXPECT(found);
238  }
239  }
240 
241  void
242  run() override
243  {
245  }
246 };
247 
249 
250 } // namespace test
251 } // namespace ripple
beast::Journal::Sink
Abstraction for the underlying message destination.
Definition: Journal.h:76
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:32
sstream
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:109
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:49
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:37
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:118
ripple::test::LedgerHistory_test::run
void run() override
Definition: LedgerHistory_test.cpp:242
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:431
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:143
ripple::test::LedgerHistory_test::CheckMessageLogs::found_
bool & found_
Definition: LedgerHistory_test.cpp:42
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:237
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:52
ripple::hotTRANSACTION_NODE
@ hotTRANSACTION_NODE
Definition: NodeObject.h:38
ripple::LedgerHistory
Retains historical ledgers.
Definition: LedgerHistory.h:34
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:33
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:422
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:54
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:52
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:463
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:89
ripple::Logs::threshold
beast::severities::Severity threshold() const
Definition: Log.cpp:146
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:98
beast::severities::Severity
Severity
Severity level / threshold of a Journal message.
Definition: Journal.h:32
ripple::test::jtx::Env::close
void close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:114
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:214
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:37
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:140
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
beast
Definition: base_uint.h:582
std::chrono